@@ -4,9 +4,19 @@ import isPlainObject from 'lodash/isPlainObject'
44import isArray from 'lodash/isArray'
55import btoa from 'btoa'
66import url from 'url'
7- import http , { mergeInQueryOrForm } from './http'
8- import { getOperationRaw , idFromPathMethod , legacyIdFromPathMethod , isOAS3 } from './helpers'
9- import createError from './specmap/lib/create-error'
7+ import http , { mergeInQueryOrForm } from '../http'
8+ import createError from '../specmap/lib/create-error'
9+
10+ import SWAGGER2_PARAMETER_BUILDERS from './swagger2/parameter-builders'
11+ import OAS3_PARAMETER_BUILDERS from './oas3/parameter-builders'
12+ import oas3BuildRequest from './oas3/build-request'
13+ import swagger2BuildRequest from './swagger2/build-request'
14+ import {
15+ getOperationRaw ,
16+ idFromPathMethod ,
17+ legacyIdFromPathMethod ,
18+ isOAS3
19+ } from '../helpers'
1020
1121const arrayOrEmpty = ( ar ) => {
1222 return Array . isArray ( ar ) ? ar : [ ]
@@ -26,18 +36,6 @@ export const self = {
2636 buildRequest
2737}
2838
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-
4139// Execute request, with the given operationId and parameters
4240// pathName/method or operationId is optional
4341export function execute ( {
@@ -69,15 +67,39 @@ export function execute({
6967}
7068
7169// Build a request, which can be handled by the `http.js` implementation.
72- export function buildRequest ( {
73- spec, operationId, parameters, securities, requestContentType,
74- responseContentType, parameterBuilders, scheme,
75- requestInterceptor, responseInterceptor, contextUrl, userFetch,
76- requestBody, server, serverVariables
77- } ) {
70+ export function buildRequest ( options ) {
71+ const {
72+ spec,
73+ operationId,
74+ securities,
75+ requestContentType,
76+ responseContentType,
77+ scheme,
78+ requestInterceptor,
79+ responseInterceptor,
80+ contextUrl,
81+ userFetch,
82+ requestBody,
83+ server,
84+ serverVariables
85+ } = options
86+
87+ let {
88+ parameters,
89+ parameterBuilders
90+ } = options
91+
7892 const specIsOAS3 = isOAS3 ( spec )
7993
80- parameterBuilders = parameterBuilders || PARAMETER_BUILDERS
94+ if ( ! parameterBuilders ) {
95+ // user did not provide custom parameter builders
96+ if ( specIsOAS3 ) {
97+ parameterBuilders = OAS3_PARAMETER_BUILDERS
98+ }
99+ else {
100+ parameterBuilders = SWAGGER2_PARAMETER_BUILDERS
101+ }
102+ }
81103
82104 // Base Template
83105 let req = {
@@ -165,78 +187,15 @@ export function buildRequest({
165187 }
166188 } )
167189
168- const requestBodyDef = operation . requestBody || { }
169- const requestBodyMediaTypes = Object . keys ( requestBodyDef . content || { } )
170-
171- // for OAS3: set the Content-Type
172- if ( specIsOAS3 && requestBody ) {
173- // does the passed requestContentType appear in the requestBody definition?
174- const isExplicitContentTypeValid = requestContentType
175- && requestBodyMediaTypes . indexOf ( requestContentType ) > - 1
176-
177- if ( requestContentType && isExplicitContentTypeValid ) {
178- req . headers [ 'Content-Type' ] = requestContentType
179- }
180- else if ( ! requestContentType ) {
181- const firstMediaType = requestBodyMediaTypes [ 0 ]
182- if ( firstMediaType ) {
183- req . headers [ 'Content-Type' ] = firstMediaType
184- requestContentType = firstMediaType
185- }
186- }
187- }
190+ // Do version-specific tasks, then return those results.
191+ const versionSpecificOptions = { ...options , operation}
188192
189- // for OAS3: add requestBody to request
190- if ( specIsOAS3 && requestBody ) {
191- if ( requestContentType ) {
192- if ( requestBodyMediaTypes . indexOf ( requestContentType ) > - 1 ) {
193- // only attach body if the requestBody has a definition for the
194- // contentType that has been explicitly set
195- if ( requestContentType === 'application/x-www-form-urlencoded' ) {
196- if ( typeof requestBody === 'object' ) {
197- req . form = { }
198- Object . keys ( requestBody ) . forEach ( ( k ) => {
199- const val = requestBody [ k ]
200- req . form [ k ] = {
201- value : val
202- }
203- } )
204- }
205- else {
206- req . form = requestBody
207- }
208- }
209- else {
210- req . body = requestBody
211- }
212- }
213- }
214- else {
215- req . body = requestBody
216- }
193+ if ( specIsOAS3 ) {
194+ req = oas3BuildRequest ( versionSpecificOptions , req )
217195 }
218-
219- // Add securities, which are applicable
220- // REVIEW: OAS3: what changed in securities?
221- req = applySecurities ( { request : req , securities, operation, spec} )
222-
223- if ( ! specIsOAS3 && ( req . body || req . form ) ) {
224- // all following conditionals are Swagger2 only
225- if ( requestContentType ) {
226- req . headers [ 'Content-Type' ] = requestContentType
227- }
228- else if ( Array . isArray ( operation . consumes ) ) {
229- req . headers [ 'Content-Type' ] = operation . consumes [ 0 ]
230- }
231- else if ( Array . isArray ( spec . consumes ) ) {
232- req . headers [ 'Content-Type' ] = spec . consumes [ 0 ]
233- }
234- else if ( operation . parameters && operation . parameters . filter ( p => p . type === 'file' ) . length ) {
235- req . headers [ 'Content-Type' ] = 'multipart/form-data'
236- }
237- else if ( operation . parameters && operation . parameters . filter ( p => p . in === 'formData' ) . length ) {
238- req . headers [ 'Content-Type' ] = 'application/x-www-form-urlencoded'
239- }
196+ else {
197+ // If not OAS3, then treat as Swagger2.
198+ req = swagger2BuildRequest ( versionSpecificOptions , req )
240199 }
241200
242201 // Will add the query object into the URL, if it exists
@@ -246,68 +205,6 @@ export function buildRequest({
246205 return req
247206}
248207
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-
311208const stripNonAlpha = str => ( str ? str . replace ( / \W / g, '' ) : null )
312209
313210export function baseUrl ( obj ) {
@@ -389,59 +286,3 @@ function swagger2BaseUrl({spec, scheme, contextUrl = ''}) {
389286
390287 return ''
391288}
392-
393-
394- // Add security values, to operations - that declare their need on them
395- export function applySecurities ( { request, securities = { } , operation = { } , spec} ) {
396- const result = assign ( { } , request )
397- const { authorized = { } , specSecurity = [ ] } = securities
398- const security = operation . security || specSecurity
399- const isAuthorized = authorized && ! ! Object . keys ( authorized ) . length
400- const securityDef = spec . securityDefinitions
401-
402- result . headers = result . headers || { }
403- result . query = result . query || { }
404-
405- if ( ! Object . keys ( securities ) . length || ! isAuthorized || ! security ||
406- ( Array . isArray ( operation . security ) && ! operation . security . length ) ) {
407- return request
408- }
409-
410- security . forEach ( ( securityObj , index ) => {
411- for ( const key in securityObj ) {
412- const auth = authorized [ key ]
413- if ( ! auth ) {
414- continue
415- }
416-
417- const token = auth . token
418- const value = auth . value || auth
419- const schema = securityDef [ key ]
420- const { type} = schema
421- const accessToken = token && token . access_token
422- const tokenType = token && token . token_type
423-
424- if ( auth ) {
425- if ( type === 'apiKey' ) {
426- const inType = schema . in === 'query' ? 'query' : 'headers'
427- result [ inType ] = result [ inType ] || { }
428- result [ inType ] [ schema . name ] = value
429- }
430- else if ( type === 'basic' ) {
431- if ( value . header ) {
432- result . headers . authorization = value . header
433- }
434- else {
435- value . base64 = btoa ( `${ value . username } :${ value . password } ` )
436- result . headers . authorization = `Basic ${ value . base64 } `
437- }
438- }
439- else if ( type === 'oauth2' && accessToken ) {
440- result . headers . authorization = `${ tokenType || 'Bearer' } ${ accessToken } `
441- }
442- }
443- }
444- } )
445-
446- return result
447- }
0 commit comments