Forum Moderators: phranque
I'm trying to create a set of rules to:
Ensure that www. host is always used.
Force https for a particular directory.
Force http for every other directory.
These are the rules I have so far:
[CODE]
#Ensure correct host
RewriteCond %{HTTP_HOST}!^www.example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
#Make sure we're using ssl here
RewriteCond %{SERVER_PORT}!^443$
RewriteCond %{REQUEST_URI} ^/payments [NC]
RewriteRule ^(.*)$ [example.com...] [L,R=301]
#or should it have been?
#RewriteRule ^(.*)$ [example.com...] [L,R=301]
#and not anywhere else
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{REQUEST_URI}!^/payments [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
[\CODE]
I wonder if anyone can see any flaws in these rules or know of better ways to achieve the goals.
I did a quick hunt but couldn't spot other posts covering thi. Please point me at any if they do.
Matt
Jim
Thanks that really is very helpful. Payments is a directory so I've changed the rules as you suggested. I've also changed the turn ssl off rule so that we can load supporting files to pages in the payments directory.
Anyone else reading this looking for copy and paste snippet here we are:
This forces SSL in "payments/" directory and off everywhere else, also force www. host use. Change example.com to your own domain and payments for the folder in which you need to force SSL.
# Make sure we're using ssl here
RewriteCond %{SERVER_PORT}!^443$
RewriteRule ^(payments/.*)$ https://www.example.com/$1 [NC,R=301,L]
# and not anywhere else
RewriteCond %{SERVER_PORT} ^443$
RewriteCond $1!^payments/ [NC]
RewriteCond %{REQUEST_URI}!\.(css¦gif¦jpe?g¦bmp¦js) [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
# Ensure correct host
RewriteCond %{HTTP_HOST}!^www\.example\.com
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
I'm curious: is there any significance in the order of the flags?
[R=301,L] vs [L,R=301]
Also am I going about the extra filtering for supporting files correctly. I've never seen the capture reference in the RewriteCond used before. Does it the $1 of the rewritecond mean insert the capture from the ^(.*)$ in the rewrite rule?
Thanks again for your help.
Matt
I'm curious: is there any significance in the order of the flags? [R=301,L] vs [L,R=301]
No, it's just a matter of style. I prefer to put them in the order that mod_rewrite originator Ralph Engleschall used in his examples, just to avoid yet another point of confusion for beginners.
Also am I going about the extra filtering for supporting files correctly? I've never seen the capture reference in the RewriteCond used before. Does it the $1 of the rewritecond mean insert the capture from the ^(.*)$ in the rewrite rule?
Yes, RewriteConds can reference $n parenthesized pattern matches from RewriteRules, and RewriteRules can reference %n pattern matches from RewriteConds. Both can reference server variables as %{VarName} and user variables as %{ENV:VarName}, or call rewritemap lookups (defined in httpd.conf or conf.d) as ${MapName:KeyValue}.
If you read the API processing description at the beginning of the mod_rewrite documentation, the reason becomes clear: The pattern of the RewriteRule is evaluated first. If it matches, then all RewriteConds are evaluated. If the RewriteConds match, then the RewriteRule is applied. So, for practical purposes, the code is not run first-line-to-last-line, but rather, last-line then first lines. This allows the directives to back-reference each other's pattern matches, among other things.
It also means that RewriteRules should always have the most specific pattern possible, so as to avoid evaluating RewriteConds unnecessarily, and that RewriteConds should be ordered from least-likely-to-match to most-likely-to-match and from most-efficient to least efficient whenever possible, in order to avoid evaluating any inefficient RewriteConds unnecessarily.
Not to worry about it too much, but it's a good idea to avoid RewriteConds which do the following things by pre-qualifying them as much as possible:
So rulesets that use those functions should be carefully ordered.
BTW, a reverse-DNS check may be invoked whenever the variable %{REMOTE_HOST} is referenced. The server must send the IP address of the current requestor (in the %{REMOTE_ADDR} variable) to the DNS system, and wait to see what hostname is returned before it can proceed. This can cause very bad delays, and in fact, means that if the RDNS lookup fails, your user's request will also fail, thus introducing a failure dependency -- Your server will look broken if the DNS server or network path is slow or goes down. I guess that's more than enough info for now... :)
So yes, $1 is the matched pattern value from the rule, and allows a further optimization.
Tweaked code:
# Make sure we're using ssl here
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(payments/.*)$ https://www.example.com/$1 [NC,R=301,L]
# and not anywhere else
RewriteCond %{SERVER_PORT} ^443$
RewriteCond $1 !(^payments/¦\.(css¦gif¦jpe?g¦bmp¦js)$) [NC]
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
# Ensure correct host
RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
Jim
Ever a great resource. Thank you.
If you read the API processing description at the beginning of the mod_rewrite documentation, the reason becomes clear: The pattern of the RewriteRule is evaluated first. If it matches, then all RewriteConds are evaluated. If the RewriteConds match, then the RewriteRule is applied. So, for practical purposes, the code is not run first-line-to-last-line, but rather, last-line then first lines. This allows the directives to back-reference each other's pattern matches, among other things.
It also means that RewriteRules should always have the most specific pattern possible, so as to avoid evaluating RewriteConds unnecessarily, and that RewriteConds should be ordered from least-likely-to-match to most-likely-to-match and from most-efficient to least efficient whenever possible, in order to avoid evaluating any inefficient RewriteConds unnecessarily.
If you haven't written a book on this whole topic you might want consider it. I'm certain I'd buy it.
Thanks again.
Matt
[edited by: MattyUK at 3:41 pm (utc) on Nov. 29, 2006]