express
express copied to clipboard
Allow for multiple parameter names in router.param()
Hi,
I just found out about router.param() and immediately started using it in my code. It makes checks based on parameters so darn clean :) Really good job on the inventor of that idea!
While using it i found myself wondering with a url like: "/:year/:month/:day". How can you make a router.param(...) function that is called when exactly those 3 arguments have been provided in the url? Perhaps it is possible, but i haven't seen a way in the documentation.
Since router.param() works on parameter names, i would suggest a feature like the following to allow for an implementation of the above to be possible in router.param().
router.param(['year', 'month', 'day'], (req, res, next, obj) => {
obj.year; // contain the year value
obj.month; // contain the month value
obj.day; // contain the day value
});
I would say that the first array in which the params are provided as string must be the exact order in which they would occur in the app.get('/:year/:month/:day' ...) function;
Is there any technical (or practical) reason why a feature like this wouldn't be possible? What are your thoughts on this?
Best regards, Mark
He @markg85 Can i have some other Details LIke your Total api structure so that I can work with my local Express.js Server
He @markg85 Can i have some other Details LIke your Total api structure so that I can work with my local Express.js Server
What do you mean? I have no further details? The topic i started is a feature request :) I don't have an implementation for that request.
Having briefly looked into the source code of router.param() (which is proto.param() in router/index.js), I noticed that all current router.param() did is push the callback on the router.params[paramName] array, and does nothing else. router.handle(), a not documented method, does the actual work. It calls another internal method router.process_params(), that actually invokes the pushed callbacks on each parameter one by one, sequentially without repeat. From index.js:
proto.process_params = function process_params(layer, called, req, res, done) {
var params = this.params;
//...
function param() {
//...
key = keys[i++];
name = key.name;
//...
paramCallbacks = params[name];
//...
paramCallback();
}
function paramCallback(err) {
var fn = paramCallbacks[paramIndex++];
//...
if (!fn) return param();
try {
fn(req, res, paramCallback, paramVal, key.name);
} catch (e) {
paramCallback(e);
}
}
param();
}
I believe to add the feature you asked may require changing these structures, and I don't feel of that much necessity if you can just give the job to a normal app.use() like methods.
@kevinkassimo Thank you for your response! Could you provide an example for the app.use() version of a "/:year/:month/:day" structure? I don't see how to do that, but that is likely due to just not knowing about it :)
@markg85 req.params will serve as the obj you wanted in normal path matching methods. Thus I believe something like
app.get("/:year/:month/:day", function (req, res, next) {
req.params["year"];
req.params.month;
req.params.day
//...
next();
})
should be good enough. (I should have said app.METHOD(), as app.use() is more likely for middleware and does prefix matching.)
It would be good to have the router.param() accepting multiple middlewares, that will permit us to split our middleware
example:
router.param('userId',
(req: Request, res: Response, next: NextFunction) => {
// Common middleware validating the data
},
(req: Request, res: Response, next: NextFunction) => {
// Middleware to assign the data, etc...
}
)