FREE THOUGHT · FREE SOFTWARE · FREE WORLD

Home  »  Htaccess  »  Smart HTTP and HTTPS .htaccess Rewrite

by 34 comments

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]

Tags

April 29th, 2008

Comments Welcome

  • ace

    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

  • Burke

    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]
    • ao2

      Don't use "https" as a global variable, that could rewrite the "$_SERVER['HTTP']" content and baffle some https detection code. I've seen this.

  • anthylon

    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.

  • Carlos M.S.

    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?

  • Tung

    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?

  • Tung

    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!

  • Tung

    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 ?

  • lrwing

    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)$
  • raystrach

    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

  • JN

    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?

  • raystrach

    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.

  • Sven

    Nice. Thanks :)

  • Andy Burton

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

    • vinod

      thanks

  • zaizai

    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.

  • deepti

    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

  • yong

    hi,
    good work.
    thanks.

    best.

  • Michael Byers

    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.

  • Livepage

    @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

  • Stephen

    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.

  • v1n_vampire

    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)

  • Meriam

    Hi, I am hosting my website with go-daddy and I am using their website builder to build my site. I wanted to know how to use .htaccess on my site. I asked the go-daddy techs and the said that they do not support the .htaccess with my type of package, but I want to know if there is any other way to go around that. My site seems to never comply with Google and there is always some type of issue that I cannot grasp. Also, I seem to be doing everything that Google asks for and yet I don't know why my site is not being read correctly. Is there anything that I can do to fix what ever may be wrong with my site? Thank you.

  • MrBiTs

    These are the most elegant and KISS solution I saw ever.

    Congrats

  • Andrew White

    Hi Charles,

    Thanks for the great article - I've just deployed a version of your solution on a production environment and it's working smoothly.

    Please note once change I had to make to make everything work right - in the SSL match I've used an asterisk to match 0 or more characters instead of the plus to match 1 or more. This allows for the direct URL (e.g. just mysite.com.au) to match and catch correctly. In my situation if it doesn't, the environment "ps" variable ends up empty and it attempts to redirect to a url starting with "://" which it assumes is an internal path.

    See this link for more info.

    Thanks!

  • AskApache

    @Andrew White

    I'm glad to hear you were able to get it to work.. This can be quite tricky for sure.

    Nice fix to replace the + with a *, I've since updated the example. Many Thanks!

  • paul harford

    Hi There

    how would i redirect all https to http ? the opposite of above. we have no https on our site but with the new firefox being https by default we wanted to redirect everything to http any suggestions ?
    have tried loads of varying rewrite rules etc but nothing seems to work

  • paul harford

    Hi There

    how would i redirect all https to http ? the opposite of above. we have no https on our site but with the new firefox being https by default we wanted to redirect everything to http any suggestions ?
    have tried loads of varying rewrite rules etc but nothing seems to work

  • varun khandelwal

    hi ... I want to redirect some specific pages from http to https.. please help.

  • varun khandelwal

    hi ... I want to redirect some specific pages from http to https.. please help.

  • ao2

    Don't use "https" as a global variable, that could rewrite the "$_SERVER['HTTP']" content and baffle some https detection code. I've seen this.

  • vinod

    thanks

  • Stanyul

    Did you ever get a response to this?

My Online Tools


Popular Articles



Hacking and Hackers

The use of "hacker" to mean "security breaker" is a confusion on the part of the mass media. We hackers refuse to recognize that meaning, and continue using the word to mean someone who loves to program, someone who enjoys playful cleverness, or the combination of the two. See my article, On Hacking.
-- Richard M. Stallman



Related Articles

Twitter









[hide]

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.

+Askapache | askapache

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

↑ TOPMain