Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use RewriteCond and RewriteRule to test a url condition?

In many rewrite rule answers, when testing the url for a certain condition, I often see a mix of using RewriteCond with REQUEST_URI, and the RewriteRule itself.

Is this just personal preferences, or is there a performance reason, or just clarity of the rules? All of these are valid reasons, in my opinion; I'm just wondering if there's a particular reason.

I know there are conditions where RewriteCond is the only choice. I'm interested here in the cases where the RewriteRule would also work. Generally these are simpler rules.

Here are some examples:

EXAMPLE 1

This answer has a common pattern, allow certain folders as-is. Htaccess maintenance mode allow certain directories

# always allow these folders
RewriteCond %{REQUEST_URI} ^/display_me_always [OR]
RewriteCond %{REQUEST_URI} ^/another_folder [OR]
RewriteCond %{REQUEST_URI} ^/even_more_folders
RewriteRule .+ - [L]

This could be done with just a RewriteRule as:

RewriteRule ^/(?:display_me_always|another_folder|even_more_folders) - [L]

(Added the ?: for non-capturing. I'm never quite sure if it's faster to have a simpler rule, or not to capture.)

EXAMPLE 2

Modifying this for a more common scenario, redirect certain folders to other folders.

RewriteCond %{REQUEST_URI} ^/display_me_always [OR]
RewriteCond %{REQUEST_URI} ^/another_folder [OR]
RewriteCond %{REQUEST_URI} ^/even_more_folders
RewriteRule ^/[^/]+/(.*)$ /other_location/$1 [L]

This seems simpler with the rule only.

RewriteRule ^/(?:display_me_always|another_folder|even_more_folders)/(.*)$ /other_location/$1 [R=301,NC]

EXAMPLE 3

This answer has a common pattern, redirect if not already in the target location. Mod Rewrite rule to redirect all pdf request to another location. Test the folder with the RewriteCond, then test the file with the rule.

I can see a negative condition being much clearer to do with RewriteCond, but it's still possible with RewriteRule.

RewriteCond %{REQUEST_URI} !^/web_content/pdf/
RewriteRule ^(.+\.pdf)$ /web_content/pdf/$1 [L]

This could be written as

RewriteRule ^(?!/web_content/pdf/)(.+\.pdf)$ /web_content/pdf/$1 [L]
like image 808
goodeye Avatar asked Sep 02 '11 01:09

goodeye


1 Answers

One simple reason: it's much easier to understand for a non regex guru.

The rewrite rule that you will give to a OP today, he may need to modify one day later .. and the easier the rule to understand the more chances that he will look into it himself and not running again to this place for yet another small fix / new similar rule.

Yes, combined rule is faster -- no doubts here. But the time spent at URL rewriting is still so small compared to a single script execution ... that it only can make some difference on very-very CPU busy servers and when there are a lot of such rewrites.

Therefore, the most optimal will be something in between -- which is still easy to read and is compact and efficient at the same time. Instead of

# always allow these folders
RewriteCond %{REQUEST_URI} ^/display_me_always [OR]
RewriteCond %{REQUEST_URI} ^/another_folder [OR]
RewriteCond %{REQUEST_URI} ^/even_more_folders
RewriteRule .+ - [L]

offer

# always allow these folders
RewriteCond %{REQUEST_URI} ^/(display_me_always|another_folder|even_more_folders)
RewriteRule .+ - [L]

You cannot become a master in a day or two (unless, maybe, you are some kind of genius) -- everything takes time. And the more practical experience you have (by modifying these rules yourself) the better it is for you to move further, to produce more efficient/stable rule.

BTW: This rule will not work if placed in .htaccess (URL in matching pattern starts with no leading slash):

RewriteRule ^/(?:display_me_always|another_folder|even_more_folders) - [L]

But will work fine if placed in server config / virtual host context -- that's one of the "nuances" you need to know.

like image 87
LazyOne Avatar answered Oct 02 '22 22:10

LazyOne