2

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

Andy Gee
  • 3,149
  • 2
  • 29
  • 44

3 Answers3

1

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.

Jan
  • 42,290
  • 8
  • 54
  • 79
  • Thanks for that, I'd forgotten about it being a new request. It's nearly there now however `http://domain.com/directory/search` is not rewriting to `http://domain.com/directory/results_template.com` if I change the rule (and condition) to `RewriteRule ^search.php$ results_template.php [L]` and request `search.php` instead of just `search` it works. Any ideas? – Andy Gee Mar 24 '12 at 09:16
  • Yes. You forgot the RewriteBase as your urls are generated in a subdirectory. I've edited my example in order for RewriteBase. See an example here: http://playground.rexbooks.com/stack/ and try to append "search" for example (i.e. http://playground.rexbooks.com/stack/search). Is this what you were after? – Jan Mar 24 '12 at 12:38
  • OK, I was hoping we wouldn't need the RewriteBase parameter as I don't know it. That's to say it can be different depending on the domain name in use. 15 domain names share this resource through a sybmolic link on the server and each have a directory which is not represented by the domain name alone. For example yycdeals.com has a directory of /xxx/yycdeals/toronto/xxx/. Is there any way to read the current directory structure or I could even send it as a parameter. I Much appreciate your continued help. – Andy Gee Mar 24 '12 at 22:38
  • Hi Andy, RewriteBase is relative to the domain, so the same directory name for any of these domains will be fine (i.e. RewriteBase /subdirectory). – Jan Mar 25 '12 at 07:18
  • To make clear: it is relative to the domain's web root (I cannot seem to change my previous comment). – Jan Mar 25 '12 at 07:42
1

You need to add the [NS] flag to third rule. This makes it not fire on internal sub requests.

baynezy
  • 6,493
  • 10
  • 48
  • 73
1

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.

regilero
  • 29,806
  • 6
  • 60
  • 99