Forum Moderators: phranque

Message Too Old, No Replies

Finally. Smart HTTP HTTPS RewriteRule Redirects

Robust HTTPS or HTTP RewriteRules with Environment Variable

         

cduke250

8:05 pm on Nov 29, 2007 (gmt 0)

10+ Year Member



I wanted to post this here because this forum is where the top gurus are like jdmorgan, and I want to know what you think especially if you have any improvements or fixes..

I learned how to solve a problem that has been bugging me for quite a long time from an article at [askapache.com...] (code reposted with permission). For URI's that can be either HTTP or HTTPS, I run into a problem where I have to duplicate every rewrite code block so that it can redirect to either the HTTP or HTTPS version based on if the request was HTTP or HTTPS.

The cool thing about this method of using an environment variable to store whether or not the request is HTTP or HTTPS is that the value of the variable can be "http" or "https" which allows the same type of dynamic robustness that mod_rewrite's RewriteRule directive allows with normal environment variables.

So before this method you would have to use something like:

RewriteRule ^.*$ https://%{SERVER_NAME}/%{REQUEST_URI} [R=301,L]
RewriteRule ^.*$ http://%{SERVER_NAME}/%{REQUEST_URI} [R=301,L]

but with this method setting an environment variable varname as "http" or "https" you can now do this!

RewriteRule ^.*$ %{ENV:varname}://%{SERVER_NAME}/%{REQUEST_URI} [R=301,L]

Old Method
The below shows 2 common rewrites, removing index.html from the url and redirecting // to /.

RewriteCond %{HTTPS}!=on
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.html\ HTTP/ [NC]
RewriteRule ^.*$ http://%{SERVER_NAME}/%1 [R=301,L]

RewriteCond %{HTTPS} =on
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.html\ HTTP/ [NC]
RewriteRule ^.*$ https://%{SERVER_NAME}/%1 [R=301,L]

RewriteCond %{HTTPS}!=on
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)//(.*)\ HTTP/ [NC]
RewriteRule ^.*$ http://%{SERVER_NAME}/%1/%2 [R=301,L]

RewriteCond %{HTTPS} =on
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)//(.*)\ HTTP/ [NC]
RewriteRule ^.*$ https://%{SERVER_NAME}/%1/%2 [R=301,L]

New Method

RewriteCond %{HTTPS} =on
RewriteRule ^(.+)$ - [env=askapache:https]
RewriteCond %{HTTPS}!=on
RewriteRule ^(.+)$ - [env=askapache:http]

# redirect urls with index.html to folder
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.html\ HTTP/ [NC]
RewriteRule ^.*$ %{ENV:askapache}://%{SERVER_NAME}/%1 [R=301,L]

# change // to /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)//(.*)\ HTTP/ [NC]
RewriteRule ^.*$ %{ENV:askapache}://%{SERVER_NAME}/%1/%2 [R=301,L]

jdMorgan

10:56 pm on Nov 29, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



New Method #2 using self-contained rule

# redirect urls with index.html to folder
RewriteCond %{SERVER_PORT}s ^(443(s)¦[0-9]+s)$
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^/]+/)*index\.html\ HTTP/
RewriteRule ^(([^/]+/)*)index\.html$ http%2://%{HTTP_HOST}/$1 [R=301,L]
#

Alternate variables and formats shown to demonstrate additional methods, regex tweaked for matching speed.

Replace broken pipe characters "¦" with solid pipes before use; Posting on this forum modifies the pipe characters.

Jim

[edited by: jdMorgan at 10:59 pm (utc) on Nov. 29, 2007]

cduke250

11:20 pm on Nov 29, 2007 (gmt 0)

10+ Year Member



Whoah... now that is pure genius. Using your method I can now set the variable to be "http" or "https" in just one block! Thanks!

RewriteCond %{HTTPS} =on
RewriteRule ^(.+)$ - [env=askapache:https]
RewriteCond %{HTTPS}!=on
RewriteRule ^(.+)$ - [env=askapache:http]

with

RewriteCond %{SERVER_PORT}s ^(443(s)¦[0-9]+s)$
RewriteRule ^(.+)$ - [env=askapache:http%2]

The reason I like the variable is because once you set it you can use it for all the rest of the rewrites without having to conditionalize it for every block.

jdMorgan

11:50 pm on Nov 29, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, it depends on how many following rules you have over which to 'amortize' the overhead of the protocol-detection rule.

Jim

therealgtron

3:27 am on Jan 7, 2008 (gmt 0)

10+ Year Member



i have a weird request. i would like every thing but my root url to redirect to ssl. this might sound like an odd request but it's a security site so our people want the entire site to run over https but a lot of search engines reject your submission if it redirects to https. not sure if that just made sense or not. lol

i was thinking something like this but i was wrong:


#Redirect all but main page to to HTTPS
RewriteCond {REQUEST_URI}!^http://www.gtron.com$
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

any help would be great. :)

jdMorgan

4:04 am on Jan 7, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Review the code posted above, and ask yourself "What is to stop [example.com...] from being redirected to itself repeatedly by my code?"

Also, REQUEST_URI will never contain the domain name, only the local URL-path. The local URL-path for your "home page" will be "" (blank) if checked by RewriteRule in an htaccess context. The pattern should therefore be "^$" to match home page requests, or "!^$" or just "." to match anything else except the home page.

Our forum charter [webmasterworld.com] contains links to the Apache documentation and other related resources -- highly-recommended reading. :)

Jim

therealgtron

4:25 am on Jan 7, 2008 (gmt 0)

10+ Year Member



first, thanks for your timely reply. second, i prolly should have researched it before trying to ask for help to avoid feeling belittled. lol

thanks again!