UNPKG

4 kBJavaScriptView Raw
1'use strict'
2
3const COLLECTION_FORMAT = {
4 CSV: ',',
5 SSV: ' ',
6 TSV: '\t',
7 PIPES: '|',
8 MULTI: '&' // multi query param instances foo=bar&foo=baz
9}
10
11exports.COLLECTION_FORMAT = COLLECTION_FORMAT
12exports.formatGroupData = formatGroupData
13exports.getPathParams = getPathParams
14exports.getFormData = getFormData
15
16function formatGroupData(groupSchema, groupData, groupId, req) {
17 const paramNames = Object.keys(groupSchema.properties)
18 if (!groupData) groupData = {}
19 const origGroupData = getOriginalGroup(req, groupId)
20 const reqParams = getReqParams(req, groupId)
21 paramNames.forEach(name => {
22 const paramSchema = groupSchema.properties[name]
23 let val = groupData[name]
24 val = parseCollectionFormat(paramSchema, val)
25 val = parseBoolean(paramSchema, val)
26 val = parseNumber(paramSchema, val)
27 val = applyDefaultValue(paramSchema, val)
28 origGroupData[name] = groupData[name] = val
29 if (reqParams && reqParams[name] !== undefined) {
30 reqParams[name] = val
31 }
32 })
33 return groupData
34}
35
36function parseCollectionFormat(paramSchema, value) {
37 if (paramSchema.type === 'array' && typeof value === 'string') {
38 return stringValueToArray(value, paramSchema.collectionFormat || 'csv')
39 }
40 return value
41}
42
43function parseBoolean(paramSchema, value) {
44 if (paramSchema.type === 'boolean') {
45 switch(`${value}`.toLowerCase().trim()) {
46 case 'true':
47 case '1':
48 case 'on':
49 case 'yes':
50 case 'y':
51 return true
52 default:
53 return false
54 }
55 }
56 return value
57}
58
59function parseNumber(paramSchema, value) {
60 if ((paramSchema.type === 'integer' || paramSchema.type === 'number') && value !== '') {
61 const num = Number(value)
62 if (!isNaN(num)) return num
63 }
64 return value
65}
66
67function stringValueToArray(value, format) {
68 const delimiter = COLLECTION_FORMAT[format.toUpperCase()] || COLLECTION_FORMAT.CSV
69 return value.split(delimiter)
70}
71
72function applyDefaultValue(paramSchema, value) {
73 return (value === undefined && !paramSchema.required) ? paramSchema.default : value
74}
75
76function getPathParams(req, operation) {
77 const params = req.params ? req.params : req.params = {}
78 if (req.app) return params // express
79
80 // restify
81 // req.params may contain a mix of more than just path parameters
82 // as restify has the option to merge body and query params in here too.
83 // This forces us to pull out just the ones defined in the swagger spec.
84 // Note that this means we can't later determine if the client has sent
85 // extra path parameters so validation around this is not possible.
86
87 return operation.parameters
88 .filter(op => op.in === 'path')
89 .reduce((pathParams, op) => {
90 if (params[op.name] !== undefined) {
91 pathParams[op.name] = params[op.name]
92 }
93 return pathParams
94 }, {})
95}
96
97function getFormData(req) {
98 if (req.accepts('multipart/form-data') || req.accepts('application/x-www-form-urlencoded')) {
99 const formData = Object.assign({}, req.body)
100 if (Array.isArray(req.files)) {
101 req.files.forEach(file => {
102 formData[file.filename] = file
103 })
104 } else if (req.files && typeof req.files === 'object') {
105 Object.assign(formData, req.files)
106 }
107 else if (req.file && typeof req.files === 'object') {
108 formData[req.file.filename] = req.file
109 }
110 return formData
111 }
112 return null
113}
114
115function getOriginalGroup(req, groupId) {
116 switch (groupId) {
117 case 'header': return req.headers || {}
118 case 'path': return req.params || {}
119 case 'query': return (typeof req.query === 'function') ? {} : req.query || {}
120 case 'body':
121 case 'formData': return req.body || {}
122 default: return {}
123 }
124}
125
126/*
127 * If using Restify, grab the common params object.
128 * We'll merge back formatted query and path params
129 * if they existed unformatted in there previously.
130 */
131function getReqParams(req, groupId) {
132 return (req && !req.app && (groupId === 'query' || groupId === 'path'))
133 ? req.params
134 : undefined
135}