96

I am using Express to handle a route which is in the format of /articles/:year/:month/:day, where year, month and day are optional.

  • If none of the three params is given, all articles will be returned;
  • If year is given, articles of that year will be returned;
  • If year and month are given, articles of that year and month will be returned;
  • If all three params are given, articles of that year, month and day will be returned.

My question is, how do I make them optional? With the current route I've defined, unless all three parameters are present, it will not be able to be resolved and will fall into the default route.

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
CLDev
  • 1,467
  • 1
  • 15
  • 19
  • You can define multiple routes for the case when a year is present, year and months are present, all parameters are present and none are present , or you can move parameters to query string – Vsevolod Goloviznin Jan 19 '17 at 08:02
  • 1
    You can also make them optional by putting a `?` after them – hjpotter92 Jan 19 '17 at 08:11
  • @VsevolodGoloviznin Thanks for your advices. They are really helpful and they fit well into my use case. I've ultimately chosen the solution from hjpotter92 though as it is also quiet elegant and result in shorter code. Thanks again for your help anyways. – CLDev Jan 19 '17 at 17:32
  • @hjpotter92 Thanks for your advice! Can't believe I've missed such important info when I read through the guide. I'll definitely go RTFM again. Do you want to formally put your answer below? I'll accept it if so. – CLDev Jan 19 '17 at 17:34

3 Answers3

179

The expressjs's guide to routing mentions:

Express uses path-to-regexp for matching the route paths; see the path-to-regexp documentation for all the possibilities in defining route paths. Express Route Tester is a handy tool for testing basic Express routes, although it does not support pattern matching.

Basically, you can use the ? character to make the parameter optional.

/articles/:year?/:month?/:day?
hjpotter92
  • 78,589
  • 36
  • 144
  • 183
  • 2
    It seems that it doesn't work. If you try that route with the route tester, `/articles//1/2` for example with not match. If I use only one optional parameter it works – Andres Espinosa Feb 12 '21 at 16:12
  • @AndresEspinosa did you go through `path-to-regexp`? You can use `*` for any nested paths – hjpotter92 Feb 12 '21 at 17:17
  • Yes, I did. I think `*` is a bad practice because it would match many unexpected paths. Anyway, what you're saying is to use something like `/articles/*` right? I would have to then parse the rest of the path by myself then? – Andres Espinosa Feb 16 '21 at 14:52
  • @AndresEspinosa it depends on how deep the paths you're expecting. – hjpotter92 Feb 16 '21 at 15:12
69

Edited for own purpose of having the 3 different options in one answer. Credit to @hjpotter92 for his regex answer.

With URL Params

With regex

app.get('/articles/:year?/:month?/:day?', function(req, res) {
  var year = req.params.year; //either a value or undefined
  var month = req.params.month;
  var day = req.params.day;
}

Without regex

var getArticles = function(year, month, day) { ... }

app.get('/articles/:year', function(req, res) {
  getArticles(req.params.year);
}
app.get('/articles/:year/:month', function(req, res) {
  getArticles(req.params.year, req.params.month);
}
app.get('/articles/:year/:month/:day', function(req, res) {
  getArticles(req.params.year, req.params.month, req.params.day);
}

Define the 3 paths you want to support and reuse the same function

With Query Params

app.get('/articles', function(req, res) {
  var year = req.query.year; //either a value or undefined
  var month = req.query.month;
  var day = req.query.day;
}

The url for this endpoint will look like this:

http://localhost/articles?year=2016&month=1&day=19
R. Gulbrandsen
  • 3,648
  • 1
  • 22
  • 35
  • Thanks a lot for your help. I think they tackle my use case perfectly (especially the multi-route proposal), just that hjpotter92 has suggested an even simpler solution. Thanks again for your help anyways! – CLDev Jan 19 '17 at 17:36
  • 1
    Also Open API Standards recommends using query parameter for optional parameters. – tbhaxor Jan 23 '21 at 07:48
-6

This type of route is not likely to work because of the underscores in the parameters passed.

app.get('/products/:product_Id/buyers/:buyer_Id', function(req, res) {
  getArticles(req.params.product_Id, req.params.buyer_Id);
}

So i suggest you use the following route system if the route is not working. There you will be able to send multiple parameters.

app.get('/products/:productId/buyers/:buyerId', function(req, res) {
  getArticles(req.params.productId, req.params.buyerId);
}
JackZ
  • 127
  • 1
  • 13