Skip to content

Commit 88bc442

Browse files
committed
Tests and supporting changes
1 parent 0663b35 commit 88bc442

File tree

5 files changed

+1115
-393
lines changed

5 files changed

+1115
-393
lines changed

src/execute.js

Lines changed: 105 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ 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} from './helpers'
8+
import {getOperationRaw, idFromPathMethod, legacyIdFromPathMethod, isOAS3} from './helpers'
99
import createError from './specmap/lib/create-error'
1010

1111
const arrayOrEmpty = (ar) => {
@@ -25,8 +25,7 @@ export const self = {
2525
// These functions will update the request.
2626
// They'll be given {req, value, paramter, spec, operation}.
2727

28-
// TODO: OAS3: add builder for requestBody
29-
// QUESTION: OAS3: how do we decide which media type to use from a requestBody?
28+
3029
export const PARAMETER_BUILDERS = {
3130
body: bodyBuilder,
3231
header: headerBuilder,
@@ -69,13 +68,16 @@ export function execute({
6968
export function buildRequest({
7069
spec, operationId, parameters, securities, requestContentType,
7170
responseContentType, parameterBuilders, scheme,
72-
requestInterceptor, responseInterceptor, contextUrl, userFetch
71+
requestInterceptor, responseInterceptor, contextUrl, userFetch,
72+
requestBody, server, serverVariables
7373
}) {
74+
const specIsOAS3 = isOAS3(spec)
75+
7476
parameterBuilders = parameterBuilders || PARAMETER_BUILDERS
7577

7678
// Base Template
7779
let req = {
78-
url: baseUrl({spec, scheme, contextUrl}),
80+
url: baseUrl({spec, scheme, contextUrl, server, serverVariables}),
7981
credentials: 'same-origin',
8082
headers: {
8183
// This breaks CORSs... removing this line... probably breaks oAuth. Need to address that
@@ -141,30 +143,54 @@ export function buildRequest({
141143
}
142144

143145
if (builder) {
144-
builder({req, parameter, value, operation, spec})
146+
builder({req, parameter, value, operation, spec, specIsOAS3})
145147
}
146148
})
147149

150+
// for OAS3: add requestBody to request
151+
if (specIsOAS3 && requestBody) {
152+
if (requestContentType) {
153+
const requestBodyDef = operation.requestBody
154+
const requestBodyMediaTypes = Object.keys(requestBodyDef.content || {})
155+
if (requestBodyMediaTypes.indexOf(requestContentType) > -1) {
156+
// only attach body if the requestBody has a definition for the
157+
// contentType that has been explicitly set
158+
req.body = requestBody
159+
}
160+
}
161+
else {
162+
req.body = requestBody
163+
}
164+
}
165+
148166
// Add securities, which are applicable
149167
// REVIEW: OAS3: what changed in securities?
150168
req = applySecurities({request: req, securities, operation, spec})
151169

152170
if (req.body || req.form) {
153171
if (requestContentType) {
154-
req.headers['content-type'] = requestContentType
172+
req.headers['Content-Type'] = requestContentType
155173
}
174+
else if (specIsOAS3) {
175+
const requestBodyDef = operation.requestBody
176+
const requestBodyMediaTypes = Object.keys(requestBodyDef.content || {})
177+
const firstMediaType = requestBodyMediaTypes[0]
178+
if (firstMediaType) {
179+
req.headers['Content-Type'] = firstMediaType
180+
}
181+
}
182+
// all following conditionals are Swagger2 only
156183
else if (Array.isArray(operation.consumes)) {
157-
req.headers['content-type'] = operation.consumes[0]
184+
req.headers['Content-Type'] = operation.consumes[0]
158185
}
159186
else if (Array.isArray(spec.consumes)) {
160-
req.headers['content-type'] = spec.consumes[0]
187+
req.headers['Content-Type'] = spec.consumes[0]
161188
}
162-
else if (operation.parameters.filter(p => p.type === 'file').length) {
163-
req.headers['content-type'] = 'multipart/form-data'
189+
else if (operation.parameters && operation.parameters.filter(p => p.type === 'file').length) {
190+
req.headers['Content-Type'] = 'multipart/form-data'
164191
}
165-
else if (operation.parameters.filter(p => p.in === 'formData').length) {
166-
// TODO: OAS3: disable this
167-
req.headers['content-type'] = 'application/x-www-form-urlencoded'
192+
else if (operation.parameters && operation.parameters.filter(p => p.in === 'formData').length) {
193+
req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
168194
}
169195
}
170196

@@ -176,8 +202,10 @@ export function buildRequest({
176202
}
177203

178204
// Add the body to the request
179-
export function bodyBuilder({req, value}) {
180-
// REVIEW: OAS3: wtf does this do
205+
export function bodyBuilder({req, value, specIsOAS3}) {
206+
if (specIsOAS3) {
207+
return
208+
}
181209
req.body = value
182210
}
183211

@@ -237,8 +265,68 @@ export function queryBuilder({req, value, parameter}) {
237265

238266
const stripNonAlpha = str => (str ? str.replace(/\W/g, '') : null)
239267

268+
export function baseUrl(obj) {
269+
const specIsOAS3 = isOAS3(obj.spec)
270+
271+
return specIsOAS3 ? oas3BaseUrl(obj) : swagger2BaseUrl(obj)
272+
}
273+
274+
function oas3BaseUrl({spec, server, serverVariables = {}}) {
275+
const servers = spec.servers
276+
277+
let selectedServerUrl = ''
278+
let selectedServerObj = null
279+
280+
if (!servers || !Array.isArray(servers)) {
281+
return '/'
282+
}
283+
284+
if (server) {
285+
const serverUrls = servers.map(srv => srv.url)
286+
287+
if(serverUrls.indexOf(server) > -1) {
288+
selectedServerUrl = server
289+
selectedServerObj = servers[serverUrls.indexOf(server)]
290+
}
291+
}
292+
293+
if (!selectedServerUrl) {
294+
// default to the first server if we don't have one by now
295+
selectedServerUrl = servers[0].url
296+
selectedServerObj = servers[0]
297+
}
298+
299+
if (selectedServerUrl.indexOf('{') > -1) {
300+
// do variable substitution
301+
const varNames = getVariableTemplateNames(selectedServerUrl)
302+
varNames.forEach((vari) => {
303+
if (selectedServerObj.variables && selectedServerObj.variables[vari]) {
304+
// variable is defined in server
305+
const variableDefinition = selectedServerObj.variables[vari]
306+
const variableValue = serverVariables[vari] || variableDefinition.default
307+
308+
const re = new RegExp(`\{${vari}\}`,"g")
309+
selectedServerUrl = selectedServerUrl.replace(re, variableValue)
310+
}
311+
})
312+
}
313+
314+
return selectedServerUrl
315+
}
316+
317+
function getVariableTemplateNames(str) {
318+
const results = []
319+
const re = /{([^}]+)}/g
320+
let text
321+
322+
while (text = re.exec(str)) {
323+
results.push(text[1])
324+
}
325+
return results
326+
}
327+
240328
// Compose the baseUrl ( scheme + host + basePath )
241-
export function baseUrl({spec, scheme, contextUrl = ''}) {
329+
function swagger2BaseUrl({spec, scheme, contextUrl = ''}) {
242330
// TODO: OAS3: support `servers` instead of host+basePath
243331
// QUESTION: OAS3: how are we handling `servers`?
244332
// QUESTION: OAS3: are we still doing assumed URL components the same way?

test/oas3/client.js

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -67,46 +67,16 @@ describe('http - OpenAPI Specification 3.0', () => {
6767
expect(client).toExist()
6868

6969
// we have 3 tags
70-
expect(Object.keys(client.apis).length).toBe(1)
70+
expect(Object.keys(client.apis).length).toBe(3)
7171

7272
// the pet tag exists
73-
expect(client.apis.pets).toExist()
73+
expect(client.apis.pet).toExist()
7474

7575
// the get pet operation
76-
expect(client.apis.pets.getPetById).toExist()
76+
expect(client.apis.pet.getPetById).toExist()
7777

7878
done()
7979
})
80-
.catch(e => done (e))
81-
})
82-
83-
/**
84-
* See https://github.com/swagger-api/swagger-js/issues/1005
85-
*/
86-
it('should get a pet from the petstore', (done) => {
87-
Swagger('http://localhost:8000/petstore-oas3.yaml')
88-
.then((client) => {
89-
client.apis.pets.getPetById({petId: -1})
90-
.then((data) => {
91-
done()
92-
})
93-
.catch((err) => {
94-
done(err)
95-
})
96-
})
97-
.catch(e => done (e))
98-
})
99-
100-
/**
101-
* See https://github.com/swagger-api/swagger-js/issues/1002
102-
*/
103-
it('should return an error when a spec doesnt exist', (done) => {
104-
Swagger('http://localhost:8000/not-real.yaml')
105-
.then((client) => {
106-
done('expected an error')
107-
})
108-
.catch((error) => {
109-
done()
110-
})
80+
.catch(e => done(e))
11181
})
11282
})

0 commit comments

Comments
 (0)