Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Route Matching Confusion Between blogs/:id and blogs/create #6244

Closed
mitulgupta72 opened this issue Dec 28, 2024 · 1 comment
Closed

Route Matching Confusion Between blogs/:id and blogs/create #6244

mitulgupta72 opened this issue Dec 28, 2024 · 1 comment

Comments

@mitulgupta72
Copy link

I encountered an issue where defining a route like /blogs/create alongside /blogs/:id causes Express to interpret create as the :id parameter. This behavior leads to errors when handling routes, as Express treats "create" as an ObjectId, which causes issues in MongoDB queries.
Steps to Reproduce:
Set up the following routes:
javascript
Copy code
app.get('/blogs/create', (req, res) => {
res.render('create', { titlex: 'Create a Blog' });
});

app.get('/blogs/:id', (req, res) => {
const id = req.params.id;
Blog.findById(id)
.then((result) => res.render('details', { blog: result, titlex: 'Blog Details' }))
.catch((err) => console.log(err));
});
Start the server.
Navigate to /blogs/create.
Observed Behavior:
The /blogs/create route is not recognized. Instead, Express interprets "create" as the :id parameter, leading to a CastError when attempting to query the database with "create".

Expected Behavior:
The /blogs/create route should take precedence over /blogs/:id since it is more specific.

Potential Solutions:
Enhance route matching to prioritize specific routes over dynamic ones.
Improve the documentation to highlight this behavior and suggest workarounds.
Environment:
Express Version: (e.g., 4.18.2)
Node.js Version: (e.g., 16.20.0)
Platform: (e.g., Windows/Linux)
Screenshot (2032)

@krzysdz
Copy link
Contributor

krzysdz commented Dec 28, 2024

If handler for /blogs/create is declared before the parametrized /blogs/:id it will be called first. That's how route matching works in Express - the first matching handler is used. If you can't move more specific routes above the parametrized ones, you can try detecting those routes and skipping to the next matching handler using next().

const express = require("express");

const app = express();

// This route is declared first, so it has priority over parametrized one
app.get('/blogs/create', (req, res) => {
    res.send('Create a blog');
});

app.get('/blogs/:id', (req, res, next) => {
    // Skip this handler if the url contains non-empty "skip" parameter in query
    if (req.query.skip) {
        next();
        return;
    }
    const id = req.params.id;
    res.send(`Blog with id ${id}`);
});

// This handler will not be called, unless the handler for `/blogs/:id` calls `next()`
app.get('/blogs/unique', (req, res) => {
    res.send('Unique blog');
});

const server = app.listen(0, "127.0.0.1", async () => {
    const {address, port} = server.address();
    for (const path of ["/blogs/create", "/blogs/abc", "/blogs/unique", "/blogs/unique?skip=1"]) {
        const r = await fetch(`http://${address}:${port}${path}`);
        const t = await r.text();
        console.log(`Response from ${path}: ${t}`);
    }
    server.close();
});
$ node index.js
Response from /blogs/create: Create a blog
Response from /blogs/abc: Blog with id abc
Response from /blogs/unique: Blog with id unique
Response from /blogs/unique?skip=1: Unique blog

@IamLizu IamLizu removed the bug label Jan 1, 2025
@IamLizu IamLizu converted this issue into discussion #6252 Jan 1, 2025

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants