I'm having trouble getting my .get() to work. My understanding of .use() vs .get() is that .use() is used for paths we want to apply things to, while .get() is more specific (choosing specific urls to apply to)
In my example, I want to show 'Applies to all pages' to any page number, but if I type in '/28', I want the .get message to show up instead. Right now, I get the .use message even when I go to /28.
router.use('/:id', function(req, res){
console.log("Things " + Date.now());
res.send('Applies to all pages ' + req.params.id);
});
router.get('/28', function(req, res){
res.send('Secret 28 page');
});
The use method is used to employ all the http verb to certain path from your express app or express router. You have to consider the precedence while using use. Here, what is happening is that you have already employed use in your dynamic router as router.use('/:id', ...) which will take get request as well.
You can employ the get router first, so that it only take getrequest in /28 and transfer all the unhandled request to other path.
router.get('/28', function(req, res){
res.send('Secret 28 page');
});
router.use('/:id', function(req, res){
console.log("Things " + Date.now());
res.send('Applies to all pages ' + req.params.id);
});
From the docs:
The order in which you define middleware with router.use() is very important. They are invoked sequentially, thus the order defines middleware precedence.
In your example your '/:id' will take precedence when matching.
So swap the order to fix your example, and in general, define more specific handlers first.
Try switching the order of your .get and use.
ExpressJS goes in sequential order when executing. Read this post for more clarification:
https://derickbailey.com/2016/05/09/in-what-order-does-my-express-js-middleware-execute/
Also, a little unrelated but you can use the .get middleware first, and pass the next step using a third parameter to your callback which is next(), if you haven't known that already.
.use() applies to all the paths regardless of HTTP verb, so in your case it applies to GET, POST, PUT and all the other requests that start with /:id path and app.get("/28") is such a request
Related
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.
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.
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
});