1

i need a nginx rewrite rule for the following problem:

I have Urls that include several hyphen and eventually underscores

Example request: http://www.example.com/cat/cat2/200-AB---a-12_12-123.312/cat-_-cat/cat/dog---I

would give a 404 error so in need a 301- redirect to:

http://www.example.com/cat/cat2/200-AB-a-12-12-123.312/cat-cat/cat/dog-I

So all underscores should be replaced with hyphens and there should be only one hyphen a time.

short version: replace --- with - and replace _ with - but by replacing _ with - this -_- will become --- and rule one would have to be called again.

Is it possible to to that in one rule? and if not how to do it any other way :)i have absolutely no idea how to do that with nginx

any help appreciated :)

  • 1
    I think it'll be much more flexible if you do it on application side instead of nginx side. – Bibhas Debnath Feb 14 '13 at 20:57
  • You will need a recursive rewrite, nginx rewrites are recursive you need to find the right way for doing it in less than 10 loops. – regilero Feb 15 '13 at 08:51
  • form my understanding the rewrite could could be done in two steps. first replace underscore with hyphen and then replace multiple hyphens with one. but i have absolutly no idea how to do that. sorry for that ;/ – user2025805 Feb 15 '13 at 09:46

1 Answers1

1
% nginx -c $PWD/test.conf
% curl -I localhost:8080/cat/cat2/200-AB---a-12_12-123.312/cat-_-cat/cat/dog---I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.13
Date: Wed, 20 Feb 2013 00:09:50 GMT
Content-Type: text/html
Content-Length: 185
Location: http://localhost:8080/cat/cat2/200-AB-a-1212-123.312/cat-cat/cat/dog-I
Connection: keep-alive

% cat test.conf
events { }

#error_log  logs/error.log debug;

http {
    server {
        listen 8080;
        location /cat/cat2/ {
            # replace up to 3 inconsecutive
            # uderscores per internal redirect
            rewrite "^(.+?)_+(?:(.+?)_+)?(?:(.+?)_+)?(.+)$" $1$2$3$4 last;

            # replace up to 3 inconsecutive multiple
            # hyphens per internal redirect
            rewrite "^(.+?-)-+(?:(.+?-)-+)?(?:(.+?-)-+)?(.+)$" $1$2$3$4 last;

            return 301 $uri;
        }
    }
}
VBart
  • 14,714
  • 4
  • 45
  • 49
  • ok, but did you try with a very very long url with a lot of hypens? Does nginx launch a recursion error? isn't there a way to make theses regex matching an infinite number of replacements? – regilero Feb 20 '13 at 16:06
  • 1
    So, having 3 replaces per iteration this configuration can handle urls with 30 fragments separated by any number of hyphens or underscores. To operate on "infinite number of replacements" you must have infinite resources and infinite time. – VBart Feb 20 '13 at 16:54