Skip to content

Commit

Permalink
fix: parameter style handling #473 (#474)
Browse files Browse the repository at this point in the history
  • Loading branch information
cdimascio committed Nov 28, 2020
1 parent d690c9e commit 19c6f49
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 1 deletion.
34 changes: 33 additions & 1 deletion src/middlewares/parsers/util.ts
Expand Up @@ -31,7 +31,7 @@ export function normalizeParameter(
} else if (parameter?.schema?.['$ref']) {
schema = dereferenceSchema(ajv, parameter.schema['$ref']);
} else {
schema = parameter.schema
schema = parameter.schema;
}
if (!schema && parameter.content) {
const contentType = Object.keys(parameter.content)[0];
Expand All @@ -41,11 +41,43 @@ export function normalizeParameter(
schema = parameter;
}

applyParameterStyle(parameter);
applyParameterExplode(parameter);

const name =
parameter.in === 'header' ? parameter.name.toLowerCase() : parameter.name;

return { name, schema };
}

function applyParameterStyle(param: OpenAPIV3.ParameterObject) {
if (!param.style) {
if (param.in === 'path') {
param.style = 'simple';
} else if (param.in === 'query') {
param.style = 'form';
} else if (param.style === 'header') {
param.style = 'simple';
} else if (param.style === 'cookie') {
param.style = 'form';
}
}
}

function applyParameterExplode(param: OpenAPIV3.ParameterObject) {
if (param.explode == null) {
if (param.in === 'path') {
param.explode = false;
} else if (param.in === 'query') {
param.explode = true;
} else if (param.style === 'header') {
param.explode = false;
} else if (param.style === 'cookie') {
param.explode = true;
}
}
}

export function dereferenceSchema(ajv: Ajv, ref: string) {
// TODO cache schemas - so that we don't recurse every time
const derefSchema = ajv.getSchema(ref);
Expand Down
46 changes: 46 additions & 0 deletions test/query.serialization.ts
@@ -0,0 +1,46 @@
import * as path from 'path';
import * as express from 'express';
import { expect } from 'chai';
import * as request from 'supertest';
import { createApp } from './common/app';
import * as packageJson from '../package.json';
import { log } from 'console';

describe.only('styles', () => {
let app = null;
before(async () => {
const apiSpec = path.join('test', 'resources', 'query.serialization.yaml');
app = await createApp({ apiSpec }, 3005, (app) =>
app.use(
`/`,
express
.Router()
.get('/api/q_form_explode', (req, res) => res.json({ query: req.query }))
.get('/api/q_form_nexplode', (req, res) => res.json({ query: req.query })),
),
);
});

after(async () => {
app.server.close();
});

it('should handle querey param (default) style=form, explode=true', async () =>
request(app)
.get('/api/q_form_explode?state=on&state=off')
.expect(200)
.then((r) => {
expect(r.body.query.state).is.an('array').of.length(2);
}));

it.only('should handle query param with style=form, explode=false', async () =>
request(app)
.get('/api/q_form_nexplode')
.query({
state: 'on,off',
})
.expect(200)
.then((r) => {
expect(r.body.query.state).is.an('array').of.length(2);
}));
});
58 changes: 58 additions & 0 deletions test/resources/query.serialization.yaml
@@ -0,0 +1,58 @@
openapi: '3.0.3'
info:
title: Dummy
version: '0.1.0'

paths:
/api/q_form_explode:
get:
parameters:
- description: Description
schema:
title: State
type: array
items:
$ref: '#/components/schemas/Foo'
description: A description
name: state
in: query
responses:
200:
description: OK
content:
'application/json; charset=utf-8':
schema:
type: object

/api/q_form_nexplode:
get:
parameters:
- description: Description
required: false
explode: false
schema:
title: State
type: array
items:
$ref: '#/components/schemas/Foo'
description: A description
name: state
in: query
responses:
200:
description: OK
content:
'application/json; charset=utf-8':
schema:
type: object


components:
schemas:
Foo:
type: string
enum:
- on
- off


0 comments on commit 19c6f49

Please sign in to comment.