I have a route that looks like this:
app.all('/path/:namedParam/*splat?',function(req,res,next){
if(!req.params.length){
// do something when there is no splat
} else {
// do something with splat
}
});
however, this doesn't work - if I call path/foo/bar
it hits the route, but if I call path/foo
, it doesn't.
Is it possible to have an optional splat param, or do I have to use a regex to detect this?
Edit:
to be clearer, here are the requirements I'm trying to achieve:
/path/foo
, (that is what my route originally looked like before I wanted an optional splat). Additionally, in your second example, adding the splat actually negates the optional second param - /path/foo
will not match your second pattern (neither will /path/foo/bar
for that matter...) - one of the more annoying parts of express' router - Jesse 2012-04-05 07:14
/path/:firstParam
and /path/:firstParam/:secondParam/
as two separate routers with a shared controller. no need to make your urls confusin - Jonathan Ong 2012-04-05 16:31
n
endpoints is necessary for the design of the app - I'm not just routing to 1-3 params, it can be any number, so having a limit on number of params is not an option (sure, I could create 10 endpoints, but having express do that work isn't any better than doing it in a route). I can use a regex route to solve my problem (what I'm doing now), but I was hoping to have a readable option - Jesse 2012-04-05 19:18
/path/:param(/:otherOptionalParam)
r3wt 2017-06-18 01:36
This works for /path and /path/foo on express 4, note the *
before ?
.
router.get('/path/:id*?', function(req, res, next) {
res.render('page', { title: req.params.id });
});
/path/foo/bar/bazzle
, req.params.id
will equal foo
, and req.params[0]
will equal /bar/bazzle
, which may trip some people up. A cleaner solution may be to define the path as /path/*?
, which in express 4 will set req.params[0]
to foo/bar/bazzle
, which is probably closer to what you're looking for - Jesse 2015-06-02 06:18
/path/foo/bar
but not /path/foo
. I tried '/path/:id/*
but *
seems to match empty string as well - Franklin Yu 2018-08-22 21:05
I just had the same problem and solved it. This is what I used:
app.get('path/:required/:optional?*', ...)
This should work for path/meow
, path/meow/voof
, path/meow/voof/moo/etc
...
It seems by dropping the /
between ?
and *
, the last /
becomes optional too while :optional?
remains optional.
Will this do what you're after?
app.all('/path/:namedParam/:optionalParam?',function(req,res,next){
if(!req.params.optionalParam){
// do something when there is no optionalParam
} else {
// do something with optionalParam
}
});
More on Express' routing here, if you haven't looked: http://expressjs.com/guide/routing.html
/path/foo/bar
, but not /path/foo/bar/baz
- the *
splat matches .+
, which is necessary for what I'm doing - I've definitely rtfm, doesn't seem to mention it, so maybe it's not possible.. - Jesse 2012-04-04 22:58
Here's the current way I'm solving this problem, it doesn't appear that express supports any number of splat params with an optional named param:
app.all(/\/path\/([^\/]+)\/?(.+)?/,function(req,res,next){
// Note: this is all hacked together because express does not appear to support optional splats.
var params = req.params[1] ? [req.params[1]] : [],
name = req.params[0];
if(!params.length){
// do something when there is no splat
} else {
// do something with splat
}
});
I'd love to have this use named params for readability and consistency - if another answer surfaces that allows this I'll accept it.
The above solutions using optional doesn't work in Express 4. And I tried couple of ways using search patterns, but not working either. And then I found this method and seems fired for unlimited nested path, http://expressjs.com/api.html#router
// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', function(req, res, next) {
// ... maybe some additional /bar logging ...
// to get the url after bar, you can try
var filepath = req.originalUrl.replace(req.baseUrl, "");
next();
});
It's match all /bar, /bar/z, /bar/a/b/c etc. And after that, you can read req.originalUrl, since params are not filled, ex. you can try compare baseUrl and originalUrl to get the remaining path.
I got around this problem by using a combination of a middleware that add trailing slashes to url and router.get('/bar/*?', ...
, which will pick up everything after /bar/
, and return undefined
if it is just /bar/
. If the visitor asked for /bar
, the express-slash
middleware will add a slash to the request and turns the request into /bar/
.
'/path/:firstParam/*'
. If you need it, do'/path/:firstParam/:secondParam?/*'
- Jonathan Ong 2012-04-05 02:53