expressjs: how can I use bodyParser only for a specific resource? - node.js

I am using expressjs, I would like to use the body Parser only for specific resource, how can I do that?

app.use() allows you to specify a "mount path", as well as which middleware to mount, so you should be able to get away with;
app.use('/foo', express.bodyParser);
As express.bodyParser returns a function whose signature is req, res, next (as with all middleware), this seems analagous to adding it as a handler to a resource;
app.get('/foo', express.bodyParser);
app.get('/foo', function (req, res, next) {
// req has been parsed.
});

#Matt answer is good, you can optimize its syntax by writing:
app.get('/foo', express.bodyParser, function (req, res, next) {
// parsed request
});

Related

Conditionally serve React static files with Node (express.static)

app.use(function (req) {
if (myCondition(req)) {
express.static(`${__dirname}/REACT_APP_1`);
} else {
express.static(`${__dirname}/REACT_APP_2`);
}
});
Trying to serve different builds depending on the condition but it does not seems to be working as expected, I have already searched but nothing seems to be matching my condition, is there anything I'm doing wrong?
express.static() returns a middleware function. That middleware function has to get called while processing a specific route in order to actually do something useful. You were creating the middleware function, but never actually calling it so you never saw any results.
You could fix that like this:
// create our two express.static() middleware handlers
const handler1 = express.static(`${__dirname}/REACT_APP_1`);
const handler2 = express.static(`${__dirname}/REACT_APP_2`);
app.use(function (req, res, next) {
if (myCondition(req)) {
handler1(req, res, next);
} else {
handler2(req, res, next);
}
});
Note, I pulled the creation of the two express.static() handlers out of the app.use() body because there is no need to create them over and over inside of app.use(). You can create each of them once and then just use the appropriate one according to your conditional by calling it and passing it the (req, res, next) arguments for the current request.

node express: is path always optional?

According to the docs for express, the path parameter is optional for app.use, so to apply the middleware to any incoming request you can write:
app.use(function (req, res, next) {
res.send('ANY request');
next();
});
But for app.get the path parameter is apparently not optional, so to apply the middleware to any incoming GET request you have to write:
app.get('/', function (req, res, next) {
res.send('GET request');
next();
});
But I find that it doesn't complain if I do miss out the path:
app.get(function (req, res, next) {
res.send('GET request');
next();
});
So, are the above two definitions equivalent, or is the second one doing something different to the first one?
I'm also not sure of the difference between specifying / or * as the path:
app.get('*', function (req, res, next) {
res.send('GET request');
next();
});
So, in summary, is there any difference between app.get('/', fn) and app.get('*', fn) and app.get(fn)?
Somewhat confusingly, there are two methods called app.get:
https://expressjs.com/en/4x/api.html#app.get
One is the converse to app.set, the other is the one for handling GET requests. In practice JS only allows a single method, so internally Express checks how many arguments are passed to work out which one you meant:
https://github.com/expressjs/express/blob/351396f971280ab79faddcf9782ea50f4e88358d/lib/application.js#L474
So while using app.get(fn) might not complain, it won't actually work as a route because it'll be treating it as the other form of get.
The difference between app.get('*', ...) and app.get('/', ...) is that the * will match any path whereas / will only match the exact path / (and nothing more). This is different from app.use, where the path is treated like a 'starts with'.
You may find the answer I gave here helpful to understand how paths differ between get and use: Difference between app.use and app.get *in proxying*.

path treated differently between app.use() and app.get()

How come when I do a GET request on /foo, my request passes through the first middleware function in example A, but bypasses it in example B ?
Example A
GET '/foo"
app.use('/', function(req, res, next) {
console.log("req passes through here");
next();
}
app.get('/foo', function(req, res, next) {
console.log("then req passes through here");
}
Example B
GET '/foo"
app.get('/', function(req, res, next) {
console.log("this part is bypassed...");
next();
}
app.get('/foo', function(req, res, next) {
console.log("then req passes through here");
}
app.use() and app.get() use the same path argument.
So how come the middleware mounted on / in not executed in example B ?
app.use() instructs the app to use the specified path for all methods (GET, PUT, POST, etc) on all calls. Specifically app.use:
Mounts the specified middleware function or functions at the specified path: the middleware function is executed when the base of the requested path matches path.
While app.get() instructs it to use the path for that specific method (GET) for that specific path only.
Routes HTTP GET requests to the specified path with the specified callback functions.

Node.js matching the url pattern

I need an equivalent of following express.js code in simple node.js that I can use in middleware. I need to place some checks depending on the url and want to do it in a custom middleware.
app.get "/api/users/:username", (req,res) ->
req.params.username
I have the following code so far,
app.use (req,res,next)->
if url.parse(req.url,true).pathname is '/api/users/:username' #this wont be true as in the link there will be a actual username not ":username"
#my custom check that I want to apply
A trick would be to use this:
app.all '/api/users/:username', (req, res, next) ->
// your custom code here
next();
// followed by any other routes with the same patterns
app.get '/api/users/:username', (req,res) ->
...
If you only want to match GET requests, use app.get instead of app.all.
Or, if you only want to use the middleware on certain specific routes, you can use this (in JS this time):
var mySpecialMiddleware = function(req, res, next) {
// your check
next();
};
app.get('/api/users/:username', mySpecialMiddleware, function(req, res) {
...
});
EDIT another solution:
var mySpecialRoute = new express.Route('', '/api/users/:username');
app.use(function(req, res, next) {
if (mySpecialRoute.match(req.path)) {
// request matches your special route pattern
}
next();
});
But I don't see how this beats using app.all() as 'middleware'.
You can use node-js url-pattern module.
Make pattern:
var pattern = new UrlPattern('/stack/post(/:postId)');
Match pattern against url path:
pattern.match('/stack/post/22'); //{postId:'22'}
pattern.match('/stack/post/abc'); //{postId:'abc'}
pattern.match('/stack/post'); //{}
pattern.match('/stack/stack'); //null
For more information, see: https://www.npmjs.com/package/url-pattern
Just use the request and response objects as you would in a route handler for middleware, except call next() if you actually want the request to continue in the middleware stack.
app.use(function(req, res, next) {
if (req.path === '/path') {
// pass the request to routes
return next();
}
// you can redirect the request
res.redirect('/other/page');
// or change the route handler
req.url = '/new/path';
req.originalUrl // this stays the same even if URL is changed
});

Can I pass data through the next function in Express?

In using Express, I have a route like:
app.get('*', function (req, res, next) {
// no route is matched
// so call next() to pass to the static middleware
next();
});
There's another route that is something like app.get('/myroute', function(req, res, next)...
Can I pass information through to that route from the first one via next?
Thanks #amakhrov. I can use res.locals and store information.

Resources