Force HTTPS or HTTP for specific files in htaccess

I am trying to find a good way of doing the following using mod_rewrite in htaccess:
Force all traffic to www
Use clean URLs for all pages (i.e. Store->store_page.php)
Force specific clean URLs to https
Force all non-specified clean URLs to http
I have tried a number of ways but the only way I can get it to work is to specify all clean URLs for both https and http. Meaning, I have to list all of the clean URLs for https and all for http.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Must be a bit of a design flaw if you are having to prepocess all your files to see which should be https.
How are people getting to the http version? Are the links not already going to the https version?
Redirect all to www is easy with
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$  http://www.%{HTTP_HOST}/$1 [R=301,L]

Open in new window

Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
Here are a couple of articles we have on how to do this.   It would be a good idea for you to post some sample urls that you have now, and how you want the urls to look. should be redirected to should be redirected to should be redirected to

When you say clean urls, are you talking about is viewed as but is actually hitting or the other way around?

Redirect to www
Steve BinkCommented:
I also think you have issues with your current strategy.  Taking your requests one at a time:

>>> Force all traffic to www

A common request, and generally a good idea.  GaryC123's example will do the trick.

>>> Use clean URLs for all pages (i.e. Store->store_page.php)

This talking point is more on the CMS/application side than on the web service side (where the rewrites live).  If you configure your application with proper SEFs, and consistently use those for your link's href attribute, you should have no issues with this.  A more common problem is when the CMS, cart, or whatever other application lives on your server does not natively use SEFs.  In any case, it is certainly possible to enforce SEF usage on any particular page with a set of two rewrites - one to forward the user to the friendly URL, and another to internally redirect the friendly URL to its proper destination.  That's all fine and dandy for one, or a handful, but if you get into a few dozen pages...whew, that's a lot of management, and a lot of rewrite logic firing on each and every request.  The better strategy is to use SEFs consistently in your links.  If your users happen to get hold an unfriendly URL, so be it - it won't hurt anything - and you can always go to the search engines to correct anything they happen to pick up.

>>> Force specific clean URLs to https

My problem with this request is that it implies parts of your site will not be on https.  Why not?  Why deal with the split?  I've been a big advocate of whole-site SSL.  In my opinion, there are zero reasons to have a split site.  If you have SSL, USE IT!  It adds just that much more protection, and you'll not see any performance hit until you're approaching the thousand-hits-per-second mark.  Also, by making your site 100% SSL, you'll remove this management item from your workload.  A total win-win.  My recommendation is a generic rule to force SSL on the entire site.  Note: I don't recommend the VirtualHost Redirect method for this because you lose the original request information.

>>> Force all non-specified clean URLs to http

Even if you DID decide to go the way of a split site, why would you even worry about this?  If someone goes to a typically non-SSL page using SSL, it hurts nothing.  This usually  happens because a user has gone to an SSL page, then navigates elsewhere on the site.  This means the secret exchange has already completed - you're not even going to see that load on subsequent requests.  This is a non-item, and will just make more work for you, with no benefit.

The complaint at the end of your initial post is exactly what I'm talking about with those last two points.  Of course you'll need to list out each URL for http/ else is the server supposed to know which is which?  You could always separate your site into subdirectories for easier management, but why even go through that trouble?  SSL is not a bad thing for any site.

Good luck!
5 Ways Acronis Skyrockets Your Data Protection

Risks to data security are risks to business continuity. Businesses need to know what these risks look like – and where they can turn for help.
Check our newest E-Book and learn how you can differentiate your data protection business with advanced cloud solutions Acronis delivers

phperAuthor Commented:
Below is what I currently am using to acomplish the tasks that I require. After the DirectoryIndex and turning on mode_rewrite the htaccess code below forces all traffic to http://www, then forces specific pages to http (which is in a way redundant) then finally forces specific pages to https. Finally, while my navigation points to the correct http or https URLs I find in some cases people manual type URLs that automatically go to http and this is why I am trying to force specific pages.

GaryC123: Yes, your mod_rewrite code is the first part of what I am trying to accomplish.
padas: Below are examples of the clean URLs. In most cases it is the same name (i.e.> but not always (i.e.>
routinet: I appreciate your response but I am not using a CMS and the reason to split http and https is because https is not cahced in the same way, thus increasing load times.

Here is what I am currently using. What I am tying to do is come up with a better way of doing the following. Hopefully, with only specifying the https pages and having all others go to http. If I did not specify the http pages in the example below and a visitor was on a https page and there was a link without the full URL then the visitor would be taken to https. Meaning, a visitor is on and there was
<a href="/About">Link</a>

Open in new window

then the visitor would be taken to instead of

DirectoryIndex index.php
IndexIgnore */*

RewriteEngine on
Options +FollowSymLinks

RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{REQUEST_URI} (index.php|Home|About|Contact|Terms)
RewriteRule ^(.*)$ http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L] 
RewriteRule ^Home$ index.php [NC,L]
RewriteRule ^About$ about_new.php [NC,L]
RewriteRule ^Contact$ contact.php [NC,L]
RewriteRule ^Terms$ terms.php [NC,L]

RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{REQUEST_URI} (Login|Logout|Register|Store|Cart|Shipping|CalculateShipping|Billing)
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule ^Login$ login.php [NC,L]
RewriteRule ^Logout$ logout.php [NC,L]
RewriteRule ^Register$ register.php [NC,L]
RewriteRule ^Store$ store.php [NC,L]
RewriteRule ^Cart$ cart.php [NC,L]
RewriteRule ^Shipping$ shipping.php [NC,L]
RewriteRule ^CalculateShipping$ calculateshipping.php [NC,L]
RewriteRule ^Billing$ billing.php [NC,L]

Open in new window

Thank you all again. Any help is appreciated.
Steve BinkCommented:
I would certainly prefer to address the caching/load time issue than to split SSL on a site, but that is your choice.

Due to the complexity of your rewrite needs, I also recommend moving this into your application logic.  The server's rewrite rules are no place for complicated, conditional logic.

From your list of rewrites I think you would benefit from setting up a RewriteMap.  

First, you need an easier detection mechanism for SSL.  Use a RewriteMap to set the required status of SSL:
# NOTE: this mapping defaults to 'off'
RewriteMap sslrequired txt:/path/to/file/sslrequired-map.txt 
RewriteRule /?(.*) - [E:REQPROT=${sslrequired:$1|off}]

Open in new window

Inside /path/to/file/sslrequired-map.txt:
# maps URLs into http/https
# on = https, off = http
Login on
Cart on
Home off

Open in new window

Now you can detect if you have to redirect based on protocol:
RewriteCond %{HTTPS} !%{ENV:REQPROT} [NC]
RewriteRule /?(.*) %{ENV:REQPROT}://%{SERVER_NAME}/$1 [NC,R=301,L]

Open in new window

At this point, you know your protocol is good.  Time to handle SEFs:
RewriteMap myrewrites txt:/path/to/file/myrewrites-map.txt
RewriteRule /?(.*) /${myrewrites:$1} [NC]

Open in new window

Inside /path/to/file/myrewrites-map.txt:
Login login.php
Cart cart.php
Home index.php

Open in new window

Note that this is untested, and is really just an idea of how it could work.  You'll have to play with the semantics and such to get it working properly, and I'm not sure there's even a way to handle things like unfound maps falling through.  Again, this should be handled by your application, where complicated logic is supposed to exist.

You should also be aware the RewriteMap is a relatively expensive process, and this is hitting two of them on each request.  Whether or not this will be more efficient that running dozens of RewriteRule/RewriteCond sets together is something you will need to benchmark and decide for yourself.
redirecting from https to http is not really  good idea because it is very likely to produce security warnings in various browsers.

if you have a caching reverse proxy, i'd advise you to handle the SSL completely in the reverse proxy so it can cache stuff properly while providing both SSL and regular access. additionally the same cache will be used for both ssl and non-ssl access in most proxies.
phperAuthor Commented:
routinet: I really like the RewriteMap use but what I am trying not to do is to specify every page's HTTP/HTTPS status. Imagine a site with 1000 pages and the pages are changed frequently and of those 1000 pages only two need to be HTTPS. What I am looking for is a smart way to push everything to www, have clean URLs and push only specified pages to HTTPS, defaulting all others to HTTP.

skullnobrains: I am not trying to redirect from HTTPS to HTTP. I am trying to have specific pages go to HTTPS via mod_rewrite and all others to HTTP. I googled "caching reverse proxy" and found some examples but do not see how it can work for my issue. Do you have a specific example how it can be used in my situation?
Steve BinkCommented:
Then you can still use the RewriteMap idea to manage only the HTTP->HTTPS redirections.  Just because the system can handle both directions does not mean you need to allow it to handle both.  Putting the detection into RewriteMap just allows for some simplified management at the expense of the map lookup.  You could do the same thing with a RewriteCond, using a long list of match phrases.

As has been covered before, the idea of having clean URLs is really an application-level enforcement.  Putting all of those checks into your rewrites is a) time-consuming, b) expensive, and c) a management nightmare.  Strongly consider putting this logic into your application, as well as enforcing SEF usage in your linking strategies on the site.
Do you have a specific example how it can be used in my situation?

yes. if your issue with all https is related to caching, i assume you have a caching reverse proxy because most remote users don't have proxies and the browsers will cache either in a very similar way

your caching reverse proxy can host the SSL certificates and proxy to your server in plain HTTP. if you do this, the reverse proxy will be able to cache secure and non secure connections in the same way


then if you really want to use rewrites and ignore the risk of mapping secure connections to non secure :

# rewrite everything to www
# note that this also maps all queries to plain http
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$  http://www.%{HTTP_HOST}/$1

RewriteCond %{HTTPS} !=on
RewriteRule ^/?(login|logout|store|...)\.php(.*) https://%{SERVER_NAME}/$1 [R]

Open in new window

or better in order to prevent remapping back and forth

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$  www.%{HTTP_HOST}/$1

RewriteCond %{HTTPS} !=on
RewriteRule ^/?(login|logout|store|...)\.php(.*) https://%{SERVER_NAME}/$1 [R,L]

RewriteRule ^(.*)$  http://www.%{HTTP_HOST}/$1

Open in new window

but you really should allow https sitewide, or just send an error (in https with a link to the http page) to the user saying you don't want him to fiddle with the address bar if you really don't want to

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Apache Web Server

From novice to tech pro — start learning today.