FREE THOUGHT · FREE SOFTWARE · FREE WORLD

Home » Htaccess » Smart HTTP and HTTPS .htaccess Rewrite

Smart HTTP and HTTPS .htaccess Rewrite

Smart HTTP and HTTPS .htaccess Rewrite

April 29th, 2008

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]

Please Comment!

Your email address is not saved.

Reader Comments

  1. v1n_vampire ~January 30, 2012 @ 3:55 am

    I tried the new method, resulting to Internal Server Error. And newer method doesn't rewrite anything at all. Is there anything I should do other than copy pasting the code to .htaccess file? (My .htaccess file is clean except for RewriteEngine on line)

  2. Stephen ~July 14, 2011 @ 8:21 pm

    Does anyone have 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, registration page to be in SSL. The rest of the pages will be in http like the index.php. 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:

    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

    http://www.mysite.com/?do=login
    http://www.mysite.com/?do=reg
    http://www.mysite.com/?do=login&url=sell
    http://www.mysite.com/?do=login&url=myaccmain
    http://www.mysite.com/?do=login&url=sindex

    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.

  3. Livepage ~February 16, 2011 @ 3:22 am

    @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 enter http://site.info/CNN/ or http://site.info/CNN to watch cnn channel :)

    regarding

  4. Michael Byers ~September 17, 2010 @ 10:07 am

    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.

  5. yong ~May 3, 2010 @ 12:01 pm

    hi,
    good work.
    thanks.

    best.

  6. deepti ~April 22, 2010 @ 3:35 am

    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

  7. sujit ~April 6, 2010 @ 8:09 am
    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 of

    THE_REQUEST,
    ^[A-Z]{3,9}\
    /(.*)index\.html\
    HTTP/
  8. zaizai ~March 19, 2010 @ 6:43 pm

    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.php

    Any 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.

  9. Andy Burton ~March 10, 2010 @ 9:32 am

    # 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]

  10. Sven ~October 1, 2009 @ 9:49 am

    Nice. Thanks :)

  11. raystrach ~September 24, 2009 @ 3:40 am

    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.

  12. JN ~July 30, 2009 @ 2:56 am

    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?

  13. raystrach ~April 29, 2009 @ 8:56 pm

    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 suspicious

    RewriteCond %{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 to GET.

    cheers

  14. lrwing ~February 11, 2009 @ 9:20 am

    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)$
  15. Tung ~October 22, 2008 @ 1:09 am

    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 browsing https://hostname/repos will be directed to https://hostname/repos/

    Where is the global area that rewrite rules will take effect on http and https both ?

  16. Tung ~October 20, 2008 @ 7:37 am

    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!

  17. Tung ~October 19, 2008 @ 2:55 pm

    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?

  18. Carlos M.S. ~October 6, 2008 @ 2:29 pm

    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?

  19. anthylon ~October 5, 2008 @ 10:22 am

    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.

  20. Burke ~May 10, 2008 @ 9:22 pm

    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]
  21. ace ~January 3, 2008 @ 6:50 am

    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


It's very simple - you read the protocol and write the code. -Bill Joy

Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 License, just credit with a link.
This site is not supported or endorsed by The Apache Software Foundation (ASF). All software and documentation produced by The ASF is licensed. "Apache" is a trademark of The ASF. NCSA HTTPd.
UNIX ® is a registered Trademark of The Open Group. POSIX ® is a registered Trademark of The IEEE.

Site Map | Contact Webmaster | Glossary | License and Disclaimer | Terms of Service |

↑ TOPMain