My urls may either look like /posts/sluggish-slug-postId123
or like /posts/postId123
.
My router currently contains:
router.get('/posts/:slug?-:id([a-zA-Z0-9]+)', function () {...}
but using this regex the -
in between the slug
and the id
is mandatory, which means I can't validate urls that only contain an id
(e.g. /posts/postId123
). How do I make the -
separator optional along with keeping the slug
optional?
Paths that should match
/posts/going-long-for-the-ball-3a6p412
going-long-for-the-ball
3a6p412
/posts/3a6p412
3a6p412
Paths that should not match
/posts/-3a6p412
I couldn't quite get what you wanted but this comes close:
router.get('/posts/:slug([a-z][a-z\-]{0,}-|):id([a-zA-Z0-9]+)', function (req, res) {
The slug
will include the trailing -
if it's present and it will be an empty string if there is no slug. The section [a-z][a-z\-]{0,}
ensures that the slug must start with a character in the range a-z
and can then contain any number of characters from a-z
or -
. If your slugs can contain other characters you'd just need to adapt that part accordingly. Note that I'm using {0,}
rather than *
because of a quirk of how Express routes interprets *
.
The way Express routes get converted to regular expressions is somewhat difficult to follow and there are major changes between Express 4 and 5 that make using complex expressions an unsafe bet for future compatibility. If you want to do something more complicated than the examples given in the documentation I would suggest just using an actual RegExp instead to cut out the unreliable middleman. Alternatively you could skip trying to parse/validate the URL in the route path altogether and do that inside your handler function instead.