Wildcard routes: bug at "turning glob expression into valid RegExp"
- Dominant language
- No language data
- Stars
- 346
- Forks
- 67
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the bug**
When using wildcard suffix in routes, it's turned into an invalid regex.
In short, the glob `/api/servicelog*` is turned into `/^\/api\/servicelog*$/`, and here the `*` quantor is affecting the `g`, and the correct regex would be `/^\/api\/servicelog.*$/` (note the dot before the asterisk).
`staticwebapp.config.json`:
```
{
"trailingSlash": "auto",
"routes": [
{
"route": "/api/servicelog*",
"methods": ["GET", "PUT"]
}
]
}
```
This route matches none of `/api/servicelog`, `/api/servicelogwhatever` or `/api/servicelog/42`.
Command to start the emulator: `swa -V silly start --app-location landing-page --api-location api`
The request:
```
$ curl -i -X GET http://localhost:7071/api/servicelogq
HTTP/1.1 404 Not Found
content-length: 0
connection: close
date: Mon, 24 Apr 2023 12:42:26 GMT
server: Kestrel
request-context: appId=cid-v1:6b7954db-b2fd-4771-be5e-44e1a84ccda7
```
The log of the request:
```
[swa] --------------------------------------------------------
[swa] ------------------- processing route -------------------
[swa] --------------------------------------------------------
[swa] processing /api/servicelogq
[swa] checking for matching route
[swa] check if request match route
[swa] - route: /api/servicelog*
[swa] - wildcard: true
[swa] checking wildcard route
[swa] - glob: /api/servicelog*
[swa] - pathBeforeWildcard: /api/servicelog
[swa] checking if glob expression is valid
[swa] - glob: /api/servicelog*
[swa] - glob ends with *. Return true
[swa] - route regexp: /api/servicelog*
[swa] turning glob expression into valid RegExp
[swa] - glob: /api/servicelog*
[swa] - regexp: /^\/api\/servicelog*$/
[swa] - isMatch: false
[swa] - alternateRequestPath: /api/servicelogq/index.html
[swa] checking wildcard route
[swa] - glob: /api/servicelog*
[swa] - pathBeforeWildcard: /api/servicelog
[swa] checking if glob expression is valid
[swa] - glob: /api/servicelog*
[swa] - glob ends with *. Return true
[swa] - route regexp: /api/servicelog*
[swa] turning glob expression into valid RegExp
[swa] - glob: /api/servicelog*
[swa] - regexp: /^\/api\/servicelog*$/
[swa] - isMatch: false
[swa] checking auth request
[swa] - not an auth request
[swa] checking function request
[swa] checking data-api request
[swa] - not a data Api request
[swa] checking HTTP method: GET
[swa] - function or auth or data-api request detected, method is valid
[swa] checking for query params
[swa] checking rewrite auth login request
[swa] checking rewrite auth logout request
[swa] checking authorizations for route
[swa] - no matching rule
[swa] - access authorized
[swa] using userConfig
[swa] - userConfig:
[swa] - trailingSlash: auto
[swa] - routes:
[swa] - 0:
[swa] - route: /api/servicelog*
[swa] - methods:
[swa] - 0: GET
[swa] - 1: PUT
[swa] function request detected. Proxying to Azure Functions emulator
[swa] - target: http://localhost:7071
[swa] GET http://localhost:7071/api/servicelogq (proxy)
[swa] injecting headers to Functions request:
[swa] - x-ms-request-id: SWA-CLI-1AR8CEP1NQH
[swa] injecting client principal to Functions request:
[swa] - no valid cookie found
[swa] getting response from remote host
[swa] GET http://localhost:4280/api/servicelogq - 404
```
(By the way, the glob `/api/servicelog/*` is transcribed correctly to `/^\/api\/servicelog\/.*$/`)
**To Reproduce**
Use the abovementioned config and request, the function itself doesn't matter.
**Expected behavior**
Optimally, the glob pattern `/api/servicelog*` should match `/api/servicelog` and `/api/servicelog/whatever` and should not match `/api/servicelogqwer`.
Not because of some standard wildcard semantics, but because that's what we need when writing routes.
If I wanted to match only the stem, then it's `/api/servicelog` and it's working fine.
If I wanted to match only the sub-paths, then it is `/api/servicelog/*`, and if it's a rewrite rule (e.g. to `/api/servicelog_star`), then it works fine. Although this way I'll have an unwanted new API endpoint - namely the target of the rewrite, so I would've rather welcomed a `"handler": ""` instead of the rewrite...
If I wanted to match both the stem and the sub-paths, then I could write `/api/servicelog*`.
And if I'm just dreaming blue sky :D, then it could even be `/api/servicelog/{id:int}/details/{attribute:alpha?}`...
**Device info (if applicable):**
- OS: Linux
- Browser: curl
- Version: 7.81.0
**The workaround that works**
`staticwebapp.config.json`:
```
{
"trailingSlash": "auto",
"routes": [
{
"route": "/api/servicelog/*",
"methods": ["GET", "PUT"],
"rewrite": "/api/servicelog"
},
{
"route": "/api/servicelog",
"methods": ["GET", "PUT"]
}
]
}
```
`function.json`:
```
"bindings": [
{
"direction": "in",
"type": "httpTrigger",
"route": "servicelog/{id:int?}",
"methods": ["get", "post"],
"name": "req",
"authLevel": "function"
},
{
"direction": "out",
"type": "http",
"name": "$return"
}
],
"scriptFile": "index.js"
}
```
This way both the stem-only and the request param works, and the literal wildcards (like `/api/servicelogqwerqwer`) don't.
So the situation *does have a solution*, just the non-slash-following-asterisk glob is meaningless.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.