I'd like to isolate a piece of code that would inspect either req.params
or req.body
for a value that is required on every request. What I'm finding is that if I try to access those values before app.use(app.router)
then the request hasn't been parsed to include those objects. If I try to insert the middleware after app.use(app.router)
then it gets skipped all together.
What can I do to work on these values in one place so that the work is ready to be used by downstream routes and models?
Middleware functions are functions that have access to the request object ( req ), the response object ( res ), and the next function in the application's request-response cycle.
The req. params property is an object that contains the properties which are mapped to the named route "parameters". For example, if you have a route as /api/:name, then the "name" property is available as req.params.name. The default value of this object is {}.
The req object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on.
The req. query property is an object containing the property for each query string parameter in the route.
Just run the middleware inline with each route,
const middleware = (req, res, next) => {
console.log(req.params.id);
next();
};
app.get('/test/:id', middleware, (req, res) => {
res.send('hi');
});
You cannot do what you are trying to do. https://github.com/strongloop/express/issues/2088 explains this very clearly.
I have been trying to do what you are trying to do for some time, with no success. I finally tracked down this issue in github.
Since my original answer won't obtain route parameters from the URL, e.g. /things/:foo
(although it will get querystring and req.body params), it won't work the way we want. But another option would be to write a wrapper function that does what you need, and apply it to your route middleware:
function checkForParam (fn) {
return function(req, res, next) {
if (req.param('foo') != 'bar') {
return res.send(403, 'No way Jose!');
}
fn (req, res, next);
};
}
Then add routes with:
app.get('/things/:foo', checkForParam(function(req, res, next) {
// your middleware code here
});
This will run the check and proceed to your custom route middleware only if it passes muster.
I like this way:
const controller = function (name, method) {
return function (req, res) {
// COERCE ID
if (req.method === 'GET' || req.method === 'DELETE') {
var _id = req.params && req.params._id || false
if (/^[0-9a-f]{24}$/.test(_id)) {
req.params._id = new ObjectID(_id)
}
else if (_id) {
return res.status(404).send('Page not found.')
}
}
require('./api/' + name + '.js')[method](req, res)
}
}
Then:
app.get('/api/post/:_id', controller('posts', 'get'))
Tried a simple core level workaround to get the URL params in router before proceeding into router
I need to validate the URL param id where it is an project id and to check respective user has access to it or not
And i don't want to use it in all routes as middleware so used split
function to extract the project id which is in URL params
router.use(apiauthenticated,(req,res,next)=>{
try {
//req.params.projectid
let temp_projectid=req.originalUrl.split("/") //Getting all endpoints and params
let last_element=temp_envid[temp_envid.length-1] //Get last element from array for URL params
let projectid =last_element.includes("?") ? last_element.split("?")[0] : last_element //Returning URL params with or without query params
if(projectid === "" ){
//if it is null throwing error
throw "Please provide required projectid";
}
//Db validation here with projectid
next();
} catch (error) {
res.status(400).send(error);
return null;
}
})
apiauthenticated
is the middleware to validate the API Key
Used last_element.includes("?") ? last_element.split("?")[0] : last_element
for handling the query params
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With