« Mod_Security .htaccess tricksAdding Akismet Anti-Spam Protection Anywhere »
Smart HTTP and HTTPS .htaccess Rewrite
April 29th, 2008
Contents
This is a really cool idea I had to make my Apache .htaccess mod_rewrite code much shorter and easier to manage multiple Redirections when using sites with both HTTP and HTTPS. Basically instead of having to check for HTTPS using a RewriteCond for every redirect that can be HTTP or HTTPS, I found out I can set an environment variable 1 time to determine if HTTP or HTTPS is being used for that request, and by giving the variable a value of "https" for HTTPS or "http" for HTTP I can remove all duplicate rewriterule blocks. This is sweet I'm telling you!
Setting HTTP/HTTPS Environment Variable
Old method for HTTP to HTTPS Redirection
This is the old way I would have to use to redirect /index.html to / and urls with // to /.
RewriteEngine On
RewriteBase /
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 HTTPS to HTTP Redirection
First I set the environment variable ps to have the value "http" for HTTP requests, or "https" for HTTPS requests. Once that is accomplished, I can use %{ENV:ps} in all of my rewriterules and it will result in https for SSL requests and http for non-ssl requests!
RewriteCond %{HTTPS} =on
RewriteRule ^(.+)$ - [env=ps:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.+)$ - [env=ps:http]
# redirect urls with index.html to folder
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.html\ HTTP/ [NC]
RewriteRule ^.*$ %{ENV:ps}://%{SERVER_NAME}/%1 [R=301,L]
# change // to /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)//(.*)\ HTTP/ [NC]
RewriteRule ^.*$ %{ENV:ps}://%{SERVER_NAME}/%1/%2 [R=301,L]
Even Newer HTTP/HTTPS Rewrite Code
The top guru I have ever seen in my lengthy .htaccess related web travels is a moderator on the WebmasterWorld.com Apache Forum, jdMorgan. Upon seeing the above solution that I came up with, jdMorgan instantly provided an improvement, resulting in being able to set the environment variable in 1 rewrite block instead of 2. This is truly Sweet.
RewriteCond %{SERVER_PORT}s ^(443(s)|[0-9]+s)$
RewriteRule ^(.+)$ - [env=askapache:%2]
# redirect urls with index.html to folder
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^/]+/)*index\.html\ HTTP/
RewriteRule ^(([^/]+/)*)index\.html$ http%{ENV:askapache}://%{HTTP_HOST}/$1 [R=301,L]
# change // to /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)//(.*)\ HTTP/ [NC]
RewriteRule ^.*$ http%{ENV:askapache}://%{HTTP_HOST}/%1/%2 [R=301,L]Reader Comments
-
@Tung ~
Maybe this will be helpful to you:Options +FollowSymLinks #removes trailing slash if not a directory RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.+)/$ /$1 [R=301,L] #adds ".php" to a URL that isn't a directory or a file RewriteCond %{REQUEST_URI} !(\.[^./]+)$ RewriteCond %{REQUEST_fileNAME} !-d RewriteCond %{REQUEST_fileNAME} !-f RewriteRule (.*) $1.php [L]I had same issue on my site, but now it doesn't matter if you enterhttp://site.info/CNN/orhttp://site.info/CNNto watch cnn channel :) regarding -
I can explain this one
RewriteCond %{SERVER_PORT}s ^(443(s)|[0-9]+s)$ RewriteRule ^(.+)$ - [env=askapache:%2]One the 1st line (RewriteCond) the text between ^ and $ is a regular expression. The parenthesis have a special purpose in regular expressions. They tell the regular expression engine you want it to store any text that matches the pattern inside the parens (this is called a capture group). The value for %{SERVER-PORT} will be 443 for https or some other number for http. Note how the first part of the RewriteCond expression appends 's' to the value of SERVER_PORT. So this may result in a value like '443s' or '80s', for example. There are two capture groups in the regular expression. Each is assigned a number so that its contents may be accessed. The outer set of parens is capture group 1 and the inner ( (s) ) is capture group 2. So if the value being evaluated is '443s', the value 's' will be stored in capture group 2. You refer to a capture group value from a RewriteCond with '%' and the capture group number. So the expression '%2' would yield the value 's'. The second line then assigns the apache env variable named 'askapache' the value of the expression '%2' which would be '2' for port 443 or null for any other port number. -
hi, good work. thanks. best.
-
Hello, I am new to .htaccess can any one explain me the following statement:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.html\ HTTP/ [NC]please explain the terms : THE_REQUEST,HTTP/ [NC]thanks -
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.html\ HTTP/ [NC]i have not understand this condition, how is it working wot is the work ofTHE_REQUEST, ^[A-Z]{3,9}\ /(.*)index\.html\ HTTP/ -
Hi, any idea please on what lines of code that i'm going to add into the htaccess file? Basically, i just need my login page, contact form, checkoutpage to be in SSL. The rest of the page will be in http like the index, aboutus and listing display. I have the ssl installed already in my server. I have the htaccess code to redirect all pages into https but I don't need the whole site to be in https. I have this few lines of code and this make the whole site in https:
RewriteCond %{HTTPS} !=on RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L] RewriteRule ^customer-login\.html$ login.php RewriteRule ^customer-registration\.html$ user-registration.php RewriteRule ^customer-checkout\.html$ checkout.php RewriteRule ^company-tradeshow\.html$ tradeshow.php RewriteRule ^company-aboutus\.html$ aboutus.phpAny idea please on how to make it that only login, registration, checkout to be in https? Then if user open it in http it will automatically be redirect into https. If user open index page, about us and tradeshow page in https it will automatically be change into http. Please help. -
# Redirect to www RewriteCond %{SERVER_PORT}s ^(443(s)|[0-9]+s)$ RewriteRule ^(.+)$ - [env=askapache:%2] RewriteCond %{HTTP_HOST} !^www.(.+)$ [NC] RewriteRule ^(.*)$ http%{ENV:askapache}://www.%{HTTP_HOST}/$1 [L,R=301]
-
Nice. Thanks :)
-
i am not a htacess expert, but i would be checking all your frames, images and includes and making sure they are coming from a secure server. then again you might have google ads which do not have the option of coming from a secure server in which case you are stuffed. other ad providers may have the option of sourcing ads from a secure server, not just an ordinary server.
-
What I am trying to do is this: If the request is coming through
https, I'd like all the internal content to ensure that it has https in it... This is mainly to get rid of that stupid IE 8 security warning about site containing non secure items which is bs... Any ideas? -
Thanks for posting this. It helped me out a great deal with having non-secure domains pointing to sub domains on my secure domain. However, I started to have problems logging in from certain pages (there was no apparent pattern) and i discovered my form post requests were being lost. I tried for hours trying to see why the form would not process until i realized that it was probably something in
htaccess. Although i really don't know exactly what the syntax means, (i am no htaccess expert) the following code looked suspiciousRewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^/]+/)*index\.php\ HTTP/ RewriteRule ^(([^/]+/)*)index\.php$ http%{ENV:smartspace}://%{HTTP_HOST}/$1 [R=301,L]Sure enough, I removed the code and it worked! It must have been stripping the post variables out as well as the index name in redirecting the page. Now it all seems to be working well (obviously it is not redirecting to the plain directory, but that's ok). I will keep you posted if I have stuffed something else up but have not yet discovered it. Someone might like to tell me exactly why the post variables are disappearing because it worked when I switched the method toGET. cheers -
I dont understand this line, i dont know how to interpret it. Can you please explain how to read this?
RewriteCond %{SERVER_PORT}s ^(443(s)|[0-9]+s)$ -
OK! My fault is the .htaccess rules work on the wrong scope. And the solution is as follows: Put the following rules inside of httpd-ssl.conf
RewriteEngine on RewriteCond %{HTTPS} =on RewriteRule ^/repos$ /repos/ [R]Then browsinghttps://hostname/reposwill be directed tohttps://hostname/repos/Where is the global area that rewrite rules will take effect on http and https both ? -
Hello, My goal is to redirect 'https://hostname/repos' to 'https://hostname/repos/' on Apache 2.2 I try a lot of methods, but I can't do it.
RewriteEngine on # rewrite '/repos' to '/repos/' # These two rules both work with http only, not with https. #RewriteRule ^(/repos)$ $1/ [R] #(/repos) means group, $1 = /repos #RewriteRule ^/repos$ /repos/ [R] # redirect 'http://hostname/repos[/...]' to https RewriteCond %{HTTPS} !=on RewriteRule ^/repos$ https://%{SERVER_NAME}%{REQUEST_URI}/ [L,R] RewriteRule ^/repos/.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R] # Notice: 'https://hostname/repos/' is our goal # (1)Redirecting 'http://hostname/repos' to 'http://hostname/repos/' is skip # (2)Redirecting 'http://hostname/repos' to 'https://hostname/repos/' is OK (done) # (3)Redirecting 'http://hostname/repos/' to 'https://hostname/repos/' is OK (done) # (4)Redirecting 'http://hostname/repos/...' to 'https://hostname/repos/...' is OK (done) # (5)Redirecting 'https://hostname/repos' to 'https://hostname/repos/' is fail # it can't add a slash at last #RewriteCond %{HTTPS} =on #RewriteRule ^/repos$ https://%{SERVER_NAME}%{REQUEST_URI}/ [L,R] # (5)Redirecting 'https://hostname/repos' to 'https://hostname/repos/' is fail # it can't add a slash at last #RewriteCond %{HTTPS} =on #and #RewriteCond %{THE_REQUEST} ^GET\ /repos\ HTTP/ #RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}/ [L,R=301] # So browsing 'https://hostname/repos' will return '404 Not Found'DO you have any good idea? Thank you! -
I want to redirect 'https://hostname/mypath' to 'https://hostname/mypath/' (add a slash) on Apache 2.2 But the following rule works with http only, not https.
RewriteEngine on RewriteRule ^/mypath$ /mypath/ [R]
Any idea? -
Hello, I have migrated a moodle https site to a new moodle http site and I need to change/rewrite all the links to
https:// to http://
How can i do it? -
Hello, I have multiple domain on my single shared account (monsterhost). It works fine but I am having small issue. Lets say my main domain is mydomain.com. Each domain is pointing to separated subfolder (example: myseconddomain.com is pointing to mydomain.com/myseconddomain/). It is all working well but I wish to block all access for requests like this: mydomain.com/myseconddomain/. Please, advise. Thank you.
-
I was looking for a way to write a RewriteRule that would work for both HTTP and HTTPS requests -- i.e., allowing either SSL and non-SSL access to the same site without having to write the RewriteRules twice. Your HTTP/HTTPS rewrite code was a great tip, but couldn't it be simpler? Here's what's working for me:
RewriteCond %{HTTPS} on RewriteRule .* - [env=https:s] # redirect urls with index.html to folder RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.html\ HTTP/ [NC] RewriteRule ^(.*/)index\.html$ http%{ENV:https}://%{SERVER_NAME}$1 [R=301,L] -
Hey there! I just installed an ssl certificate on my site and: thanks for posting the http to https rewrite.. I was also informed of this two liner:
RewriteCond %{SERVER_PORT} =80 RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI}but I really don't know which to use or why i should use either. Also, does using the rewrite to go from http to https mess up anything with google searches? sitemaps? etc.? Thanks in advance, ACE

RewriteEngine On RewriteCond %{SERVER_PORT} !^443$ RewriteRule ^index.php$ https://www.mysite.com/I need only these pages to be https and the rest of the site to load in http Any idea please on how to make it that only login, registration to be in https? Then if user open it in http it will automatically be redirect into https. If user open index page in https it will automatically be change into http. Please help.