From a133736b0e2324100cca7dd01f302d8d3d2d1c0d Mon Sep 17 00:00:00 2001 From: mrmodise Date: Sun, 11 Oct 2020 19:08:06 +0200 Subject: [PATCH] fix: allow array query parameter for a single value Signed-off-by: mrmodise --- .../coercion/coercion.acceptance.ts | 32 +++++++++++++++++++ .../rest/src/coercion/coerce-parameter.ts | 21 ++++++++++++ 2 files changed, 53 insertions(+) diff --git a/packages/rest/src/__tests__/acceptance/coercion/coercion.acceptance.ts b/packages/rest/src/__tests__/acceptance/coercion/coercion.acceptance.ts index 0278cc8eab1b..4fc6e8b43a84 100644 --- a/packages/rest/src/__tests__/acceptance/coercion/coercion.acceptance.ts +++ b/packages/rest/src/__tests__/acceptance/coercion/coercion.acceptance.ts @@ -144,6 +144,14 @@ describe('Coercion', () => { ) { return filter; } + + @get('/array-parameters-from-query') + getArrayFromQuery( + @param.array('stringArray', 'query', {type: 'string'}) + stringArray: string[], + ) { + return stringArray; + } } it('coerces parameter in path from string to number', async () => { @@ -283,6 +291,30 @@ describe('Coercion', () => { ); }); + describe('coerces array parameters', () => { + it('coerces a single value into an array with one item', async () => { + const response = await client + .get('/array-parameters-from-query') + .query({ + stringArray: 'hello', + }) + .expect(200); + + expect(response.body).to.eql(['hello']); + }); + + it('preserves array values as arrays', async () => { + const response = await client + .get('/array-parameters-from-query') + .query({ + stringArray: ['hello', 'loopback', 'world'], + }) + .expect(200); + + expect(response.body).to.eql(['hello', 'loopback', 'world']); + }); + }); + async function givenAClient() { app = new RestApplication({rest: givenHttpServerConfig()}); app.controller(MyController); diff --git a/packages/rest/src/coercion/coerce-parameter.ts b/packages/rest/src/coercion/coerce-parameter.ts index 3f2404af15ae..973022e48704 100644 --- a/packages/rest/src/coercion/coerce-parameter.ts +++ b/packages/rest/src/coercion/coerce-parameter.ts @@ -95,6 +95,9 @@ export async function coerceParameter( case 'password': result = coerceString(data, spec); break; + case 'array': + result = coerceArray(data, spec); + break; } if (result != null) { @@ -103,6 +106,7 @@ export async function coerceParameter( await validateParam(spec, data, options); return result; } + result = await validateParam(spec, result, options); } return result; @@ -199,6 +203,23 @@ async function coerceObject(input: string | object, spec: ParameterObject) { return data; } +function coerceArray( + data: string | number | boolean | object, + spec: ParameterObject, +) { + if (spec.in === 'query') { + if ( + typeof data === 'string' || + typeof data === 'number' || + typeof data === 'boolean' + ) { + return [data]; + } + } + + return data; +} + function validateParam( spec: ParameterObject, // eslint-disable-next-line @typescript-eslint/no-explicit-any