Skip to content

Commit e114650

Browse files
committed
Working path parameters
1 parent a521649 commit e114650

File tree

5 files changed

+190
-82
lines changed

5 files changed

+190
-82
lines changed

src/execute/index.js

Lines changed: 17 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,15 @@ import isArray from 'lodash/isArray'
55
import btoa from 'btoa'
66
import url from 'url'
77
import http, {mergeInQueryOrForm} from '../http'
8-
import {getOperationRaw, idFromPathMethod, legacyIdFromPathMethod, isOAS3} from '../helpers'
98
import createError from '../specmap/lib/create-error'
9+
import SWAGGER2_PARAMETER_BUILDERS from './swagger2-parameter-builders'
10+
import OAS3_PARAMETER_BUILDERS from './oas3-parameter-builders'
11+
import {
12+
getOperationRaw,
13+
idFromPathMethod,
14+
legacyIdFromPathMethod,
15+
isOAS3
16+
} from '../helpers'
1017

1118
const arrayOrEmpty = (ar) => {
1219
return Array.isArray(ar) ? ar : []
@@ -26,18 +33,6 @@ export const self = {
2633
buildRequest
2734
}
2835

29-
// These functions will update the request.
30-
// They'll be given {req, value, paramter, spec, operation}.
31-
32-
33-
export const PARAMETER_BUILDERS = {
34-
body: bodyBuilder,
35-
header: headerBuilder,
36-
query: queryBuilder,
37-
path: pathBuilder,
38-
formData: formDataBuilder
39-
}
40-
4136
// Execute request, with the given operationId and parameters
4237
// pathName/method or operationId is optional
4338
export function execute({
@@ -77,7 +72,15 @@ export function buildRequest({
7772
}) {
7873
const specIsOAS3 = isOAS3(spec)
7974

80-
parameterBuilders = parameterBuilders || PARAMETER_BUILDERS
75+
if (!parameterBuilders) {
76+
// user did not provide custom parameter builders
77+
if (specIsOAS3) {
78+
parameterBuilders = OAS3_PARAMETER_BUILDERS
79+
}
80+
else {
81+
parameterBuilders = SWAGGER2_PARAMETER_BUILDERS
82+
}
83+
}
8184

8285
// Base Template
8386
let req = {
@@ -246,68 +249,6 @@ export function buildRequest({
246249
return req
247250
}
248251

249-
// Add the body to the request
250-
export function bodyBuilder({req, value, specIsOAS3}) {
251-
if (specIsOAS3) {
252-
return
253-
}
254-
req.body = value
255-
}
256-
257-
// Add a form data object.
258-
export function formDataBuilder({req, value, parameter}) {
259-
// REVIEW: OAS3: check for any parameter changes that affect the builder
260-
req.form = req.form || {}
261-
if (value || parameter.allowEmptyValue) {
262-
req.form[parameter.name] = {
263-
value,
264-
allowEmptyValue: parameter.allowEmptyValue,
265-
collectionFormat: parameter.collectionFormat,
266-
}
267-
}
268-
}
269-
270-
// Add a header to the request
271-
export function headerBuilder({req, parameter, value}) {
272-
// REVIEW: OAS3: check for any parameter changes that affect the builder
273-
req.headers = req.headers || {}
274-
if (typeof value !== 'undefined') {
275-
req.headers[parameter.name] = value
276-
}
277-
}
278-
279-
// Replace path paramters, with values ( ie: the URL )
280-
export function pathBuilder({req, value, parameter}) {
281-
// REVIEW: OAS3: check for any parameter changes that affect the builder
282-
req.url = req.url.replace(`{${parameter.name}}`, encodeURIComponent(value))
283-
}
284-
285-
// Add a query to the `query` object, which will later be stringified into the URL's search
286-
export function queryBuilder({req, value, parameter}) {
287-
// REVIEW: OAS3: check for any parameter changes that affect the builder
288-
req.query = req.query || {}
289-
290-
if (value === false && parameter.type === 'boolean') {
291-
value = 'false'
292-
}
293-
294-
if (value === 0 && ['number', 'integer'].indexOf(parameter.type) > -1) {
295-
value = '0'
296-
}
297-
298-
if (value) {
299-
req.query[parameter.name] = {
300-
collectionFormat: parameter.collectionFormat,
301-
value
302-
}
303-
}
304-
else if (parameter.allowEmptyValue) {
305-
const paramName = parameter.name
306-
req.query[paramName] = req.query[paramName] || {}
307-
req.query[paramName].allowEmptyValue = true
308-
}
309-
}
310-
311252
const stripNonAlpha = str => (str ? str.replace(/\W/g, '') : null)
312253

313254
export function baseUrl(obj) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import stylize from './oas3-style-serializer'
2+
export default {
3+
path
4+
}
5+
6+
function path({req, value, parameter}) {
7+
const {name, style, explode} = parameter
8+
const styledValue = stylize({
9+
key: parameter.name,
10+
value,
11+
style: style || 'simple',
12+
explode: explode || false,
13+
})
14+
15+
req.url = req.url.replace(`{${name}}`, styledValue)
16+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
export default function (config) {
2+
const {value} = config
3+
4+
if (Array.isArray(value)) {
5+
return encodeArray(config)
6+
}
7+
else if (typeof value === 'object') {
8+
return encodeObject(config)
9+
}
10+
11+
return encodePrimitive(config)
12+
}
13+
14+
function encodeArray({key, value, style, explode}) {
15+
if (style === 'simple') {
16+
return value.join(',')
17+
}
18+
if (style === 'label') {
19+
return `.${value.join('.')}`
20+
}
21+
if (style === 'matrix') {
22+
return value.reduce((prev, curr) => {
23+
if (!prev || explode) {
24+
return `${(prev || '')};${key}=${curr}`
25+
}
26+
return prev + `,${curr}`
27+
}, '')
28+
}
29+
}
30+
31+
function encodeObject({key, value, style, explode}) {
32+
const valueKeys = Object.keys(value)
33+
34+
if (style === 'simple') {
35+
return valueKeys.reduce((prev, curr) => {
36+
const val = value[curr]
37+
const middleChar = explode ? '=' : ','
38+
const prefix = prev ? `${prev},` : ''
39+
40+
return `${prefix}${curr}${middleChar}${val}`
41+
}, '')
42+
}
43+
44+
if (style === 'label') {
45+
return valueKeys.reduce((prev, curr) => {
46+
const val = value[curr]
47+
const middleChar = explode ? '=' : '.'
48+
const prefix = prev ? `${prev}.` : '.'
49+
50+
return `${prefix}${curr}${middleChar}${val}`
51+
}, '')
52+
}
53+
54+
if (style === 'matrix' && explode) {
55+
return valueKeys.reduce((prev, curr) => {
56+
const val = value[curr]
57+
const prefix = prev ? `${prev};` : ';'
58+
59+
return `${prefix}${curr}=${val}`
60+
}, '')
61+
}
62+
63+
if (style === 'matrix') {
64+
// no explode
65+
return valueKeys.reduce((prev, curr) => {
66+
const val = value[curr]
67+
const prefix = prev ? `${prev},` : `;${key}=`
68+
69+
return `${prefix}${curr},${val}`
70+
}, '')
71+
}
72+
}
73+
74+
function encodePrimitive({key, value, style, explode}) {
75+
if (style === 'simple') {
76+
return value
77+
}
78+
if (style === 'label') {
79+
return `.${value}`
80+
}
81+
if (style === 'matrix') {
82+
return `;${key}=${value}`
83+
}
84+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// These functions will update the request.
2+
// They'll be given {req, value, paramter, spec, operation}.
3+
4+
5+
export default {
6+
body: bodyBuilder,
7+
header: headerBuilder,
8+
query: queryBuilder,
9+
path: pathBuilder,
10+
formData: formDataBuilder
11+
}
12+
13+
14+
// Add the body to the request
15+
function bodyBuilder({req, value}) {
16+
req.body = value
17+
}
18+
19+
// Add a form data object.
20+
function formDataBuilder({req, value, parameter}) {
21+
req.form = req.form || {}
22+
if (value || parameter.allowEmptyValue) {
23+
req.form[parameter.name] = {
24+
value,
25+
allowEmptyValue: parameter.allowEmptyValue,
26+
collectionFormat: parameter.collectionFormat,
27+
}
28+
}
29+
}
30+
31+
// Add a header to the request
32+
function headerBuilder({req, parameter, value}) {
33+
req.headers = req.headers || {}
34+
if (typeof value !== 'undefined') {
35+
req.headers[parameter.name] = value
36+
}
37+
}
38+
39+
// Replace path paramters, with values ( ie: the URL )
40+
function pathBuilder({req, value, parameter}) {
41+
req.url = req.url.replace(`{${parameter.name}}`, encodeURIComponent(value))
42+
}
43+
44+
// Add a query to the `query` object, which will later be stringified into the URL's search
45+
function queryBuilder({req, value, parameter}) {
46+
req.query = req.query || {}
47+
48+
if (value === false && parameter.type === 'boolean') {
49+
value = 'false'
50+
}
51+
52+
if (value === 0 && ['number', 'integer'].indexOf(parameter.type) > -1) {
53+
value = '0'
54+
}
55+
56+
if (value) {
57+
req.query[parameter.name] = {
58+
collectionFormat: parameter.collectionFormat,
59+
value
60+
}
61+
}
62+
else if (parameter.allowEmptyValue) {
63+
const paramName = parameter.name
64+
req.query[paramName] = req.query[paramName] || {}
65+
req.query[paramName].allowEmptyValue = true
66+
}
67+
}

test/oas3/execute/style-explode.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const petstoreSpec = jsYaml.safeLoad(fs.readFileSync(path.join('test', 'oas3', '
1111
// Supported shape... { spec, operationId, parameters, securities, fetch }
1212
// One can use operationId or pathItem + method
1313

14-
describe.skip('buildRequest w/ `style` & `explode` - OpenAPI Specification 3.0', function () {
14+
describe('buildRequest w/ `style` & `explode` - OpenAPI Specification 3.0', function () {
1515
describe('path parameters', function () {
1616
describe('primitive values', function () {
1717
it('default: should build a path parameter in a simple/no-explode format', function () {
@@ -831,7 +831,7 @@ describe.skip('buildRequest w/ `style` & `explode` - OpenAPI Specification 3.0',
831831
})
832832
})
833833
describe('query parameters', function () {
834-
describe('primitive values', function () {
834+
describe.skip('primitive values', function () {
835835
const VALUE = 5
836836

837837
it('default: should build a query parameter in form/explode format', function () {
@@ -946,7 +946,7 @@ describe.skip('buildRequest w/ `style` & `explode` - OpenAPI Specification 3.0',
946946
})
947947
})
948948
})
949-
describe('array values', function () {
949+
describe.skip('array values', function () {
950950
const VALUE = [3, 4, 5]
951951

952952
it('default: should build a query parameter in form/explode format', function () {
@@ -1213,7 +1213,7 @@ describe.skip('buildRequest w/ `style` & `explode` - OpenAPI Specification 3.0',
12131213
})
12141214
})
12151215
})
1216-
describe('object values', function () {
1216+
describe.skip('object values', function () {
12171217
const VALUE = {
12181218
role: 'admin',
12191219
firstName: 'Alex'
@@ -1332,7 +1332,7 @@ describe.skip('buildRequest w/ `style` & `explode` - OpenAPI Specification 3.0',
13321332
})
13331333
})
13341334
})
1335-
describe('header parameters', function () {
1335+
describe.skip('header parameters', function () {
13361336
describe('primitive values', function () {
13371337
const VALUE = 5
13381338

@@ -1700,7 +1700,7 @@ describe.skip('buildRequest w/ `style` & `explode` - OpenAPI Specification 3.0',
17001700
})
17011701
})
17021702
})
1703-
describe('cookie parameters', function () {
1703+
describe.skip('cookie parameters', function () {
17041704
describe('primitive values', function () {
17051705
const VALUE = 5
17061706

0 commit comments

Comments
 (0)