How to simulate Apache [END] flag on a redirect

301-redirectapache-2.2mod-rewriterewrite

For business-specific reasons I created the following RewriteRule for Apache 2.2.22 (mod_rewrite):

RewriteRule /site/(\d+)/([^/]+)\.html /site/$2/$1 [R=301,L]

Which if given a URL like:

http://www.example.com/site/0999/document.html

Is translated to:

http://www.example.com/site/document/0999.html

That's the expected scenario. However, there are documents which name are only numbers. So consider the following case:

http://www.example.com/site/0055/0666.html

Gets translated to:

http://www.example.com/site/0666/0055.html

Which also matches my RewriteRule pattern, so I end up with "The web page resulted in too many redirects" errors from browsers.

I have researched for a long time, and haven't found "good" solutions. Things I tried:

  1. Use the [END] flag. Unfortunately is not available on my Apache version nor it works with redirects.

  2. Use %{ENV:REDIRECT_STATUS} on a RewriteCond clause to end the rewrite process (L). For some reason %{ENV:REDIRECT_STATUS} is empty all the times I tried.

  3. Add a response header with the Header clause if my rule matches and then check for that header (see: here for details). Seems that a) REDIRECT_addHeader is empty b) headers are can't be set on the 301 response explicitly.

There is another alternative. I could set a query parameter to the redirect URL which indicates it comes from a redirect, but I don't like that solution as it seems too hacky.

Is there a way to do exactly what the [END] flag does but in older Apache versions? Such as mine 2.2.22.

Best Answer

Add a query parameter to the redirect is the best option. It is done quite often for all kinds of reasons.

For example make the rule like this:

RewriteCond %{QUERY_STRING}  !redirected
RewriteRule /site/(\d+)/([^/]+)\.html /site/$2/$1?redirected [R=301,L]

What now happens is that the redirects are to URLs with "?redirected" added to them. And so the rule isn't applied the second time.