Does anyone know how I could define an express route (or very minimal number of routes) to take in search parameters in no specific order?
I'm talking about having some search parameters, e.g. movie details:
- name (e.g. "foo")
- year (e.g. 2015)
- genre (e.g. "comedy")
- type (e.g. "movie", "series", "episode")
- season (e.g. 1)
- episode (e.g. 1)
and be able to take inputs for them in a single URL, e.g.
/search/name/foo/genre/action
or equally:
/search/year/2016/season/5/episode/12/name/bar
I don't want to mandate an order to these parameters because only partial information may be known (i.e. not a value for every parameter), and I wouldn't want to force users to have to know the order given there may be many search parameters eventually.
Two thoughts I've had on this...
(1) Using express's app.use to specify some repeating pattern maybe something like:
/\/search\/(([name|year|type|genre|season|episode])\/(.*))+
and then somehow get access to the captured groups for parameter name and value inside the route handler function
(2) Use express's app.param to define a param for the search param, e.g.
/search/:searchParam/:searchValue
but I'm not sure how I can indicate that these are potentially repeating, and also in the param handler function you only seem to get access to the value being represent by the param itself, not adjoining or related param values, e.g.
app.param('searchParam', function(req,res,next,searchParam) {
var paramRegex = new RegExp('name|year|type|season|episode|genre', i);
if( !paramRegex.test(searchParam) ) {
res.status(400)
.send('URL component for "searchParam" must be like: "'+ paramRegex + '" (got: "'+ searchParam + '")');
} else {
var query = req.query || {};
query[searchParam] = '???'; // no way to access :searchValue here from what I can see?
req.query = query;
next();
}
});
Anyone come across this issue before, and is there a more elegant way to do what I'd like here other than something like (1)?
UPDATE #1:
Ugh! Annoying as hell :(
Turns out that you can't use capturing groups with a quantifier this way in JS - it will only ever capture the last captured group's value (as per this post).
So I had tried to use this:
router.get( /^\/search(?:\/(name|year|type|season|episode|genre)\/(.*?))*$/i, search );
where search
is simply:
function search(req,res) {
console.log('Params: ', req.params);
}
and when I try to access this URL:
.../search/year/2016/season/2/episode/12
what do I get in the console?:
Params: { '0': 'episode', '1': '12' }
Only the last matched group's values. Looks like I'm just going to have to take in the entire URL and parse it "manually".