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.
Related
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().
I wish to know how can I have both get and post request handled by app.use the way I do it using app.route
app.use('/', (req, res, next) => {
if (isLaunched) {
return next()
}
// You can also render if you want
res.render('coming-soon')
});
How can I handle a post request to this?
According to https://expressjs.com/en/guide/using-middleware.html the syntax you already have is used for any type of HTTP request - including GET and POST. You can detect the method via req.method.
app.use() already handles ALL http methods, including GET and POST. You can see exactly which method it is for any given request by checking req.method.
If you had trouble with some GET or POST when doing this, then please show the specific code and the specific request that it didn't work for. If you didn't try it yet, then just try it as it should work just fine.
Middlewares are mounted using app.use(<middleware-name>) so, you can add it to all routes like you do for bodyParser/CORS etc.
If you want to mount for specific routes you can use
app.post("/example" , middleware, (req,res)=>{
res.send("Hello world")
})
Refer to Use middleware on specific routes
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.
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.
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
});