CodeGenieApp / CodeGenieApp/serverless-express

Routing to root path does not work correctly when using nested API resources

Offen
#377 0 Kommentare 6 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
JavaScript
Sterne
5.3k
Forks
676
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

First off, thanks for this great project!

I'm reporting an issue here I ran into when using API Gateway v1 with a proxy resource.

### Repro

I have defined a RestAPI resource triggered on a **nested** root path and subpaths under a `/v1/` path namespace. The SAM template looks like this:

```
Events:
ProxyApiRoot:
Type: Api
Properties:
RestApiId: !Ref ExpressApi
Path: /v1/
Method: ANY
ProxyApiGreedy:
Type: Api
Properties:
RestApiId: !Ref ExpressApi
Path: /v1/{proxy+}
Method: ANY
```

I also have a BasePathMapping defined nesting one level deeper, so the final root path for my app is `/routes/v1/`.

My express app has a handler defined for the root path:

```
router.get('/', (req, res) => { ... }
```

However a request to `/routes/v1/` returns a generic 404 from express. The request is routing correctly through API Gateway to my app, but once it gets to express it can't find a matching handler for the `/` path.

### Debugging

I added a handler for the catch-all route `*` and printed out the currentInvoke to try to track down the problem. I think I narrowed it down to this line:

https://github.com/vendia/serverless-express/blob/4ba9799a6573ea4227939001c3e49e07b75a35ea/src/event-sources/utils.js#L6-L7

The issue is that my request to `/routes/v1/` is being handled by ProxyApiRoot, not ProxyApiGreedy. Since ProxyApiRoot doesn't populate a value for event.pathParameters.proxy, the fallback event.path is used. But unlike pathParameters.proxy, event.path includes the _full path_ including the namespaces. So for a request to the root of my app, serverless-express is interpreting the path as `event.path == '/routes/v1'`, not `event.path == '/'`.

### Solution?

There may need to be more smarts added to `getPathWithQueryStringParams` for stripping out prefixes from the root path.

For example from printing out the currentInvoke I found:
* The base path part is available at `event.requestContext.customDomain.basePathMatched == 'routes'`
* The `v1` part is available at `event.resource = '/v1'`.

Perhaps these can be used to remove `/routes/v1` from the root path when event.pathParameters.proxy is not populated.

### Workaround

In the short term I found a workaround by avoiding root paths altogether. My SAM template now looks like:

```
ProxyApiGreedy:
Type: Api
Properties:
RestApiId: !Ref ExpressApi
Path: /{proxy+}
Method: ANY
```

and I mount all my express routes at v1 explicitly using `app.use('/v1', router)`.

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Beginne in src/event-sources/utils.js bei getPathWithQueryStringParams und bilde dann die verschachtelten /v1/ und /v1/{proxy+} SAM API Gateway-Routen mit dem /routes/v1/-Basispfad-Mapping nach. Verfolge die für die Root-Anfrage verwendeten Event-Felder, insbesondere event.path, event.resource, event.requestContext.customDomain.basePathMatched und event.pathParameters.proxy. Fertig ist es, wenn der Express-Root-Handler / statt des Namespace-Pfads erhält.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
aws, express, javascript, node.js
Bereich
api, backend
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.