Is it possible to normalize "double-dots" URL using nginx?
According to RFC3986 URL like this
http://example.com/catalog/category/goods/../brand/product.html
converted by some UserAgent (curl would be nice example) to http://example.com/catalog/category/brand/product.html
How can I achieve such behavior using nginx rewrite, if my stupid UserAgent can not parse original URL in correct way?
Is it ever possible or not?
Solution 1:
You can replace /./
sequences and /goods/../
sequences with a single /
. For example:
rewrite ^(.*)/\./(.*)$ $1/$2 redirect;
rewrite ^(.*)/(?!\.\.)[^/]+/\.\./(.*)$ $1/$2 redirect;
The /(?!\.\.)[^/]+/
sequence should match any path element that is not another ..
. The above rewrites are recursive and issue 302 responses until all of the /./
and /../
sequences are correctly removed.
Alternatively, the same can be achieved using an internal redirect, by placing rewrite...last
statements within a suitable location
block. For example:
location / {
rewrite ^(.*)/\./(.*)$ $1/$2 last;
rewrite ^(.*)/(?!\.\.)[^/]+/\.\./(.*)$ $1/$2 last;
}
In this case, the URL displayed on the browser's address bar will not be changed.
See this document for details of the rewrite
directive, and this link for details of the negative lookahead assertion.
Solution 2:
As I see nginx normailses URL by default. Quoting documentation:
a normalized URI, after decoding the text encoded in the “%XX” form, resolving references to relative path components “.” and “..”, and possible compression of two or more adjacent slashes into a single slash.
I've tested and it works out of box here (with proxy_pass), or do you have any problems with that?