diff --git a/package.json b/package.json index cc656489..9962e1b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "express-openapi-validator", - "version": "3.14.1", + "version": "4.0.0", "description": "Automatically validate API requests and responses with OpenAPI 3 and Express.", "main": "dist/index.js", "scripts": { diff --git a/src/middlewares/openapi.request.validator.ts b/src/middlewares/openapi.request.validator.ts index dd10a1b4..097909ed 100644 --- a/src/middlewares/openapi.request.validator.ts +++ b/src/middlewares/openapi.request.validator.ts @@ -165,8 +165,8 @@ export class RequestValidator { } private processQueryParam(query, schema, whiteList: string[] = []) { - if (!schema.properties) return; - const knownQueryParams = new Set(Object.keys(schema.properties)); + const keys = schema.properties ? Object.keys(schema.properties) : []; + const knownQueryParams = new Set(keys); whiteList.forEach((item) => knownQueryParams.add(item)); const queryParams = Object.keys(query); const allowedEmpty = schema.allowEmptyValue; diff --git a/test/query.params.spec.ts b/test/query.params.spec.ts index 69ca63b2..374a3bc2 100644 --- a/test/query.params.spec.ts +++ b/test/query.params.spec.ts @@ -11,13 +11,14 @@ describe(packageJson.name, () => { before(async () => { // Set up the express app const apiSpec = path.join('test', 'resources', 'query.params.yaml'); - app = await createApp({ apiSpec }, 3005, app => + app = await createApp({ apiSpec }, 3005, (app) => app.use( `${app.basePath}`, express .Router() .post(`/pets/nullable`, (req, res) => res.json(req.body)) .get(`/no_reserved`, (req, res) => res.json(req.body)) + .get(`/no_query_params`, (req, res) => res.json({ complete: true })) .get(`/allow_reserved`, (req, res) => res.json(req.body)), ), ); @@ -39,6 +40,17 @@ describe(packageJson.name, () => { }) .expect(200)); + it('should reject any query param when endpoint declares none', async () => + request(app) + .get(`${app.basePath}/no_query_params`) + .query({ + name: 'max', + }) + .expect(400) + .then((r) => { + expect(r.body.errors).to.be.an('array'); + })); + it('should fail if unknown query param is specified', async () => request(app) .get(`${app.basePath}/pets`) @@ -51,7 +63,7 @@ describe(packageJson.name, () => { unknown_prop: 'test', }) .expect(400) - .then(r => { + .then((r) => { expect(r.body.errors).to.be.an('array'); })); @@ -66,13 +78,11 @@ describe(packageJson.name, () => { owner_name: 'carmine', }) .expect(400) - .then(r => { + .then((r) => { expect(r.body) .to.have.property('message') .that.equals("Empty value found for query parameter 'breed'"); - expect(r.body.errors) - .to.be.an('array') - .with.length(1); + expect(r.body.errors).to.be.an('array').with.length(1); expect(r.body.errors[0].path).to.equal('.query.breed'); })); @@ -99,7 +109,7 @@ describe(packageJson.name, () => { request(app) .get(`${app.basePath}/no_reserved?value=ThisHas$ReservedChars!`) .expect(400) - .then(r => { + .then((r) => { const body = r.body; expect(body.message).equals( "Parameter 'value' must be url encoded. It's value may not contain reserved characters.", diff --git a/test/resources/query.params.yaml b/test/resources/query.params.yaml index 6869def6..5b0dcc5e 100644 --- a/test/resources/query.params.yaml +++ b/test/resources/query.params.yaml @@ -69,7 +69,12 @@ paths: responses: '200': description: success - + /no_query_params: + get: + description: test no query parameters + responses: + '200': + description: pet response /pets: get: description: | diff --git a/test/resources/read.only.yaml b/test/resources/read.only.yaml index 744380d3..b57b18fe 100644 --- a/test/resources/read.only.yaml +++ b/test/resources/read.only.yaml @@ -15,6 +15,11 @@ paths: post: description: get user operationId: getUser + parameters: + - name: include_id + in: query + schema: + type: boolean requestBody: required: true content: @@ -44,6 +49,11 @@ paths: post: description: get user operationId: getUser + parameters: + - name: include_id + in: query + schema: + type: boolean requestBody: required: true content: diff --git a/test/resources/request.bodies.ref.yaml b/test/resources/request.bodies.ref.yaml index b937a1f4..8f4b3cd1 100644 --- a/test/resources/request.bodies.ref.yaml +++ b/test/resources/request.bodies.ref.yaml @@ -10,6 +10,11 @@ servers: paths: /request_bodies_ref: post: + parameters: + - name: bad_body + in: query + schema: + type: boolean requestBody: $ref: '#/components/requestBodies/TestBody' responses: @@ -37,7 +42,6 @@ paths: '*/*': schema: type: string - '400': description: Bad Request diff --git a/test/resources/write.only.yaml b/test/resources/write.only.yaml index 68f0c4b6..64db4be3 100644 --- a/test/resources/write.only.yaml +++ b/test/resources/write.only.yaml @@ -15,6 +15,11 @@ paths: post: description: create products operationId: createProductsInline + parameters: + - name: exclude_write_only + in: query + schema: + type: boolean requestBody: required: true content: @@ -45,6 +50,11 @@ paths: post: description: create products operationId: createProductsNested + parameters: + - name: exclude_write_only + in: query + schema: + type: boolean requestBody: required: true content: