Using ExpressJS 4 I'm not able to get a dollar sign to work in URL e.g.
app.post('/foo/$bar', handler);
Cannot POST /foo/$bar
According to RFC dollar sign should be safe character, is it something I'm missing here?
Express urls get converted to regular expressions, and the dollar sign is significant in regexp. You could explicitly pass in a RegExp that has an escaped dollar sign.
In the version of path-to-regexp that Express is using (not sure if this is an issue in the latest version), it looks like the $ is getting inserted into the constructed regular expression literally in the above mentioned case, i.e.:
$ node -pe 'require("path-to-regexp")("/foo/$bar")'
/^\/foo\/$bar\/?$/i
This may be something we can fix in the 0.x line of path-to-regexp, or confirm if this should work/is it is fxed in 1.x. /cc @blakeembrey
Definitely fixed in 1.x, all literals are escaped. In 0.x, it _may_ be possible to escape but we need to be careful not to break existing usages. For example, in the 0.x branch you could do /([\$]) and escaping that directly is a breaking change as you'd result in two backslashes. So it might need to check for existing backslashes before the literal. I feel like the only issue fixing it on 0.x is ambiguous backslashes, would need to think about it for a little bit.
Just for someone who stump into this problem
For me helped for the situation when I needed to get www.odata.com/$metadata worked out:
router.get('/([\$])metadata', function(req, res, next){
})
@hacksparrow do you think we can document this on the API site?
@dougwilson sure, will add it.
@blakeembrey is enclosing with () mandatory? Simply enclosing the escaped $ within [] works just fine.
@hacksparrow Nope, not in 0.x. In 1.x, it is, because there's too many obscure issues otherwise with parsing. However, in the current version Express.js uses it's basically a valid regexp already with minor transformations on the (, ), / and : characters to give meaning. So even just doing /foo\\$ should work.
Most helpful comment
Just for someone who stump into this problem
For me helped for the situation when I needed to get www.odata.com/$metadata worked out: