Reputation: 14236
Here is below my code of route:-
app.get('/server/lead/get/:id?', leadCtrl.get);
app.get('/server/lead/filter/:filterQuery', leadCtrl.get);
As you see above i am using different route to access same controller method leadCtrl.get
.
Now, i want something like route app.get('/server/lead/get/:id?:filter?', leadCtrl.get);
. So, i can get params either req.params.id
or req.params.filter
but only one at a time.
Upvotes: 2
Views: 13226
Reputation: 111296
What you asked in the question is not possible in the form that you describe it.
Now, i want something like route app.get('/server/lead/get/:id?:filter?', leadCtrl.get);. So, i can get params either req.params.id or req.params.filter but only one at a time.
Your router would have no way to differentiate those two parameters. If it got a request to /server/lead/get/X
then what is X? A filter or an ID?
You have few solutions here:
You can either keep using two routes like you did before.
You can use a common parameter for both cases as Robert explained in the comments.
Or you can use what seems to me the perfect solution for your use case - named query parameters - just use a route /server/lead/get
and use query parameters to pass id and the filter.
Example URLs:
/server/lead/get?id=xxx
/server/lead/get?filterQuery=xxx
You will only have to make sure in your handler that only one of those two are set at a time with something like:
if (req.query.id && req.query.filterQuery) {
// respond with error
}
You can even mix the two if you have app.get('/server/lead/get/:id?')
route you can have the id in the route and filterQuery as a query parameter. Now the URLs would be:
/server/lead/get/xxx
(for id)/server/lead/get?filterQuery=xxx
(for filter)For more info see: http://expressjs.com/en/api.html#req.query
If you follow some REST conventions then you can use:
That way you would always know that when you access:
/server/lead/xxx
- then it's one object with ID = xxx/server/lead
- then it's a list of any objects/server/lead?filterQuery=xxx
- then it's a list of objects that match the queryIf you follow the REST conventions for things like this instead of inventing your own, it would be much easier for you to design the routes and handlers, and it would be much easier for other people to use your system.
You may also want to use plural /server/leads
instead of /server/lead
which is common with REST. That way it will be more obvious that leads
is a list and leads/id
is one of its elements.
For more info see:
Upvotes: 5
Reputation: 203241
You have to realize that the following two routes match exactly the same:
app.get('/server/lead/get/:id?', leadCtrl.get);
app.get('/server/lead/get/:filter?', leadCtrl.get);
Express doesn't care about how you name the placeholders, so any requests for /server/lead/get/SOMEVALUE
will always match the first (the one with :id
).
You can add a distinction yourself, by only allowing a parameter to match a particular regular expression. From your code, it looks like :id
should match MongoDB ObjectId's, so you can create a specific match for those:
app.get('/server/lead/get/:id([a-fA-F0-9]{24})?', leadCtrl.get);
If SOMEVALUE
matches an ObjectId, it will call leadCtrl.get
and populate req.params.id
. If you also add another router for "the rest", you can also cover the req.params.filter
case:
app.get('/server/lead/get/:filter?', leadCtrl.get);
As an aside: you're saying that you're passing JSON to the "filter" routes, in the URL. I would strongly suggest using a POST
route for that, and post the JSON as request body content.
Upvotes: 4