Skip to content

Commit

Permalink
feat: #467 support for URI path params
Browse files Browse the repository at this point in the history
  • Loading branch information
cdimascio committed Dec 16, 2020
1 parent e5a5cea commit f2aa54e
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 2 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ Determines whether the validator should validate requests.
responses:
200:
description: success
```
```
**coerceTypes:**
Expand Down Expand Up @@ -774,10 +774,13 @@ Defines a regular expression or function that determines whether a path(s) shoul

The following ignores any path that ends in `/pets` e.g. `/v1/pets`.
As a regular expression:

```
ignorePaths: /.*\/pets$/
```

or as a function:

```
ignorePaths: (path) => path.endsWith('/pets')
```
Expand Down Expand Up @@ -1048,6 +1051,32 @@ module.exports = app;

## FAQ

**Q:** How do i handle wildcard path, like those described in RFC 6570?
**A:** OpenAPI 3.0 does not support RFC 6570. That said, we provide a minimalistic mechanism that conforms syntactically to OpenAPI 3 and accomplishes a common use case. For example, matching file paths

Using the following OpenAPI defintion

```yaml
/files/{path}*:
get:
tags:
- Data
parameters:
- name: path
in: path
required: true
schema:
type: string
```
With the following route definition
```javascript
app.get(`/files/:path(*)`, (req, res) => { /* do stuff */ }`
```

You can match `/files/some/long/path` and `req.params.path` will contain `some/long/path`

**Q:** What happened to the `securityHandlers` property?

**A:** In v3, `securityHandlers` have been replaced by `validateSecurity.handlers`. To use v3 security handlers, move your existing security handlers to the new property. No other change is required. Note that the v2 `securityHandlers` property is supported in v3, but deprecated
Expand Down Expand Up @@ -1172,6 +1201,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
Expand Down
12 changes: 11 additions & 1 deletion src/framework/openapi.spec.loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ export class OpenApiSpecLoader {
}

private toExpressParams(part: string): string {
return part.replace(/\{([^}]+)}/g, ':$1');
// substitute wildcard path with express equivalent
// {/path} => /path(*) <--- RFC 6570 format (not supported by openapi)
// const pass1 = part.replace(/\{(\/)([^\*]+)(\*)}/g, '$1:$2$3');

// instead create our own syntax that is compatible with express' pathToRegex
// /{path}* => /:path*
const pass1 = part.replace(/\/{([^\*]+)}(\*)/g, '/:$1$2');

// substitute params with express equivalent
// /path/{id} => /path/:id
return pass1.replace(/\{([^}]+)}/g, ':$1');
}
}
43 changes: 43 additions & 0 deletions test/resources/wildcard.path.params.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
openapi: 3.0.1
info:
title: api-server
description: Pharmacy Tools API server
version: 1.0.0
servers:
- url: /v1
tags:
- name: Data
description: Data endpoints
- name: Specification
description: The swagger API specification
paths:
/d1/{id}:
get:
tags:
- Data
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
200:
description: Returns the latest tracked s3 keys
content: {}

/d2/{path}*:
get:
tags:
- Data
parameters:
- name: path
in: path
required: true
schema:
type: string

responses:
200:
description: Returns the latest tracked s3 keys
content: {}
49 changes: 49 additions & 0 deletions test/wildcard.path.params.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as path from 'path';
import { expect } from 'chai';
import * as request from 'supertest';
import { createApp } from './common/app';

describe('wildcard path params', () => {
let app = null;

before(async () => {
const apiSpec = path.join('test', 'resources', 'wildcard.path.params.yaml');
app = await createApp(
{
apiSpec,
},
3001,
(app) => {
app
.get(`${app.basePath}/d1/:id`, (req, res) =>
res.json({
...req.params,
}),
)
.get(`${app.basePath}/d2/:path(*)`, (req, res) =>
res.json({
...req.params,
}),
);
},
);
});

after(() => app.server.close());

it('should allow path param without wildcard', async () =>
request(app)
.get(`${app.basePath}/d1/my-id`)
.expect(200)
.then((r) => {
expect(r.body.id).to.equal('my-id');
}));

it('should allow path param with slashes "/" using wildcard', async () =>
request(app)
.get(`${app.basePath}/d2/some/long/path`)
.expect(200)
.then((r) => {
expect(r.body.path).to.equal('some/long/path');
}));
});

0 comments on commit f2aa54e

Please sign in to comment.