From 2a763f7ba6c691d950533b387ec0f04e143e1409 Mon Sep 17 00:00:00 2001 From: DEEPAK RAJAMOHAN Date: Sun, 17 Nov 2019 19:46:29 -0800 Subject: [PATCH 1/2] feat: spike on url encoding of json object in query param --- .../acceptance/todo-list.acceptance.ts | 11 ++++++++++ .../param/param-query.decorator.unit.ts | 21 +++++++++++++++++++ .../src/decorators/parameter.decorator.ts | 5 +++++ 3 files changed, 37 insertions(+) diff --git a/examples/todo-list/src/__tests__/acceptance/todo-list.acceptance.ts b/examples/todo-list/src/__tests__/acceptance/todo-list.acceptance.ts index ddacc4ae3c38..63b326730600 100644 --- a/examples/todo-list/src/__tests__/acceptance/todo-list.acceptance.ts +++ b/examples/todo-list/src/__tests__/acceptance/todo-list.acceptance.ts @@ -204,6 +204,17 @@ describe('TodoListApplication', () => { }); }); + it('exploded filter conditions work', async () => { + const list = await givenTodoListInstance(todoListRepo); + await givenTodoInstance(todoRepo, {title: 'todo1', todoListId: list.id}); + await givenTodoInstance(todoRepo, {title: 'todo2', todoListId: list.id}); + await givenTodoInstance(todoRepo, {title: 'todo3', todoListId: list.id}); + + const response = await client.get('/todos').query('filter[limit]=2'); + + expect(response.body).to.have.length(2); + }); + /* ============================================================================ TEST HELPERS diff --git a/packages/openapi-v3/src/__tests__/unit/decorators/param/param-query.decorator.unit.ts b/packages/openapi-v3/src/__tests__/unit/decorators/param/param-query.decorator.unit.ts index 34e8ee0f7720..f6b75cb3a1d2 100644 --- a/packages/openapi-v3/src/__tests__/unit/decorators/param/param-query.decorator.unit.ts +++ b/packages/openapi-v3/src/__tests__/unit/decorators/param/param-query.decorator.unit.ts @@ -235,6 +235,11 @@ describe('Routing metadata for parameters', () => { type: 'object', additionalProperties: true, }, + content: { + 'application/json': { + schema: {type: 'object', additionalProperties: true}, + }, + }, }; expectSpecToBeEqual(MyController, expectedParamSpec); }); @@ -258,6 +263,17 @@ describe('Routing metadata for parameters', () => { in: 'query', style: 'deepObject', explode: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + where: {type: 'object', additionalProperties: true}, + limit: {type: 'number'}, + }, + }, + }, + }, schema: { type: 'object', properties: { @@ -306,6 +322,11 @@ describe('Routing metadata for parameters', () => { type: 'object', additionalProperties: true, }, + content: { + 'application/json': { + schema: {type: 'object', additionalProperties: true}, + }, + }, }; expectSpecToBeEqual(MyController, expectedParamSpec); }); diff --git a/packages/openapi-v3/src/decorators/parameter.decorator.ts b/packages/openapi-v3/src/decorators/parameter.decorator.ts index be7bbfce2db8..1ead09add613 100644 --- a/packages/openapi-v3/src/decorators/parameter.decorator.ts +++ b/packages/openapi-v3/src/decorators/parameter.decorator.ts @@ -214,6 +214,11 @@ export namespace param { in: 'query', style: 'deepObject', explode: true, + content: { + 'application/json': { + schema, + }, + }, schema, ...spec, }); From 9218d22a862aaa67a660195906fcd2fc3bb0c067 Mon Sep 17 00:00:00 2001 From: DEEPAK RAJAMOHAN Date: Tue, 26 Nov 2019 19:33:10 -0800 Subject: [PATCH 2/2] fix: remove style and schema from param spec --- .../param/param-query.decorator.unit.ts | 21 ------------------- .../src/decorators/parameter.decorator.ts | 10 ++++----- .../rest/src/coercion/coerce-parameter.ts | 9 +++++++- 3 files changed, 13 insertions(+), 27 deletions(-) diff --git a/packages/openapi-v3/src/__tests__/unit/decorators/param/param-query.decorator.unit.ts b/packages/openapi-v3/src/__tests__/unit/decorators/param/param-query.decorator.unit.ts index f6b75cb3a1d2..85d2f50a7b09 100644 --- a/packages/openapi-v3/src/__tests__/unit/decorators/param/param-query.decorator.unit.ts +++ b/packages/openapi-v3/src/__tests__/unit/decorators/param/param-query.decorator.unit.ts @@ -229,12 +229,6 @@ describe('Routing metadata for parameters', () => { const expectedParamSpec = { name: 'filter', in: 'query', - style: 'deepObject', - explode: true, - schema: { - type: 'object', - additionalProperties: true, - }, content: { 'application/json': { schema: {type: 'object', additionalProperties: true}, @@ -261,8 +255,6 @@ describe('Routing metadata for parameters', () => { const expectedParamSpec: ParameterObject = { name: 'filter', in: 'query', - style: 'deepObject', - explode: true, content: { 'application/json': { schema: { @@ -274,13 +266,6 @@ describe('Routing metadata for parameters', () => { }, }, }, - schema: { - type: 'object', - properties: { - where: {type: 'object', additionalProperties: true}, - limit: {type: 'number'}, - }, - }, }; expectSpecToBeEqual(MyController, expectedParamSpec); }); @@ -316,12 +301,6 @@ describe('Routing metadata for parameters', () => { name: 'filter', in: 'query', description: 'Search criteria', - style: 'deepObject', - explode: true, - schema: { - type: 'object', - additionalProperties: true, - }, content: { 'application/json': { schema: {type: 'object', additionalProperties: true}, diff --git a/packages/openapi-v3/src/decorators/parameter.decorator.ts b/packages/openapi-v3/src/decorators/parameter.decorator.ts index 1ead09add613..8ed5684960b0 100644 --- a/packages/openapi-v3/src/decorators/parameter.decorator.ts +++ b/packages/openapi-v3/src/decorators/parameter.decorator.ts @@ -50,8 +50,11 @@ export function param(paramSpec: ParameterObject) { // generate schema if `paramSpec` has `schema` but without `type` (isSchemaObject(paramSpec.schema) && !paramSpec.schema.type) ) { - // please note `resolveSchema` only adds `type` and `format` for `schema` - paramSpec.schema = resolveSchema(paramType, paramSpec.schema); + // If content explicitly mentioned do not resolve schema + if (!paramSpec.content) { + // please note `resolveSchema` only adds `type` and `format` for `schema` + paramSpec.schema = resolveSchema(paramType, paramSpec.schema); + } } } @@ -212,14 +215,11 @@ export namespace param { return param({ name, in: 'query', - style: 'deepObject', - explode: true, content: { 'application/json': { schema, }, }, - schema, ...spec, }); }, diff --git a/packages/rest/src/coercion/coerce-parameter.ts b/packages/rest/src/coercion/coerce-parameter.ts index fe82566a2f65..fe53ce05f5d7 100644 --- a/packages/rest/src/coercion/coerce-parameter.ts +++ b/packages/rest/src/coercion/coerce-parameter.ts @@ -32,7 +32,14 @@ export function coerceParameter( data: string | undefined | object, spec: ParameterObject, ) { + if (!spec.schema && spec.content) { + const content = spec.content; + const jsonSpec = content['application/json']; + spec.schema = jsonSpec.schema; + } + const schema = spec.schema; + if (!schema || isReferenceObject(schema)) { debug( 'The parameter with schema %s is not coerced since schema' + @@ -172,7 +179,7 @@ function parseJsonIfNeeded( ): string | object | undefined { if (typeof data !== 'string') return data; - if (spec.in !== 'query' || spec.style !== 'deepObject') { + if (spec.in !== 'query' || (spec.style !== 'deepObject' && !spec.content)) { debug( 'Skipping JSON.parse, argument %s is not in:query style:deepObject', spec.name,