Skip to content
12 changes: 8 additions & 4 deletions src/execute/oas3/build-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export default function (options, req) {
operation,
requestBody,
securities,
spec
spec,
attachContentTypeForEmptyPayload
} = options

let {
Expand All @@ -20,12 +21,12 @@ export default function (options, req) {

const requestBodyDef = operation.requestBody || {}
const requestBodyMediaTypes = Object.keys(requestBodyDef.content || {})
const isExplicitContentTypeValid = requestContentType
&& requestBodyMediaTypes.indexOf(requestContentType) > -1

// for OAS3: set the Content-Type
if (requestBody) {
if (requestBody || attachContentTypeForEmptyPayload) {
// does the passed requestContentType appear in the requestBody definition?
const isExplicitContentTypeValid = requestContentType
&& requestBodyMediaTypes.indexOf(requestContentType) > -1

if (requestContentType && isExplicitContentTypeValid) {
req.headers['Content-Type'] = requestContentType
Expand All @@ -38,6 +39,9 @@ export default function (options, req) {
}
}
}
else if (requestContentType && isExplicitContentTypeValid) {
req.headers['Content-Type'] = requestContentType
}

// for OAS3: add requestBody to request
if (requestBody) {
Expand Down
12 changes: 10 additions & 2 deletions src/execute/swagger2/build-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ export default function (options, req) {
spec,
operation,
securities,
requestContentType
requestContentType,
attachContentTypeForEmptyPayload
} = options
// Add securities, which are applicable
req = applySecurities({request: req, securities, operation, spec})

if (req.body || req.form) {
if (req.body || req.form || attachContentTypeForEmptyPayload) {
// all following conditionals are Swagger2 only
if (requestContentType) {
req.headers['Content-Type'] = requestContentType
Expand All @@ -34,6 +35,13 @@ export default function (options, req) {
req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
}
}
else if (requestContentType) {
const isBodyParamPresent = operation.parameters && operation.parameters.filter(p => p.in === 'body').length > 0
const isFormDataParamPresent = operation.parameters && operation.parameters.filter(p => p.in === 'formData').length > 0
if (isBodyParamPresent || isFormDataParamPresent) {
req.headers['Content-Type'] = requestContentType
}
}

return req
}
Expand Down
2 changes: 1 addition & 1 deletion src/execute/swagger2/parameter-builders.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ function bodyBuilder({req, value}) {

// Add a form data object.
function formDataBuilder({req, value, parameter}) {
req.form = req.form || {}
if (value || parameter.allowEmptyValue) {
req.form = req.form || {}
req.form[parameter.name] = {
value,
allowEmptyValue: parameter.allowEmptyValue,
Expand Down
256 changes: 252 additions & 4 deletions test/execute/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,88 @@ describe('execute', () => {
})
})

it('should not add Content-Type with no form-data or body param', function () {
it('should add Content-Type if a body param definition is present but there is no payload', function () {
// Given
const spec = {
host: 'swagger.io',
paths: {
'/one': {
get: {
operationId: 'getMe',
parameters: [
{
name: 'body',
in: 'body',
schema: {
type: 'string'
}
}
]
}
}
}
}

// When
const req = buildRequest({
spec,
operationId: 'getMe',
requestContentType: 'application/josh'
})

// Then
expect(req).toEqual({
url: 'http://swagger.io/one',
body: undefined,
headers: {
'Content-Type': 'application/josh'
},
credentials: 'same-origin',
method: 'GET'
})
})

it('should add Content-Type if a formData param definition is present but there is no payload', function () {
// Given
const spec = {
host: 'swagger.io',
paths: {
'/one': {
get: {
operationId: 'getMe',
parameters: [
{
name: 'data',
in: 'formData',
schema: {
type: 'string'
}
}
]
}
}
}
}

// When
const req = buildRequest({
spec,
operationId: 'getMe',
requestContentType: 'application/x-www-form-encoded'
})

// Then
expect(req).toEqual({
url: 'http://swagger.io/one',
headers: {
'Content-Type': 'application/x-www-form-encoded'
},
credentials: 'same-origin',
method: 'GET'
})
})

it('should not add Content-Type if no form-data or body param definition is present', function () {
// Given
const spec = {
host: 'swagger.io',
Expand Down Expand Up @@ -608,7 +689,7 @@ describe('execute', () => {
const req = buildRequest({
spec,
operationId: 'postMe',
parameters: {file: 'test'}})
parameters: {foo: 'test'}})

// Then
expect(req.headers).toEqual({
Expand Down Expand Up @@ -816,6 +897,171 @@ describe('execute', () => {
one: 1
})
})

describe('attachContentTypeForEmptyPayload', () => {
it('should attach a Content-Type to a Swagger 2 operation with a body parameter defined but no body provided', () => {
const spec = {
swagger: '2.0',
host: 'swagger.io',
consumes: ['application/json'],
paths: {
'/one': {
post: {
operationId: 'myOp',
parameters: [
{
name: 'body',
in: 'body'
}
]
}
}
}
}

const req = buildRequest({
spec,
operationId: 'myOp',
attachContentTypeForEmptyPayload: true
})

expect(req).toEqual({
url: 'http://swagger.io/one',
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin',
method: 'POST',
body: undefined
})
})
it('should attach a Content-Type to a Swagger 2 operation with a formData parameter defined but no body provided', () => {
const spec = {
swagger: '2.0',
host: 'swagger.io',
paths: {
'/one': {
post: {
operationId: 'myOp',
parameters: [
{
name: 'data',
in: 'formData',
type: 'string'
}
]
}
}
}
}

const req = buildRequest({
spec,
operationId: 'myOp',
attachContentTypeForEmptyPayload: true
})

expect(req).toEqual({
url: 'http://swagger.io/one',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
credentials: 'same-origin',
method: 'POST'
})
})
it('should not attach a Content-Type to a Swagger 2 operation with no body or formData parameter definition present', () => {
const spec = {
swagger: '2.0',
host: 'swagger.io',
paths: {
'/one': {
post: {
operationId: 'myOp'
}
}
}
}

const req = buildRequest({
spec,
operationId: 'myOp',
attachContentTypeForEmptyPayload: true
})

expect(req).toEqual({
url: 'http://swagger.io/one',
headers: {},
credentials: 'same-origin',
method: 'POST'
})
})
it('should not attach a Content-Type to a Swagger 2 operation with a body parameter defined but no body provided if the option is not enabled', () => {
const spec = {
swagger: '2.0',
host: 'swagger.io',
consumes: ['application/json'],
paths: {
'/one': {
post: {
operationId: 'myOp',
parameters: [
{
name: 'body',
in: 'body'
}
]
}
}
}
}

const req = buildRequest({
spec,
operationId: 'myOp',
})

expect(req).toEqual({
url: 'http://swagger.io/one',
headers: {},
credentials: 'same-origin',
method: 'POST',
body: undefined
})
})
it('should not attach a Content-Type to a Swagger 2 operation with a formData parameter defined but no body provided if the option is not enabled', () => {
const spec = {
swagger: '2.0',
host: 'swagger.io',
paths: {
'/one': {
post: {
operationId: 'myOp',
parameters: [
{
name: 'data',
in: 'formData',
type: 'string'
}
]
}
}
}
}

const req = buildRequest({
spec,
operationId: 'myOp',
})

expect(req).toEqual({
url: 'http://swagger.io/one',
headers: {},
credentials: 'same-origin',
method: 'POST'
})
})
})
})


Expand All @@ -834,12 +1080,14 @@ describe('execute', () => {
fetch: createSpy().andReturn({then() { }}),
spec,
operationId: 'getMe',
josh: 1
josh: 1,
attachContentTypeForEmptyPayload: true
})

expect(buildRequestSpy.calls.length).toEqual(1)
expect(buildRequestSpy.calls[0].arguments[0]).toInclude({
josh: 1
josh: 1,
attachContentTypeForEmptyPayload: true
})
})

Expand Down
Loading