Skip to content

Commit 9197266

Browse files
authored
Merge branch 'master' into bug/1184-rfc3986-query-param-value-escaping
2 parents 89914bd + da237e5 commit 9197266

File tree

7 files changed

+194
-35
lines changed

7 files changed

+194
-35
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swagger-client",
3-
"version": "3.3.4",
3+
"version": "3.3.5",
44
"description": "SwaggerJS - a collection of interfaces for OAI specs",
55
"main": "dist/index.js",
66
"repository": "[email protected]:swagger-api/swagger-js.git",

src/execute/index.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export function buildRequest(options) {
104104

105105
// Base Template
106106
let req = {
107-
url: baseUrl({spec, scheme, contextUrl, server, serverVariables}),
107+
url: '',
108108
credentials: 'same-origin',
109109
headers: {
110110
// This breaks CORSs... removing this line... probably breaks oAuth. Need to address that
@@ -124,6 +124,15 @@ export function buildRequest(options) {
124124
req.userFetch = userFetch
125125
}
126126

127+
const operationRaw = getOperationRaw(spec, operationId)
128+
if (!operationRaw) {
129+
throw new OperationNotFoundError(`Operation ${operationId} not found`)
130+
}
131+
132+
const {operation = {}, method, pathName} = operationRaw
133+
134+
req.url += baseUrl({spec, scheme, contextUrl, server, serverVariables, pathName, method})
135+
127136
// Mostly for testing
128137
if (!operationId) {
129138
// Not removing req.cookies causes testing issues and would
@@ -134,13 +143,6 @@ export function buildRequest(options) {
134143
return req
135144
}
136145

137-
const operationRaw = getOperationRaw(spec, operationId)
138-
if (!operationRaw) {
139-
throw new OperationNotFoundError(`Operation ${operationId} not found`)
140-
}
141-
142-
const {operation = {}, method, pathName} = operationRaw
143-
144146
req.url += pathName // Have not yet replaced the path parameters
145147
req.method = (`${method}`).toUpperCase()
146148

@@ -240,8 +242,11 @@ export function baseUrl(obj) {
240242
return specIsOAS3 ? oas3BaseUrl(obj) : swagger2BaseUrl(obj)
241243
}
242244

243-
function oas3BaseUrl({spec, server, contextUrl, serverVariables = {}}) {
244-
const servers = spec.servers
245+
function oas3BaseUrl({spec, pathName, method, server, contextUrl, serverVariables = {}}) {
246+
const servers =
247+
getIn(spec, ['paths', pathName, (method || '').toLowerCase(), 'servers']) ||
248+
getIn(spec, ['paths', pathName, 'servers']) ||
249+
getIn(spec, ['servers'])
245250

246251
let selectedServerUrl = ''
247252
let selectedServerObj = null

src/execute/oas3/build-request.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export default function (options, req) {
5151
Object.keys(requestBody).forEach((k) => {
5252
const val = requestBody[k]
5353
req.form[k] = {
54-
value: val
54+
value: typeof val === 'object' ? JSON.stringify(val) : val
5555
}
5656
})
5757
}

src/specmap/index.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class SpecMap {
8383
// We might consider making this (traversing & application) configurable later.
8484
function createKeyBasedPlugin(pluginObj) {
8585
return function* (patches, specmap) {
86+
const traversedRefs = {}
87+
8688
for (const patch of patches.filter(lib.isAdditiveMutation)) {
8789
yield* traverse(patch.value, patch.path, patch)
8890
}
@@ -102,9 +104,21 @@ class SpecMap {
102104
for (const key of Object.keys(obj)) {
103105
const val = obj[key]
104106
const updatedPath = path.concat(key)
105-
106-
if (lib.isObject(val)) {
107-
yield* traverse(val, updatedPath, patch)
107+
const isObj = lib.isObject(val)
108+
109+
// If the object has a meta '$$ref' - and store this $$ref
110+
// in a lookaside to prevent future traversals of this $ref's tree.
111+
const objRef = obj.$$ref
112+
const traversed = specmap.allowMetaPatches && traversedRefs[obj.$$ref]
113+
114+
if (!traversed) {
115+
if (isObj) {
116+
// Only store the ref if it exists
117+
if (specmap.allowMetaPatches && objRef) {
118+
traversedRefs[objRef] = true
119+
}
120+
yield* traverse(val, updatedPath, patch)
121+
}
108122
}
109123

110124
if (!isRootProperties && key === pluginObj.key) {

test.js

Whitespace-only changes.

test/execute/main.js

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,37 +37,27 @@ describe('execute', () => {
3737
})
3838
})
3939

40-
it('should include host + http + baseUrl', function () {
41-
// Given
42-
const spec = {
43-
host: 'swagger.io',
44-
basePath: '/v1',
45-
}
46-
47-
// When
48-
const req = buildRequest({spec})
49-
50-
// Then
51-
expect(req).toEqual({
52-
url: 'http://swagger.io/v1',
53-
credentials: 'same-origin',
54-
headers: { }
55-
})
56-
})
57-
5840
it('should include host + port', function () {
5941
// Given
6042
const spec = {
6143
host: 'foo.com:8081',
6244
basePath: '/v1',
45+
paths: {
46+
'/': {
47+
get: {
48+
operationId: 'foo'
49+
}
50+
}
51+
}
6352
}
6453

6554
// When
66-
const req = buildRequest({spec})
55+
const req = buildRequest({spec, operationId: 'foo'})
6756

6857
// Then
6958
expect(req).toEqual({
70-
url: 'http://foo.com:8081/v1',
59+
url: 'http://foo.com:8081/v1/',
60+
method: 'GET',
7161
credentials: 'same-origin',
7262
headers: { }
7363
})

test/oas3/execute/main.js

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,58 @@ describe('buildRequest - OpenAPI Specification 3.0', function () {
169169
})
170170
})
171171

172+
it('should stringify object values of form data bodies', function () {
173+
// Given
174+
const spec = {
175+
openapi: '3.0.0',
176+
servers: [
177+
{
178+
url: 'http://petstore.swagger.io/v2',
179+
name: 'Petstore'
180+
}
181+
],
182+
paths: {
183+
'/one': {
184+
get: {
185+
operationId: 'getOne',
186+
requestBody: {
187+
content: {
188+
'application/x-www-form-urlencoded': {
189+
schema: {
190+
type: 'object'
191+
}
192+
}
193+
}
194+
}
195+
}
196+
}
197+
}
198+
}
199+
200+
// when
201+
const req = buildRequest({
202+
spec,
203+
operationId: 'getOne',
204+
requestBody: {
205+
a: 1,
206+
b: {
207+
c: 3,
208+
d: 4
209+
}
210+
}
211+
})
212+
213+
expect(req).toEqual({
214+
method: 'GET',
215+
url: 'http://petstore.swagger.io/v2/one',
216+
credentials: 'same-origin',
217+
headers: {
218+
'Content-Type': 'application/x-www-form-urlencoded'
219+
},
220+
body: 'a=1&b=%7B%22c%22%3A3%2C%22d%22%3A4%7D'
221+
})
222+
})
223+
172224
it('should build a request for the given operationId with a requestBody, and not be overriden by an invalid Swagger2 body parameter value', function () {
173225
// Given
174226
const spec = {
@@ -419,6 +471,104 @@ describe('buildRequest - OpenAPI Specification 3.0', function () {
419471

420472
expect(res).toEqual('https://petstore.net')
421473
})
474+
it('should use an explicitly chosen server at the operation level', function () {
475+
const spec = {
476+
openapi: '3.0.0',
477+
servers: [
478+
{
479+
url: 'https://petstore.com'
480+
},
481+
{
482+
url: 'https://petstore.net'
483+
}
484+
],
485+
paths: {
486+
'/': {
487+
get: {
488+
servers: [
489+
{
490+
url: 'https://petstore-operation.net/{path}',
491+
variables: {
492+
path: {
493+
default: 'foobar'
494+
}
495+
}
496+
}
497+
]
498+
}
499+
}
500+
}
501+
}
502+
503+
const res = baseUrl({
504+
spec,
505+
server: 'https://petstore-operation.net/{path}',
506+
pathName: '/',
507+
method: 'GET'
508+
})
509+
510+
const resWithVariables = baseUrl({
511+
spec,
512+
server: 'https://petstore-operation.net/{path}',
513+
serverVariables: {
514+
path: 'fizzbuzz'
515+
},
516+
pathName: '/',
517+
method: 'GET'
518+
})
519+
520+
expect(res).toEqual('https://petstore-operation.net/foobar')
521+
expect(resWithVariables).toEqual('https://petstore-operation.net/fizzbuzz')
522+
})
523+
524+
it('should use an explicitly chosen server at the path level', function () {
525+
const spec = {
526+
openapi: '3.0.0',
527+
servers: [
528+
{
529+
url: 'https://petstore.com'
530+
},
531+
{
532+
url: 'https://petstore.net'
533+
}
534+
],
535+
paths: {
536+
'/': {
537+
servers: [
538+
{
539+
url: 'https://petstore-path.net/{path}',
540+
variables: {
541+
path: {
542+
default: 'foobar'
543+
}
544+
}
545+
}
546+
],
547+
get: {}
548+
}
549+
}
550+
}
551+
552+
const res = baseUrl({
553+
spec,
554+
server: 'https://petstore-path.net/{path}',
555+
pathName: '/',
556+
method: 'GET'
557+
})
558+
559+
const resWithVariables = baseUrl({
560+
spec,
561+
server: 'https://petstore-path.net/{path}',
562+
serverVariables: {
563+
path: 'fizzbuzz'
564+
},
565+
pathName: '/',
566+
method: 'GET'
567+
})
568+
569+
expect(res).toEqual('https://petstore-path.net/foobar')
570+
expect(resWithVariables).toEqual('https://petstore-path.net/fizzbuzz')
571+
})
422572
it('should not use an explicitly chosen server that is not present in the spec', function () {
423573
const spec = {
424574
openapi: '3.0.0',

0 commit comments

Comments
 (0)