Fix how path variables are escaped for Swagger (#5246)

* path escapte fix 

paths in swagger are not correctly escaped and won't be correct. You can try with following swagger:

openapi: 3.0.0
info:
 title: SampleAPI
 version: "1.0"
tags:
  - description: Sample API
    name: Sample Echo API
paths:
  /healthcheck/$echo:
    get:
      parameters:
        - in: query
          name: message
          required: true
          schema:
            type: string
          description: The echo message
      responses:
        "200":
          description: An echo message.
      summary: Return a echo message.
      operationId: getEcho
      tags:
        - Generate echo message
  /batchs(Material='{Material}',Batch='{Batch}'):
    get:
      parameters:
        - in: path
          name: Material
          required: true
          schema:
            type: string
          description: The echo message
        - in: path
          name: Batch
          required: true
          schema:
            type: string
          description: The echo message
      responses:
        "200":
          description: An echo message.
      summary: Return a echo message.
      operationId: getBatch
      tags:
        - Generate echo message
servers:
  - url: https://httpbin.org/anything

* Update test for new regex fix

* Update common.test.ts

* Update common.ts

* Update common.test.ts

* Update common.ts

* Update common.test.ts

* Update common.ts

* Patch-Regex-Text

* Update services.test.ts

* Update httpbin.expected.json

* Update link-example.expected.json

* Update petstore-expanded.expected.json

* Update petstore.expected.json

* Update request-validator-plugin.expected.json

* Update uspto.expected.json

* Update generate.js

* Update generate.js
This commit is contained in:
Antoine Jacquemin 2022-10-24 22:00:34 +02:00 committed by GitHub
parent 38a943d0f3
commit d102de2850
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 33 additions and 27 deletions

View File

@ -235,13 +235,17 @@ describe('common', () => {
describe('pathVariablesToRegex()', () => {
it('converts variables to regex path', () => {
expect(pathVariablesToRegex('/foo/{bar}/{baz}')).toBe(
'/foo/(?<bar>[^\\/]+)/(?<baz>[^\\/]+)$',
'/foo/(?<bar>[^/]+)/(?<baz>[^/]+)$',
);
});
it('does not convert to regex if no variables present', () => {
expect(pathVariablesToRegex('/foo/bar/baz')).toBe('/foo/bar/baz$');
});
it('escape special characters not present in curly braces', () => {
expect(pathVariablesToRegex('/foo/bar/$baz')).toBe('/foo/bar/\\$baz$');
});
});
describe('getPluginNameFromKey()', () => {

View File

@ -66,8 +66,10 @@ export function generateSlug(str: string, options: SlugifyOptions = {}) {
const pathVariableSearchValue = /{([^}]+)}(?!:\/\/)/g;
export function pathVariablesToRegex(p: string) {
// escape URL special characters except the curly braces
p = p.replace(/[$()]/g, '\\$&');
// match anything except whitespace and '/'
const result = p.replace(pathVariableSearchValue, '(?<$1>[^\\/]+)');
const result = p.replace(pathVariableSearchValue, '(?<$1>[^/]+)');
// add a line ending because it is a regex
return result + '$';
}

View File

@ -27,21 +27,21 @@
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"]
}
],
"paths": ["/basic-auth/(?<user>[^\\/]+)/(?<password>[^\\/]+)$"]
"paths": ["/basic-auth/(?<user>[^/]+)/(?<password>[^/]+)$"]
},
{
"methods": ["GET"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"],
"name": "httpbin-image-format-get",
"paths": ["/image/(?<format>[^\\/]+)$"]
"paths": ["/image/(?<format>[^/]+)$"]
},
{
"methods": ["GET"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"],
"name": "httpbin-delay-n-get",
"paths": ["/delay/(?<n>[^\\/]+)$"]
"paths": ["/delay/(?<n>[^/]+)$"]
},
{
"methods": ["GET"],
@ -55,35 +55,35 @@
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"],
"name": "httpbin-status-statusCode-delete",
"paths": ["/status/(?<statusCode>[^\\/]+)$"]
"paths": ["/status/(?<statusCode>[^/]+)$"]
},
{
"methods": ["PUT"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"],
"name": "httpbin-status-statusCode-put",
"paths": ["/status/(?<statusCode>[^\\/]+)$"]
"paths": ["/status/(?<statusCode>[^/]+)$"]
},
{
"methods": ["PATCH"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"],
"name": "httpbin-status-statusCode-patch",
"paths": ["/status/(?<statusCode>[^\\/]+)$"]
"paths": ["/status/(?<statusCode>[^/]+)$"]
},
{
"methods": ["POST"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"],
"name": "httpbin-status-statusCode-post",
"paths": ["/status/(?<statusCode>[^\\/]+)$"]
"paths": ["/status/(?<statusCode>[^/]+)$"]
},
{
"methods": ["GET"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"],
"name": "httpbin-status-statusCode-get",
"paths": ["/status/(?<statusCode>[^\\/]+)$"]
"paths": ["/status/(?<statusCode>[^/]+)$"]
},
{
"methods": ["GET"],
@ -105,7 +105,7 @@
}
],
"paths": [
"/hidden-basic-auth/(?<user>[^\\/]+)/(?<password>[^\\/]+)$"
"/hidden-basic-auth/(?<user>[^/]+)/(?<password>[^/]+)$"
]
},
{
@ -161,7 +161,7 @@
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_httpbin.yaml"],
"name": "httpbin-parse-machine_timestamp-get",
"paths": ["/parse/(?<machine_timestamp>[^\\/]+)$"]
"paths": ["/parse/(?<machine_timestamp>[^/]+)$"]
},
{
"methods": ["POST"],
@ -209,7 +209,7 @@
"enabled": true
}
],
"paths": ["/when/(?<human_timestamp>[^\\/]+)$"]
"paths": ["/when/(?<human_timestamp>[^/]+)$"]
},
{
"methods": ["GET"],

View File

@ -13,14 +13,14 @@
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_link-example.yaml"],
"name": "Link_Example-getUserByName",
"paths": ["/2.0/users/(?<username>[^\\/]+)$"]
"paths": ["/2.0/users/(?<username>[^/]+)$"]
},
{
"methods": ["GET"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_link-example.yaml"],
"name": "Link_Example-getRepositoriesByOwner",
"paths": ["/2.0/repositories/(?<username>[^\\/]+)$"]
"paths": ["/2.0/repositories/(?<username>[^/]+)$"]
},
{
"methods": ["GET"],
@ -28,7 +28,7 @@
"tags": ["OAS3_import", "OAS3file_link-example.yaml"],
"name": "Link_Example-getRepository",
"paths": [
"/2.0/repositories/(?<username>[^\\/]+)/(?<slug>[^\\/]+)$"
"/2.0/repositories/(?<username>[^/]+)/(?<slug>[^/]+)$"
]
},
{
@ -37,7 +37,7 @@
"tags": ["OAS3_import", "OAS3file_link-example.yaml"],
"name": "Link_Example-getPullRequestsByRepository",
"paths": [
"/2.0/repositories/(?<username>[^\\/]+)/(?<slug>[^\\/]+)/pullrequests$"
"/2.0/repositories/(?<username>[^/]+)/(?<slug>[^/]+)/pullrequests$"
]
},
{
@ -46,7 +46,7 @@
"tags": ["OAS3_import", "OAS3file_link-example.yaml"],
"name": "Link_Example-getPullRequestsById",
"paths": [
"/2.0/repositories/(?<username>[^\\/]+)/(?<slug>[^\\/]+)/pullrequests/(?<pid>[^\\/]+)$"
"/2.0/repositories/(?<username>[^/]+)/(?<slug>[^/]+)/pullrequests/(?<pid>[^/]+)$"
]
},
{
@ -55,7 +55,7 @@
"tags": ["OAS3_import", "OAS3file_link-example.yaml"],
"name": "Link_Example-mergePullRequest",
"paths": [
"/2.0/repositories/(?<username>[^\\/]+)/(?<slug>[^\\/]+)/pullrequests/(?<pid>[^\\/]+)/merge$"
"/2.0/repositories/(?<username>[^/]+)/(?<slug>[^/]+)/pullrequests/(?<pid>[^/]+)/merge$"
]
}
],

View File

@ -27,14 +27,14 @@
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_petstore-expanded.yaml"],
"name": "Swagger_Petstore-find_pet_by_id",
"paths": ["/pets/(?<id>[^\\/]+)$"]
"paths": ["/pets/(?<id>[^/]+)$"]
},
{
"methods": ["DELETE"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_petstore-expanded.yaml"],
"name": "Swagger_Petstore-deletePet",
"paths": ["/pets/(?<id>[^\\/]+)$"]
"paths": ["/pets/(?<id>[^/]+)$"]
}
],
"tags": ["OAS3_import", "OAS3file_petstore-expanded.yaml"]

View File

@ -27,7 +27,7 @@
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_petstore.yaml"],
"name": "Swagger_Petstore-showPetById",
"paths": ["/pets/(?<petId>[^\\/]+)$"]
"paths": ["/pets/(?<petId>[^/]+)$"]
}
],
"tags": ["OAS3_import", "OAS3file_petstore.yaml"]

View File

@ -60,7 +60,7 @@
{
"methods": ["GET"],
"name": "Example-params-pathid-get",
"paths": ["/params/(?<pathid>[^\\/]+)/$"],
"paths": ["/params/(?<pathid>[^/]+)/$"],
"plugins": [
{
"config": {

View File

@ -20,14 +20,14 @@
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_uspto.yaml"],
"name": "USPTO_Data_Set_API-list-searchable-fields",
"paths": ["/(?<dataset>[^\\/]+)/(?<version>[^\\/]+)/fields$"]
"paths": ["/(?<dataset>[^/]+)/(?<version>[^/]+)/fields$"]
},
{
"methods": ["POST"],
"strip_path": false,
"tags": ["OAS3_import", "OAS3file_uspto.yaml"],
"name": "USPTO_Data_Set_API-perform-search",
"paths": ["/(?<dataset>[^\\/]+)/(?<version>[^\\/]+)/records$"]
"paths": ["/(?<dataset>[^/]+)/(?<version>[^/]+)/records$"]
}
],
"tags": ["OAS3_import", "OAS3file_uspto.yaml"]

View File

@ -43,7 +43,7 @@ const getSpecResult = (): DCService =>
name: 'My_API-birds-id-get',
strip_path: false,
methods: ['GET'],
paths: ['/birds/(?<id>[^\\/]+)$'],
paths: ['/birds/(?<id>[^/]+)$'],
tags,
},
],
@ -255,7 +255,7 @@ describe('services', () => {
tags,
name: 'My_API-birds-id-get',
methods: ['GET'],
paths: ['/birds/(?<id>[^\\/]+)$'],
paths: ['/birds/(?<id>[^/]+)$'],
strip_path: false,
plugins: [
{