How to remove or replace callbacks for a specific path - node.js

I tried to replace the / path with another callback:
app.get('/', (req, res) => res.send('Hello World!'))
app.get('/', (req, res) => res.send('404'))
But when I navigate to / path it still responds with Hello World! instead of 404, so that means that the callback was not replaced. So is there any way to do this?
Clarification:
What I actually want to do is to delete routes at runtime, but replacing callbacks with something that respond with say 404 would also do the trick.

It's not clear from your question, but it looks like you have both routes present in your code. If that is the case, then only the first one will be used.
If you are trying to set up some sort of dynamic routes (ie. replace the route handler completely after the application starts), I'm not sure that is possible in Express. According to this comment on deleting Express routes at runtime, it appears that the routes are optimized when the application is first initialized and there is no easy way to change them after that.
If you need a route to behave differently at runtime, the way to do it is in the route callback. For example:
app.get('/', (req, res) => {
// test something & respond accordingly
if (req.query.someValue === 'do this') {
return res.send('Hello world');
}
// otherwise, return a 404 error
return res.status(404).send('No way, man!');
});

Related

Order of route precedence express 3 vs 4

Accord to a book for express3. In the following case, http://localhost:3000/abcd will always print "abc*", even though the next route also matches the pattern.
My question is work in the same way for express4 ?
app.get('/abcd', function(req, res) {
res.send('abcd');
});
app.get('/abc*', function(req, res) {
res.send('abc*');
});
Reversing the order will make it print "abc*":
app.get('/abc*', function(req, res) {
res.send('abc*');
});
app.get('/abcd', function(req, res) {
res.send('abcd');
});
The first route handler that matches the route is the one that gets called. That's how Express works in all recent versions. You should generally specify your routes from more specific to less specific and then the more specific will match first and the less specific will catch the rest.
If you want a handler to see all matches and then pass things on to other handlers, you would generally use middleware:
// middleware
app.use("/abc*", function(req, res, next) {
// process request here and either send response or call next()
// to continue processing with other handlers that also match
next();
});

Make dynamic path in node and express js

I am trying to make route dynamic like /review-{title}-{id}
, but causing error don't know why, Also if user enter the wrong params than how to handle that.
My client requirement is like above, I am not good in node and express please anyone suggested how to make routes like above.
Also if I needed to make route like this /review/:title/:id format than how can I make like that.
I am trying but it redirect me out to the 404 page,
Please find my existing code details inside,
server.js
this is working..
app.get('/review', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/review.html'));
});
but not this one..
app.get('/review-*-*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/review.html'));
});
Also not this one working
app.get('/review/*/*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/review.html'));
});
This is 404 page which call evrytime while accessing dynamic pages
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/404.html'));
});
Check out the syntax for routes in Express.
In most cases you're better off using route params, e.g.:
app.get('/review/:title/:id', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/review.html'));
});
Some more flexibility (but more opaque for most developers) would be to match on regex.
I think you can put a * in the middle of words (they give an example like '/abc*def', but I'm not sure how nicely that plays with the other things you're doing, and I don't think you can have multiple *'s in the pattern if you do that.)

Express 4: router syntax

I am using Express 4 with the new router. At least one thing continues to confuse me, and it is a syntax problem - I am wondering if there is a regex that can do what I want. I have a standard REST api, but I want to add batch updates, so that I can send all the info to update some users models with one request, instead of one PUT request per user, for example. Anyway, I currently route all requests to the users resources, like so:
app.use('/users, userRoutes);
in userRoutes.js:
router.get('/', function (req, res, next) {
//gets all users
});
router.put('/:user_id', function (req, res, next) {
//updates a single user
});
but now I want a route that captures a batch request, something like this:
router.put('/Batch', function (req, res, next) {
//this picks up an array of users from the JSON in req.body and updates all
});
in other words, I want something which translates to:
app.use('/usersBatch, function(req,res,next){
}
...but with the new router. I can't get the syntax right.
I tried this:
app.use('/users*, userRoutes);
but that doesn't work. Does anyone know how to design this?
I'm guessing that the call to [PUT] /users/Batch is being picked up by the [PUT] /users/:user_id route. The string /:user_id is used as a regular expression causing it to also collect /Batch.
You can either move /Batch before /:user_id in the route order, refine the regex of /:user_id to not catch /Batch or change /Batch to something that won't get picked up too early.
(plus all the stuff Michael said)
REST doesn't include a POST as a list syntax. That's because each URL in REST point to an individual resource.
As an internet engineer I haven't seen any bulk PUTs or POSTs, but that said, it's your app, so you can make whatever API you like. There are definitely use cases for it.
You'll still need to describe it to Express. I would do it like this:
var express = require('express');
var router = express.Router();
router.get('/', function (req, res) {}); // gets all users
router.post('/:user_id', function (req, res) {}); // one user
router.put('/:user_id', function (req, res) {}); // one user
router.patch('/:user_id', function (req, res) {}); // one user
router.delete('/:user_id', function (req, res) {}); // one user
app.use('/user', router); // Notice the /user/:user_id is *singular*
var pluralRouter = express.Router();
pluralRouter.post('/', function (req, res) {
// req.body is an array. Process this array with a foreach
// using more or less the same code you used in router.post()
});
pluralRouter.put('/', function (req, res) {
// req.body is another array. Have items in the array include
// their unique ID's. Process this array with a foreach
// using +/- the same code in router.put()
});
app.use('/users', pluralRouter); // Notice the PUT /users/ is *plural*
There are other ways to do this. Including putting comma-delimited parameters in the URL. E.g.
GET /user/1,2,3,4
But this isn't that awesome to use, and vague in a PUT or POST. Parallel arrays are evil.
All in all, it's a niche use case, so do what works best. Remember, the server is built to serve the client. Figure out what the client needs and serve.

in express how multiple callback works in app.get

I am newbie in node so please forgive me if i am not getting obvious.
In node.js express application for app.get function we typically pass route and view as parameters
e.g.
app.get('/users', user.list);
but in passport-google example I found that they are calling it as
app.get('/users', ensureAuthenticated, user.list);
where ensureAuthenticated is a function
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login')
}
In short this means there are multiple callbacks which while running are called in series. i tried adding couple of more functions to make it look like
app.get('/users', ensureAuthenticated, dummy1, dummy2, user.list);
and i found ensureAuthenticated, dummy1, dummy2, user.list is getting called in series.
for my specific requirement i find calling functions sequentially in above form is quite elegant solution rather that using async series. can somebody explain me how it really works and how i can implement similar functionality in general.
In Express, each argument after the path is called in sequence. Usually, this is a way of implementing middleware (as you can see in the example you provided).
app.get('/users', middleware1, middleware2, middleware3, processRequest);
function middleware1(req, res, next){
// perform middleware function e.g. check if user is authenticated
next(); // move on to the next middleware
// or
next(err); // trigger error handler, usually to serve error page e.g. 403, 501 etc
}

Low Priority Express.js app.get('/route');

Is there a way to register an express.js app.get() call with a lower priority?
For example,
app.get('*', function(req, res) {});
app.get('/page', function(req, res) {});
Would there be a way to specify a lower priority on that first call so that it is at the bottom of the route lookup, allowing the later called path to be checked first, effectively as if the first line of code was executed after the second line of code?
I just had a quick look at Express' source code and it does not seem you can set any kind of priority when you add routes. Routes are always matched by order of creation. In your example, it will first try to match '*', then '/page'.
However, you can ask Express to resume matching after you are done:
app.get('*', function (req, res, next) {
// run some tests on the request
// ...
// finally, resume matching
next();
});

Resources