-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathoperation.js
More file actions
119 lines (100 loc) · 3.75 KB
/
operation.js
File metadata and controls
119 lines (100 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
const _ = require('lodash')
const getAjv = require('./z-schema')
const Parameter = require('./parameter')
const helpers = require('./helpers')
// addtional __data__ field can used with isSwitchOn to return addtional data in unit test
const ajv = getAjv()
class Operation {
constructor (method, definition, parent, pathToDefinition) {
this.method = method
this.definition = definition
this.parent = parent
this.pathToDefinition = pathToDefinition
_.assign(this, definition)
this.parameterObjects = _.map(definition.parameters, (parameterDef, index) => {
return new Parameter(parameterDef, this, pathToDefinition.concat(['parameters', index]))
})
this.consumes = this.consumes || parent.parent.consumes || []
this.validates = {}
}
validateContentType (contentType, supportedTypes) {
const rawContentType = contentType
if (!_.isUndefined(contentType)) {
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
contentType = contentType.split(';')[0] // Strip the parameter(s) from the content type
}
// Check for exact match or mime-type only match
if (_.indexOf(supportedTypes, rawContentType) === -1 && _.indexOf(supportedTypes, contentType) === -1) {
return {
code: 'INVALID_CONTENT_TYPE',
message: 'Invalid Content-Type (' + contentType + '). These are supported: ' +
supportedTypes.join(', '),
path: []
}
}
}
validateRequest (req) {
const results = {
errors: [],
warnings: []
}
// Validate the Content-Type but only for POST and PUT (The rest do not have bodies)
if (['post', 'put'].indexOf(this.method) > -1 && req.body && Object.keys(req.body).length) {
const error = this.validateContentType(helpers.getContentType(req.headers), this.consumes)
if (error) {
results.errors.push(error)
}
}
// Validate the parameters
_.each(this.parameterObjects, (param) => {
const paramValue = param.getValue(req)
let vErr
if (paramValue.valid) {
param.setValue(req, paramValue.value)
} else {
vErr = {
code: 'INVALID_REQUEST_PARAMETER',
errors: paramValue.error.errors || [
{
code: paramValue.error.code,
message: paramValue.error.message,
path: paramValue.error.path
}
],
in: paramValue.parameterObject.in,
// Report the actual error if there is only one error. Otherwise, report a JSON Schema validation error.
message: 'Invalid parameter (' + param.name + '): ' + ((paramValue.errors || []).length > 1
? 'Value failed JSON Schema validation' : paramValue.error.message),
name: paramValue.parameterObject.name,
path: paramValue.error.path
}
results.errors.push(vErr)
}
})
return results
}
validateResponse (req, res, obj) {
if (req.method.toLowerCase() === 'head') {
return
}
const maybeStatusCode = res ? String(res.statusCode) : 'default'
let responseDef = _.find(this.definition.responses, (response, responseCode) => {
return responseCode === maybeStatusCode
})
let realStatusCode = maybeStatusCode
if (!responseDef) {
realStatusCode = 'default'
responseDef = this.definition.responses.default
}
this.validates[realStatusCode] = this.validates[realStatusCode] || ajv.compile(responseDef.schema)
if (responseDef && typeof responseDef === 'object') {
// clone original obj
const data = helpers.prune(JSON.parse(JSON.stringify(obj)))
const valid = this.validates[realStatusCode](data)
if (!valid) {
return this.validates[realStatusCode].errors
}
}
}
}
module.exports = Operation