I am working with nodejs/express. I want to do the same thing for a route, for GET and POST http requests.
I am doing this:
app.get('/', function(req, res) {
// Some code
});
app.post('/', function(req, res) {
// Same code
});
Is there a way to refactor get and post in the same callback ?
Thanks
Or you can use all, if your site doesn't use any other methods in particular:
app.all('/', handler)
This seems like a very odd requirement. If the behavior is exactly the same just specify one function to handle both:
function myHandler(req, res) {
// Some code
}
app.get('/', myHandler);
app.post('/', myHandler);
A bit old question but still facing today.
If you want to expose the api for all method with the same handler:
function sameHandler(req, res) {
// do something here
}
app.all('/', sameHandler);
If just wanna use the same route but with different handlers:
function getHandler(req, res) {
// do something here
}
function postHandler(req, res) {
// do something here
}
function deleteHandler(req, res) {
// do something here
}
app.route('/').get(getHandler).post(postHandler).delete(deleteHandler);
Related
Does anyone know if it's possible to get the path used to trigger the route?
For example, let's say I have this:
app.get('/user/:id', function(req, res) {});
With the following simple middleware being used
function(req, res, next) {
req.?
});
I'd want to be able to get /user/:id within the middleware, this is not req.url.
What you want is req.route.path.
For example:
app.get('/user/:id?', function(req, res){
console.log(req.route);
});
// outputs something like
{ path: '/user/:id?',
method: 'get',
callbacks: [ [Function] ],
keys: [ { name: 'id', optional: true } ],
regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
params: [ id: '12' ] }
http://expressjs.com/api.html#req.route
EDIT:
As explained in the comments, getting req.route in a middleware is difficult/hacky. The router middleware is the one that populates the req.route object, and it probably is in a lower level than the middleware you're developing.
This way, getting req.route is only possible if you hook into the router middleware to parse the req for you before it's executed by Express itself.
FWIW, two other options:
// this will only be called *after* the request has been handled
app.use(function(req, res, next) {
res.on('finish', function() {
console.log('R', req.route);
});
next();
});
// use the middleware on specific requests only
var middleware = function(req, res, next) {
console.log('R', req.route);
next();
};
app.get('/user/:id?', middleware, function(req, res) { ... });
I know this is a little late, but for later Express/Node setups req.originalUrl works just fine!
Hope this helps
This nasty trick using prototype override will help
"use strict"
var Route = require("express").Route;
module.exports = function () {
let defaultImplementation = Route.prototype.dispatch;
Route.prototype.dispatch = function handle(req, res, next) {
someMethod(req, res); //req.route is available here
defaultImplementation.call(this, req, res, next);
};
};
req.route.path will work to get the path for the given route. But if you want the complete path including the path of the parent route, use something like
let full_path = req.baseUrl+req.route.path;
Hope it helps
You can take a look at Router().stack, which has all the routes defined. In your middleware you need to manually compare the available routes with the one called to define actions.
I have a server in express and it uses an external api. I would like for each request to that api ('/api/*'), that it appends a query param in the url without to write it for each requests.
app.use(function(req, res) {
req.query.key = process.env.APIKEY;
});
I tried something like that but it doesn't work.
I thought of doing something like :
app.get('/api/stuff', addApiKey, api.stuff);
Is there a better way?
You need to supply your middleware function with a next callback:
function addApiKey(req, res, next) {
req.query.key = process.env.APIKEY;
next();
});
app.get('/api/:endpoint', addApiKey, function(req, res) {
// do your stuff here
});
Does anyone know if it's possible to get the path used to trigger the route?
For example, let's say I have this:
app.get('/user/:id', function(req, res) {});
With the following simple middleware being used
function(req, res, next) {
req.?
});
I'd want to be able to get /user/:id within the middleware, this is not req.url.
What you want is req.route.path.
For example:
app.get('/user/:id?', function(req, res){
console.log(req.route);
});
// outputs something like
{ path: '/user/:id?',
method: 'get',
callbacks: [ [Function] ],
keys: [ { name: 'id', optional: true } ],
regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
params: [ id: '12' ] }
http://expressjs.com/api.html#req.route
EDIT:
As explained in the comments, getting req.route in a middleware is difficult/hacky. The router middleware is the one that populates the req.route object, and it probably is in a lower level than the middleware you're developing.
This way, getting req.route is only possible if you hook into the router middleware to parse the req for you before it's executed by Express itself.
FWIW, two other options:
// this will only be called *after* the request has been handled
app.use(function(req, res, next) {
res.on('finish', function() {
console.log('R', req.route);
});
next();
});
// use the middleware on specific requests only
var middleware = function(req, res, next) {
console.log('R', req.route);
next();
};
app.get('/user/:id?', middleware, function(req, res) { ... });
I know this is a little late, but for later Express/Node setups req.originalUrl works just fine!
Hope this helps
This nasty trick using prototype override will help
"use strict"
var Route = require("express").Route;
module.exports = function () {
let defaultImplementation = Route.prototype.dispatch;
Route.prototype.dispatch = function handle(req, res, next) {
someMethod(req, res); //req.route is available here
defaultImplementation.call(this, req, res, next);
};
};
req.route.path will work to get the path for the given route. But if you want the complete path including the path of the parent route, use something like
let full_path = req.baseUrl+req.route.path;
Hope it helps
You can take a look at Router().stack, which has all the routes defined. In your middleware you need to manually compare the available routes with the one called to define actions.
I have the following code :
app.get('/payment', function(req, res) {
// do lots of stuff
});
now I want to add the following :
app.post('/payment', function(req, res) {
req.myvar = 'put something here';
// now do the same as app.get() above
});
Obviously I want to reuse the code. I tried doing next('/payment') inside the post handler and put it above the get handler, but no luck, probably because they are different VERBs.
What are my options ?
Thanks.
Just lift out the middleware to its own function and use it in both routes.
function doLotsOfStuff (req, res) {
// do lots of stuff
}
app.get('/payment', doLotsOfStuff);
app.post('/payment', function(req, res, next) {
req.myvar = 'put something here';
next();
}, doLotsOfStuff);
I am mimicking another api. I would also like to provide a different (better IMHO) api as well.
// this is url I need to support
api.post('/books/updateBook', function(req, res) {
...
});
// Would also like to support
api.put('/books/:bookId', function(req, res) {
...
});
I could easily do:
var updateBook = function(req, res) {
...
}
// this is url I need to support
api.post('/books/updateBook', updateBook);
// Would also like to support
api.put('/books/:bookId', updateBook);
Perfectly acceptable right? Being new to express I am wondering if there is a more 'express' way to handle this. I know you can use regex, but I am not sure you can map regex across different HTTP verbs (POST vs PUT).
Thoughts?
api.all('/books/:bookId', function (req, res, next) {
if (req.method === 'PUT' || req.method === 'POST) {
//get your groove on
} else {
next();
}
});
You can combine verbs in express, you just use all and examine the method, if it matches, handle the request other wise pass it down the handler chain (with next();).
That being said I think you're doing it right, there's no reason route handlers need to be lamdas.