Apache mod_rewrite: one RewriteCond to many RewriteRules

Today I decided to resolve a problem in an Apache virtual container rewrites I’d been having for a while. It appeared that RewriteCond was “leaking”.  However, on closer observation (and lots of Googling) it turned out that RewriteCond only applies one RewriteRule that comes immediately after the RewriteCond. I didn’t know that (or I had forgotten it). Either way, it didn’t seem like such a great idea to have to duplicate a lengthy RewriteCond definition half a dozen times for multiple RewriteRules in each group which there are ten (that would’ve been almost hundred duplications – not fun to maintain when the rules change).

Turns out there is a fairly simple trick to achieve exactly what I was looking for: if the RewriteCond is negated and followed by RewriteRule . – [S=n] to skip following n rules, the RewriteRules in essence are only applied when the singular RewriteCond is true. Like so:

RewriteCond %{REQUEST_URI} !^/(pattern1|pattern2|pattern3)(/[0-9]+|/P[0-9]+|)[/]?$ [NC]
RewriteRule . - [S=3]
RewriteRule ^/([^/]*)[/]?$ /index.php/site_embeds/department/$1/X [L]
RewriteRule ^/([^/]*)/([0-9]+)[/]?$ /index.php/site_embeds/article/$2/$1 [L]
RewriteRule ^/([^/]*)/P([0-9]+)[/]?$ /index.php/site_embeds/department_archive/P$2/$1 [L]

Now the last three rules are skipped if the condition is not true or, in reverse: they are applied if the condition is true. In other words, exactly what I was looking for!

9 thoughts on “Apache mod_rewrite: one RewriteCond to many RewriteRules”

  1. Perfect!
    Using this trick to rewrite PNG images to JPG/GIF alternatives for IE6 browsers.

    RewriteCond %{HTTP_USER_AGENT} !MSIEs+6
    RewriteRule . – [S=4]
    RewriteRule ^MAIN_logo.(png|gif)$ /images/MAIN_logo.jpg [NC,L,R]
    RewriteRule ^MAIN_bg.jpg$ /images/MAIN_bg_ie6.jpg [NC,L,R]
    RewriteRule ^((MAIN_[cdm][^_]+|icon|logo|SpryMenuBarCorner)_.*).png$ /images/$1.gif [NC,L,R]
    RewriteRule ^(bg_gradient_.*).png$ /images/$1.jpg [NC,L,R]

  2. This worked great, except for

    RewriteRule . – [S=x]

    Instead, it must be

    RewriteRule .* – [S=3]

    I don’t know if it worked for the above users, but for me, using just a period (.) resulted in the following RewriteRules being used, until I changed it to .*


  3. Sometimes the skip rule is written like so:

    RewriteRule .? – [S=n]

    That essentially takes care of the same thing as an asterisk, i.e. it allows “nothing” for the pattern which is likely the key issue in your configuration. Your situation may occur when you’re matching [with a RewriteRule] a URL without a path (e.g. http://www.somedomain.tld). Since a period requires at least one character, a rule without a question mark (“zero or one times”) or an asterisk (“zero to unlimited times”) attribute would be skipped and so the rules immediately following would be executed.

  4. Great solution, BUT – it seems that using this I can’t access to the atoms defined in the RewriteCond with %1, %2, etc. 🙁

  5. I did not try it, but I think we might have more flexibility with the skip flag instead of this rewrite to dash rule, because with the skip flag you can specify how many rules you skip.

  6. OK, I just tried it. It works. It is not really a different trick. The skip tag is added to a rewrite to a dash. It’s very cool. It can be used to create conditional.

  7. I played arnoud with it a little and wasn’t able to get a RewriteCond to work properly. That’s probably more of a sign of my lack of experience with regex than anything else, but still

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.