Skip to content

Commit 0aebe5d

Browse files
fix: Dereference path parameters (#962)
The OpenAPI spec loader has a `discoverRoutes` method which explores an OpenAPI document and gathers information about the paths and parameters used. The list of discovered path parameters is used to install parameter-specific middleware in `src/openapi.validator.ts#installPathParams` Path parameters declared with `$ref` were not detected in the `discoverRoutes` implementation, leading to the un-coerced values being used. By dereferencing each path parameter when building this list, we should see the same behavior for referenced path parameters and for inline path parameters. Closes #803
1 parent 0a8dc2f commit 0aebe5d

File tree

4 files changed

+52
-8
lines changed

4 files changed

+52
-8
lines changed

src/framework/openapi.spec.loader.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { dereferenceParameter } from '../middlewares/parsers/util';
12
import { OpenAPIFramework } from './index';
23
import {
34
OpenAPIFrameworkAPIContext,
@@ -68,13 +69,15 @@ export class OpenApiSpecLoader {
6869
) {
6970
continue;
7071
}
71-
const pathParams = new Set<string>();
72-
const parameters = [...schema.parameters ?? [], ...methods.parameters ?? []]
73-
for (const param of parameters) {
74-
if (param.in === 'path') {
75-
pathParams.add(param.name);
76-
}
77-
}
72+
73+
const pathParams = [
74+
...(schema.parameters ?? []),
75+
...(methods.parameters ?? []),
76+
]
77+
.map(param => dereferenceParameter(apiDoc, param))
78+
.filter(param => param.in === 'path')
79+
.map(param => param.name);
80+
7881
const openApiRoute = `${bp}${path}`;
7982
const expressRoute = `${openApiRoute}`
8083
.split(':')
@@ -86,7 +89,7 @@ export class OpenApiSpecLoader {
8689
expressRoute,
8790
openApiRoute,
8891
method: method.toUpperCase(),
89-
pathParams: Array.from(pathParams),
92+
pathParams: Array.from(new Set(pathParams)),
9093
});
9194
}
9295
}

test/operation.handler.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,12 @@ describe('custom operation handler', () => {
120120
});
121121
});
122122

123+
it('should coerce path parameters', async () => {
124+
return request(app)
125+
.get(`${basePath}/users/123/info`)
126+
.expect(200)
127+
.then((r) => {
128+
expect(r.text).to.be.equal('{"id":123}');
129+
});
130+
});
123131
});

test/resources/eov-operations.modulepath.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,35 @@ paths:
185185
properties:
186186
success:
187187
type: boolean
188+
/users/{userID}/info:
189+
get:
190+
description: Get info about a User
191+
summary: Get info about a User
192+
operationId: user.info
193+
security: []
194+
parameters:
195+
- $ref: '#/components/parameters/userID'
196+
responses:
197+
'200':
198+
description: Returns info about a User.
199+
content:
200+
'application/json':
201+
schema:
202+
type: object
203+
properties:
204+
id:
205+
$ref: '#/components/schemas/UserID'
188206

189207
components:
208+
parameters:
209+
userID:
210+
name: userID
211+
in: path
212+
required: true
213+
schema:
214+
$ref: '#/components/schemas/UserID'
215+
# type: number
216+
190217
schemas:
191218
Pet:
192219
required:
@@ -210,6 +237,9 @@ components:
210237
- dog
211238
- cat
212239

240+
UserID:
241+
type: number
242+
213243
Error:
214244
required:
215245
- code

test/resources/routes/user.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
info: (req, res) => res.status(200).send({ id: req.params.userID })
3+
};

0 commit comments

Comments
 (0)