Reputation: 3335
I have a .htaccess as follows and some rules are conflicting - I need to somehow make a condition so they don't
RewriteEngine On
RewriteRule ^search$ results_template.php [L]
RewriteRule ^load-([a-z0-9-]+)$ index.php?key=$1 [L]
RewriteRule ^([a-z0-9-]+)$ http://domain.com/share/index.php?key=$1 [L]
The .htaccess file is located at http://domain.com/directory/.htaccess
The first rule is supposed to just rewrite the name search
to results_template.php
and stop processing more rules
http://domain.com/directory/search
loads
http://domain.com/directory/results_template.php
The second rule is supposed to take the abcdef-1
from
http://domain.com/directory/load-abcdef-1
and send it as a parameter to
http://domain.com/directory/index.php?key=abcdef-1
and then stop processing rules.
The third rule is supposed to take the abcdef-1
from
http://domain.com/directory/abcdef-1
and send it as a parameter to
http://domain.com/share/index.php?key=abcdef-1
and then stop processing rules.
The problem I'm having is no matter how I try to make these play nicely together whenever I request http://domain.com/directory/search the third rule is invoked and I'm redirected.
I'm sure it's just complete tiredness or complete stupidity but I've been at this small step for too many hours now so any help would really be good. Thanks
Upvotes: 2
Views: 329
Reputation: 30496
Your problem is what @Jan explained that when the first rewrite id done search
becomes results_template.php
. To understand it fully I will add that the [L]
tag on the rewrite is really stoping the rewrite and pushing the resulting path to Apache but in fact an internal redirection is performed in apache and mod-rewrite is re-applied after that internal redirection.
It's the hardest thing to understand with mod-rewrite. Using RewriteLog and RewriteLogLevel may help you greatly to detect such problems when dealing with theses not so simple rules.
No the solution provided by Jan will work but a more generic solution exists. If you want your rules to be applied only once, only on the url provided by browsers, and if you are not chaining several layers of redirections then the simpliest way of ensuring your rules is to prevent them from being applied after the internal redirection. And this can be done by checking before each rule that the environ,ent variable REDIRECT_STATUS is empty
# prevent this rule from being applied after first pass
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ...
EDIT
But I've just been reading @baynezy (+1) answer and the [NS] or [nosubreq] tag seems to be doing the same thing. You should try it also.
Upvotes: 1
Reputation: 7066
You need to add the [NS]
flag to third rule. This makes it not fire on internal sub requests.
Upvotes: 1
Reputation: 43169
You will need RewriteConds:
RewriteEngine On
RewriteBase /directory
RewriteRule ^search$ results_template.php [L]
RewriteRule ^load-([a-z0-9-]+)$ index.php?key=$1 [L]
RewriteCond %{QUERY_STRING} !^results_template.php
RewriteRule ^([a-z0-9-]+)$ http://domain.com/share/index.php?key=$1 [L]
E.g. a user requests /search, then the query is transformed to results_template.php. With this new query /results_template.php all rules are checked again and of course the last rule fits as it is the most general one.
Upvotes: 1