views:

171

answers:

3

I have a website where various parts parse request URLs by themselves and some don't (e.g. a vBulletin forum). The .htaccess I have to send requests to the appropriates scripts is:

# wiki, shop, admin
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !(.*)\.js
RewriteRule ^wiki/(.*)$ w/index.php?title=$1 [PT,L,QSA]
RewriteRule ^wiki/*$ wiki/ [L,QSA]
RewriteRule ^shop/ /shop/shop.php [NC,L]
RewriteRule ^forum/admincp/pkr/ /forum/admincp/pkr/pkr.php [NC,L]

This doesn't work as I expected. I forgot that the rewrite conditions are only applied to the first rule that follows them. The question is How can I apply those RewriteConditions to all those rules without having to copypaste them 4 times?


What goes wrong is this:

  • /shop/example is rewritten to /shop/shop.php
  • /shop/shop.php is then rewritten again to /shop/shop.php (read: we have an infinite loop). This would not happen if this condition was applied to that rewrite rule, because /shop/shop.php is an actual file:

    RewriteCond %{REQUEST_FILENAME} !-f

So yeah...

+1  A: 

Invert the expression and attach it to a breaking rule:

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} (.*)\.js
RewriteRule ^ - [L]
Gumbo
A: 

or Just make another condition like

RewriteCond %{THE_REQUEST} !shop.php

or even better

RewriteCond %{THE_REQUEST} !(.*)\.php
A: 

I didn't understand Gumbo's answer so here is what I found what works:

Instead of matching something and executing more than one RewriteRule from that test, you can invert your match rule (such as using a ! sign) and if it doesn't find it, skip past X number of rules. Such as:

RewriteCond %{HTTP_HOST} !^www.mydomain.com [NC]
RewriteRule . - [S=2] # Skip the below X lines if the above test passes
RewriteRule ^/images/(.*) /resources/images/$1 [L]
RewriteRule ^/favicon.ico /resources/favicon.ico [L]

So if the HTTP_HOST starts with www.mydomain.com I want the two last RewriteRules to be processed. But what I'm doing is, if the HTTP_HOST does not start with www.mydomain.com, skip the next two rules. The first RewriteRule: . - [S=2] doesn't actually change anything, but the S=2 flag means skip the next X=2 rules.

A little bit of reverse logic if you ask me.

Michael Butler