jeremydaly / lambda-api

Lightweight web framework for your serverless applications
https://serverless-api.com
MIT License
1.41k stars 125 forks source link

Nested register and wildcards sometimes mess up #179

Open slootjes opened 3 years ago

slootjes commented 3 years ago

I'm using register() on multiple depths, to illustrate it's something like this:

api.js:

const api = require('lambda-api')({
    base: '/api'
});

api.register(require('./api/user'), { prefix: '/me' });

api/user.js:

module.exports = (api, opts) => {
    api.register(require('./user/app'), { prefix: '/apps' });

api/user/app.js:

module.exports = (api, opts) => {

    api.get(':app/data', async (req, res) => {
        // code
    });

    api.get(':app/data/:scope', async (req, res) => {
        // code
    });

    api.get(':app/data/:scope/:key', async (req, res) => {
        // code
    });

    api.delete(':app/data/user/:key', async (req, res) => {
        // code
    });

    api.put(':app/data', async (req, res) => {
        // code
    });

    api.put(':app/data/user/:key/:value', async (req, res) => {
        // code
    });
}

When I do a GET '/api/me/apps/myapp/data/user' which should match the route ':app/data/:scope/:key' however it generated this error:

MethodError: Method not allowed at REQUEST.parseRequest (/var/task/node_modules/lambda-api/lib/request.js:247:13) at API.run (/var/task/node_modules/lambda-api/index.js:220:21) at Runtime.module.exports.handle [as handler] (/var/task/functions/controller/api.js:17:22) at Runtime.handleOnce (/var/runtime/Runtime.js:66:25) { method: 'GET', path: '/api/me/apps/myapp/data/user' }

When rendering a full list of routes, this is returned:

╟──────────┼─────────────────────────────────────────────────────────────────────────╢
║  PUT     │  /api/me/apps/:app/data                                                 ║
╟──────────┼─────────────────────────────────────────────────────────────────────────╢
║  GET     │  /api/me/apps/:app/data                                                 ║
╟──────────┼─────────────────────────────────────────────────────────────────────────╢
║  DELETE  │  /api/me/apps/:app/data/user/:key                                       ║
╟──────────┼─────────────────────────────────────────────────────────────────────────╢
║  PUT     │  /api/me/apps/:app/data/user/:key/:value                                ║
╟──────────┼─────────────────────────────────────────────────────────────────────────╢
║  GET     │  /api/me/apps/:app/data/:scope                                          ║
╟──────────┼─────────────────────────────────────────────────────────────────────────╢
║  GET     │  /api/me/apps/:app/data/:scope/:key                                     ║
╟──────────┼─────────────────────────────────────────────────────────────────────────╢

So I'd say it should work just fine however it doesn't. However when I remove the "DELETE" and "PUT" methods from code, the GET route starts working. So it seems like the matching doesn't fully work when using nested routes.