Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get mod_rewrite to match a rule just once

I have the following URL...

http://localhost/http.mygarble.com/foundationsofwebprogramming/86

...that I want to convert into the following:

http://localhost/http.mygarble.com/php/blog.php?subdomain=foundationsofwebprogramming&page=posts&label=86

I thought I could achieve this with the following rule:

RewriteRule ([^/]+)/([^/]+)$ php/blog.php?subdomain=$1&page=post&label=$2 [NC,L]

However what I find is that this rule is applied repeatedly, resulting in an internal server error. I understand that when the URI is transformed using this rule, the resulting URI will also match the rule, and therefore it is applied again ad-infinitum.

My previous (admittedly rather hazy) understanding was that the [L] flag would stop further processing, although I now understand that this simply means that only the remainder of the rules are skipped, and does not stop the rewrite engine running through the rules again.

I can fix this problem by adding the following condition...

RewriteCond $0 !php/blog.php
RewriteRule ([^/]+)/([^/]+)$ php/blog.php?subdomain=$1&page=post&label=$2 [NC,L]

...or by writing a more specific regular expression. But what I really want to do is find a way of stopping the rewrite engine from attempting ANY further matches once this rule is matched once. Is this possible?

Many thanks.

like image 354
James Smith Avatar asked Jun 14 '11 10:06

James Smith


People also ask

What is $1 RewriteRule?

In your rewrite, the ^ signifies the start of the string, the (. *) says to match anything, and the $ signifies the end of the string. So, basically, it's saying grab everything from the start to the end of the string and assign that value to $1.

What is rewrite condition?

The RewriteCond directive defines a rule condition. One or more RewriteCond can precede a RewriteRule directive. The following rule is then only used if both the current state of the URI matches its pattern, and if these conditions are met.

How does mod rewrite work?

mod_rewrite works through the rules one at a time, processing any rules that match the requested URL. If a rule rewrites the requested URL to a new URL, that new URL is then used from that point onward in the . htaccess file, and might be matched by another RewriteRule further down the file.


1 Answers

Usually 2 methods are used.

The first one is a Rewrite Condition testing that the requested file is not a real file. When internal recursion arise your php/blog.php is a real file and rewriterule is not executed the 2nd time. Side-effect is that any request for a file which exists won't be rewritten (which can be good side effect)

RewriteCond %{REQUEST_FILENAME} !-f

The second solution is to check you're not in an internal redirection with:

RewriteCond %{ENV:REDIRECT_STATUS} ^$

Side effect of this 2nd solution is that the rewriteRule cannot be applied if some other rules are applied before (if you want some internal redirection to run after a first pass of rewriting in fact).

Edit

For completion I will add a third method: the [NS] or [nosubreq] tag seems to be doing the same thing. Preventing the rule usage after an internal redirection.

like image 182
regilero Avatar answered Sep 21 '22 21:09

regilero