ExpressJS multiple routes being hit at the same time - javascript

I'm setting up my routes for an expressjs app, and I'm seeing 2 routes being executed when I hit one endpoint. Here is my code:
app.get("/forgot-password", (req, res) => {
....
});
app.get("/:modelName/:id?", (req, res) => {
....
});
I get that the second one essentially will catch everything if the first one is not a match. But I was under the impression that once one route is matched, no others are ran. The correct output is showing in the browser, but I'm seeing errors from the second route show up in my console.
Is there any way to prevent this other than putting some type of prefix to the second route? (making it /model/:modelName...)

Be sure to end your request with req.end, otherwise the request object will get passed to the next middleware in the stack.
Or be sure to call a method that calls req.end, such as res.redirect() or res.send.

Related

Express.js: send results after next() is called

I have an app that enables users to define their own routes on the fly. And I still want to display an custom 404 message, so in the last middleware I do this:
app.use((req, res, next) => {
// ...normal logic
// check for user defined routes
next()
// if res is not written, i.e. request not processed by user defined routes
if (!res.writableEnded) {
res.status(404).send(`not found!`)
}
})
However, I got
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
. How can I implement this?
There is no way for middleware to know if a subsequent route handler is going to pick up the path.
You need to define it last, really last, after any user defined routes.
Then you need to not call next().

ExpressJS - How to jump to the next middleware which has initial url defined

Example code:
app.use('/list-product', (req, res, next) => {
// Do stuff
next();
})
app.use('/add-product', (req, res, next) => {
console.log("I'm here")
})
Somehow it doesn't log "I'm here'", which means next() call doesn't work.
But if I change '/add-product' to '/' or I remove it at all, it works. Why is that?
How can I jump to the next middleware which has initial url on it as the example above?
It sounds like you don't quite understand that when you put a path in front of the middleware, the URL must a least be a partial match for that path for that middleware to be called at all.
So, when you do a request for /list-product, that will match your /list-product middleware which will then call next(). That will continue on the middleware chain looking for other middleware handlers that match the /list-product path. When it gets to your next middleware for /add-product, that doesn't match /list-product so it is skipped (not called).
If you change app.use('/add-product', ...) to app.use('/', ...) or to app.use(...) with no path, then those last two are matches for /list-product so they will get called. The / middleware is a partial match (for all URLs) and middleware with no path will be called for all URLs. app.use() runs for partial matches. The more specific request handlers like app.get() and app.post() require a more complete match.

Using a POST request inside a GET request's call back (Closures)

I will demonstrate my problem with this simplified code:
app.get('/test', (req, res) => {
let x = req.query.someVar;
app.post('/test', (req, res) => {
console.log(x);
});
res.send(`Hello ${req.query.someVar}`);
});
The first time this code runs, the POST callback function saves a reference to x which is whatever I pass as query parameters. if I change the query parameters, send another GET request it will be updated in the server's response i.e.res.send(Hello ${req.query.someVar}); but a POST request will still log the original x value to the console.
Why is it behaving this way? I have tried many things like passing by objects and through other functions, etc..
I am familiar with how closures work, but obviously not entirely as this is most definitely a problem with the POST call back preserving the value of the query parameters and not updating them.
Thanks.
I'm not sure what you are trying to do. No one defines a POST inside of a GET, they do that at the root level, unless you want the GET request to change the behavior of your server. app.post means 'add a new route to handle a POST'. Perhaps you wanted to actually send an HTTP request from the GET handler?
If you want the behavior to change maybe just handle the POST at the root level and set a global flag in the GET handler to indicate that POST should do something different with subsequent requests.

Conflicts between endpoints in Node.js with express application

First of all, i have searched the solution to this problem and i didn't found anything. Sorry if it's duplicated.
I have in my express+node.js app two endpoints like this:
// Gets a tweet by unique id
app.get('/tweets:id', function(req, res, next) {
// Response management
});
// Gets mentions of user unique id
app.get('/tweets/mentions', function(req, res, next) {
// Response management
});
The problem is that requesting a GET petition to "/tweets/mentions", is attended first by "/tweets/:id" and later by "/tweets/mentions", making a conflict.
I have tried to change the declaration order of the endpoints, but always the request is attended by both endpoints.
Also I have tried things like "/tweets::mentions", but I need to access the endpoint via "/tweets/mentions", and I suppose there is a possible way.
How can i resolve this conflict?
Thanks.
Are you using next() in one of the handlers?
next() passes control to the next matching route, so in your example, if one of them is called and inside it you call next(), the other one will be called.
I allways recommend to use 'Router' if you have more than one base path because it helps you to keep it organized.
You can resolve the conflict by checking the value of req.params.id in the "tweet by id" handler.
For routes with additional parameters is always recommended to not use the same base path of other routes.
Something like could work for you:
app.get('/tweets/users/:id', function(req, res, next) {
// Response management
});
// Gets mentions of user unique id
app.get('/tweets/mentions', function(req, res, next) {
// Response management
});

Multiple routes in node.js and URL endpoints

app.use('/api', require('./api'));
app.use('/', require('./cms'));
The first route is for my public api, the second is the cms dashboard. But this will not work, because localhost:80/api will still load the second route too.
How to solve this? I know I can do app.use('/cms', require('./cms')); but the route would be localhost:80/cms/blog which is not fine for me.
I think the function you pass to the app.use has 3 parameters, the third one being next() callback, which calls the next middleware.
If you define your function as below, and don't call next, then it shouldn't trigger the next middleware( route too perhaps ).
app.use('/api', function(req, res, next) {
require('./api');
});
Whatever your require'd file contains, it probably receives the "next" function as its parameter. Dont call it.
update: Also, in your middleware , call res.end() to quit other routes
What's in your ./cms file? It might be that the server isn't closing the response, so it continues on to the next route.

Categories