CodeGenieApp / CodeGenieApp/serverless-express
Routing to root path does not work correctly when using nested API resources
Personne n'a encore pris cette issue.
- Langage dominant
- JavaScript
- Étoiles
- 5.3k
- Forks
- 674
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Description
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 <host>/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:
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
v1part is available atevent.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).
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez dans src/event-sources/utils.js, au niveau de getPathWithQueryStringParams, puis reproduisez les routes imbriquées /v1/ et /v1/{proxy+} de SAM API Gateway avec le mapping de chemin de base /routes/v1/. Suivez les champs de l’événement utilisés pour la requête racine, en particulier event.path, event.resource, event.requestContext.customDomain.basePathMatched et event.pathParameters.proxy. C’est terminé lorsque le gestionnaire racine Express reçoit / au lieu du chemin avec espace de noms.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- aws, express, javascript, node.js
- Domaine
- api, backend
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 35/100