3

I seem to be having trouble with Apache 2.2's Rewrite module (running on FreeBSD 8). My .htaccess file is as follows:

Options -Indexes

RewriteEngine on
RewriteRule ^xpaste$ cross.php [L]
RewriteRule ^x([a-f0-9]*)$ cross.php?id=$1 [L]
RewriteRule ^(gen|[a-f0-9]+)$ index.php?$1 [L]
RewriteRule ^(.*)$ index.php [L] 

Yet somehow, the last rule overrides the other three. As soon as I comment it out, the other rules work as expected:

  • www.example.com/xpaste opens cross.php
  • www.example.com/x132633 opens cross.php?id=132633
  • www.example.com/gen opens index.php?gen

I've tried various combinations of L, NS, and S=n flags on each RewriteRule, but unless I comment out the last rule, everything gets directed to index.php. How do I make Apache stop processing the RewriteRules once it finds a match?

2 Answers 2

6

RewriteRule generates an INTERNAL REDIRECT, then processing to be repeated starting from the first RewriteRule(RewriteRule ^xpaste$ cross.php [L]). You need add RewriteCond before last RewriteRule:

 RewriteEngine on
 RewriteRule ^xpaste$ cross.php [L]
 RewriteRule ^x([a-f0-9]*)$ cross.php?id=$1 [L]
 RewriteRule ^(gen|[a-f0-9]+)$ index.php?$1 [L]
 RewriteCond %{REQUEST_URI} !^/(cross|index)\.php$
 RewriteRule ^(.*)$ index.php [L]
3
  • httpd.apache.org/docs/current/mod/mod_rewrite.html "[...] that if the RewriteRule generates an internal redirect[...], this will reinject the request and will cause processing to be repeated..."
    – Steven
    Mar 1, 2011 at 23:02
  • 2
    Is there any more generic solution, something to tell Apache "don't process this rule if you're already handling a redirect"?
    – Doktor J
    Mar 2, 2011 at 6:35
  • @DoktorJ You can use a condition to check against the REDIRECT_STATUS environment variable. This is empty on the initial request and set to a non-empty string after the first rewrite (specifically, it's set to the HTTP status code).
    – MrWhite
    Jun 26, 2019 at 0:53
0

NS on the last rule should have worked. Could also do it on the other rules, with no harm. I'm getting to where I'm doing '[L,NS]', adding an NS wherever there's an L.

RewriteEngine on
RewriteRule ^xpaste$ cross.php [L]
RewriteRule ^x([a-f0-9]*)$ cross.php?id=$1 [L]
RewriteRule ^(gen|[a-f0-9]+)$ index.php?$1 [L]
RewriteRule ^(.*)$ index.php [L,NS] 

I haven't tested these yet, but there's also an interesting approach here, for your more generic solution, using an IS_SUBREQ variable. https://stackoverflow.com/questions/9555247/can-anyone-think-of-when-a-sub-request-rewrite-is-useful

This post mentions REDIRECT_STATUS variable also. http://www.webmasterworld.com/apache/4299003.htm

1
  • "NS on the last rule should have worked." - No it shouldn't have (and nor would the IS_SUBREQ server variable help here). A subrequest (which is what the NS flag blocks) is not the same as an internal rewrite - which is what's happening here. A subrequest is different and can be triggered by other modules such as mod_dir, SSI and HTTP error states. However, the REDIRECT_STATUS environment variable IS an option here.
    – MrWhite
    Jun 26, 2019 at 0:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .