.htaccess rules to switch between https si http

Hello,

Can anyone help me make the correct .htaccess rules in order to switch between https and http depending on the accessed file or folder.

my .htaccess looks something like this:


RewriteEngine on
#enforce www
RewriteCond %{HTTP_HOST} !^www.site.com [NC]
RewriteRule ^(.*)$ http://www.site.com/$1 [L,R=301]

# Turn https on only for the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} (thefolder/|thelink) 
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

# Turn https off for everything but the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !(thefolder/|thelink) 
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]

RewriteBase /

RewriteRule ^key/a-link\\z /a-link [NC,L,R=301]
RewriteRule ^a-link\\z index.php?key=a-link [NC,L]
...
[B]RewriteRule ^key/thelink\\z /thelink [NC,L,R=301]
RewriteRule ^thelink\\z index.php?key=thelink [NC,L][/B]

  1. When I go to: [noparse]http://www.site.com/thelink[/noparse] it changes to: [noparse]http://www.site.com/index.php?key=thelink[/noparse] instead of [noparse]https://www.site.com/thelink[/noparse]
  2. When I go to: [noparse]http://www.site.com/thefolder/[/noparse] it changes goes to 404 not found…

(the only thing that works is that all other pages but “thelink” when accessed with https switch to http)

What am i doing wrong? How can I make it work ?

Thank you in advance for your help!

First off, welcome to SitePoint :wave:

Let’s look at what you have there.


RewriteEngine on
#enforce www
RewriteCond %{HTTP_HOST} !^www.site.com [NC]
RewriteRule ^(.*)$ http://www.site.com/$1 [L,R=301]

That is not entirely correct as you must escape dots in the RewriteCond (otherwise it just means “match any character”, which also works, but is not semantically correct, and -albeit negligible- slower).
Also, try to stay clear from (.*) as much as possible. In this case you could just use .? and %{REQUEST_URI}. So, you’d get:


RewriteEngine On
#force www
RewriteCond %{HTTP_HOST} !www\\.site\\.com$ [NC]
RewriteRule .? http://www.site.com%{REQUEST_URI} [L,R=301]

Moving on, we see


# Turn https on only for the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} (thefolder/|thelink) 
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

Same reasoning applies here: don’t match (.*) but .? and then use %{REQUEST_URI} in the redirect. Also, you know we are on [noparse]www.site.com[/noparse] because we just enforced that, so let’s j
ust use that instead of asking Apache something we already know. The folder and link you want to match against need to be at the start of string, so you need to indicate that by starting the expressing with a ^
The rest of this code seems fine to me.

So, we get


# Turn https on only for the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^(thefolder/|thelink)
RewriteRule .? https://www.site.com%{REQUEST_URI} [R=301,L]

Everything I just said also applies to the next block, so you get


# Turn https off for everything but the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^(thefolder/|thelink) 
RewriteRule .? http://www.site.com%{REQUEST_URI} [R=301,L]

Then you have


RewriteBase /

This is only needed to undo effects of mod_alias and is most likely not needed in your case. Remove it. If that breaks everything (some hosts are weird and won’t work without it) put it back.


RewriteRule ^key/a-link\\z /a-link [NC,L,R=301]
RewriteRule ^a-link\\z index.php?key=a-link [NC,L]
...
RewriteRule ^key/thelink\\z /thelink [NC,L,R=301]
RewriteRule ^thelink\\z index.php?key=thelink [NC,L]

What is the \z supposed to mean? Do you want to indicate the end of the string? If so, that’s done with $ instead of \z

Also, you said “When I go to: [noparse]http://www.site.com/thefolder/[/noparse] it changes goes to 404 not found…”. What does it change to?

Thank you for your prompt reply, and thank you for explaining everything so nice and clear!

I made all the replacements in the code as you suggested and the behavior changed, but it still doesn’t work as needed:

  1. Any link I access either with https or http changes to [noparse]http://www.site.com/[/noparse]
  2. When accessing [noparse]http://www.site.com/thefolder[/noparse] no longer redirects to the 404 not found page. It just opens the link… no https redirect…
  3. No link changes to https, all links redirect from https to http.

Previously when I accessed: [noparse]http://www.site.com/thefolder/[/noparse] it redirected to the default 404 page (I validate all links through index.php and if it’s not a valid page it redirects to 404 page. I don’t know what link it tried to validate).

my current .htaccess looks like this:


# secure htaccess file
<Files ~ "\\.(inc|htaccess)$">
 order allow,deny
 deny from all
</Files>

ErrorDocument 404 /404.php

# enable directory browsing
Options All +Indexes
IndexIgnore *

Options +FollowSymLinks
RewriteEngine On
#force www
RewriteCond %{HTTP_HOST} !www\\.site\\.com$ [NC]
RewriteRule .? http://www.site.com%{REQUEST_URI} [L,R=301]

# Turn https on only for the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^(thefolder/|thefile)
RewriteRule .? https://www.site.com%{REQUEST_URI} [R=301,L]

# Turn https off for everything but the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^(thefolder/|thefile) 
RewriteRule .? http://www.site.com%{REQUEST_URI} [R=301,L]

RewriteRule ^key/a-link$ /a-link [NC,L,R=301]
RewriteRule ^a-link$ index.php?key=a-link [NC,L]

#some other rules for other pages...

RewriteRule ^key/thelink$ /thelink [NC,L,R=301]
RewriteRule ^thelink$ index.php?key=thelink [NC,L]

Thank you very much for helping!

Can you turn off the auto url parsing when replying please alexandruc?
Your replies keep going into the moderation queue because of the links.

Ok. Sorry… I didn’t realize.

Hi alexandruc,

Please read the section “Enforce Secure Server” on http://www.datakoncepts.com/seo

The problem seems to be that %{HTTPS} is not set when https is not on; i.e. checkecking %{HTTPS} off does not work, so you can either use !on, or check ports instead.
You can try to check using the ports (80 for http and 443 for https) using the following:


# Turn https on only for the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{SERVER_PORT} ^80$
RewriteCond %{REQUEST_URI} ^(thefolder/|thefile)
RewriteRule .? https://www.site.com%{REQUEST_URI} [R=301,L]

# Turn https off for everything but the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{REQUEST_URI} !^(thefolder/|thefile) 
RewriteRule .? http://www.site.com%{REQUEST_URI} [R=301,L]

It seems that the %{HTTPS} is not the problem. I changed with {SERVER_PORT} and the same behavior.

However I noticed the following:

  1. If remove the start string operator “^” from the RewriteCond %{REQUEST_URI} ^(thefolder/|thelink) and try to access http://www.site.com/thelink this happens:
  • IE will display “Internet Explorer cannot display the webpage”,
  • Google Chrome will display: “This webpage has a redirect loop The webpage at https://www.site.com/thelink has resulted in too many redirects. Clearing your cookies for this site or allowing third-party cookies may fix the problem. If not, it is possibly a server configuration issue and not a problem with your computer.”,
  • FF: “The page isn’t redirecting properly Firefox has detected that the server is redirecting the request for this address in a way that will never complete.”.
  1. If I leave the “^” the rules force everything to http.

  2. If I remove the code that forces http (second block of code), then all the links behave as they are accessed.
    If a link is accessed via http, all the navigation will be http and will not force the wanted page/link - e.g: “thelink” - to change to https (if a link is accessed via https, all the navigation will be https).

  3. If I remove both the “^” and the code for https -> http, when visiting http://www.site.com/thelink it changes to https://www.site.com/thelink as it supposed to :frowning:

So the first block of code (http -> https) works as wanted if I remove “^” and if I remove the second block of code (https -> http).

  1. Now with “^” removed from “http -> https” and the “https -> http” code added with the “^” in place, the page enters a loop.

If remove the “^” from the second code block (“https -> http” - so now both ^ are removed) when accessing http://www.site.com/thelink it changes to http://www.site.com/index.php?key=thelink. All links are forced to http.

Alex,

Rémon and Mike have given good answers but they missed the mark.

First, you must consider WHAT you want to be served via https. Unfortunately, that includes your support files, i.e., images, css, js, etc which are not likely in your two subdirectories.

Second, if it’s that important to have www, enforce www with the correct http/https protocol - what you have will loop on the https as mod_rewrite will LOOP until no matches/redirections are made.

Let’s look at your code:

RewriteEngine on
#enforce www
# RewriteCond %{HTTP_HOST} !^www.site.com [NC]
# RewriteRule ^(.*)$ http://www.site.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST}/s%{HTTPS} ^www\\.([^/]+)/((s)on|s.*)$ [NC]
RewriteRule .? http%3://%1%{REQUEST_URI} [R=301,L]

# I would advise AGAINST this as the support files outside thefolder|thelink will be served via http,
# i.e., causing the browser to issue a warning that non-secure content is being displayed

# Turn https on only for the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
# {HTTPS} is either on or {null}
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} ^(thefolder|thelink) 
RewriteRule .? https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# Turn https off for everything but the links: https://www.site.com/thefolder/ and  https://www.site.com/thelink
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !(thefolder|thelink) 
RewriteRule .? http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# RewriteBase / DUMB - this is to UNDO a mod_alias redirect else it will cause problems

# RewriteRule ^key/a-link\\z /a-link [NC,L,R=301] # what is \\z? It's not a regex shorthand (that I'm aware of).
# RewriteRule ^a-link\\z index.php?key=a-link [NC,L] # Ditto
# also, URIs are case sensitive so do NOT use NC in a RewriteRule!

If you need support files to be served via https, consider {HTTP_REFERER} and attempt to match thefolder|thelink.

Now, ORDER IS EVERYTHING. I would have enforced the www, set everything to http protocol (which obviates the special code shown above) then changed thefolder|thelink and their support files to use the https protocol. To avoid looping on the http=>https redirections, use !%{IS_SUBREQ} at the enforce www block.

[indent]IS_SUBREQ

Will contain the text “true” if the request currently being processed is a sub-request, “false” otherwise. Sub-requests may be generated by modules that need to resolve additional files or URIs in order to complete their tasks.[/indent]
Regards,

DK

dklynn, thank you for your help.

I must force www (at least on the http links) since google indexed the site with www.

This is what I actually need: https for 1 folder and about 3 other pages.

The folder is actually the “/admin/” folder and all resources are self-contained in that folder. I guess it would be much simpler to just have the force https in the admin folder. :slight_smile:

The other pages I would like to be https are pages like the contact form (witch requires personal data) and 2 other pages: the shopping basket and checkout page.

For these pages the resources are common with the rest of the site so I should use the {HTTP_REFERER} to match the files.

I removed RewriteBase and \z on ScallioXTX’s suggestion. I will also remove the NC.

I must read more about the IS_SUBREQ and how to use it since I don’t have any experience with .htaccess and it’s the first time I hear about it. I think this is they key since on previous trials I got the redirect loop error. Once I have some code to show (hopefully a functional one) I will post it.

Thank you!

ok. I give up. I just cannot make it work. :frowning:

I made a special .htaccess for “thefolder” (the admin folder) so that is solved.

All I have to do is make certain links go to https://www. and the rest to http://www.

This is my latest code (comments in the code):

RewriteEngine On
#force www
RewriteCond %{HTTP_HOST} !www\\.site\\.com$ [NC]
RewriteRule .? http://www.site.com%{REQUEST_URI} [L,R=301]

#if trafic either http://www.site.com/link1 or http://www.site.com/link2, redirect to https. (and it works).
RewriteCond %{SERVER_PORT} ^80$
RewriteCond %{REQUEST_URI} ^(/link1|/link2|link3)$
RewriteRule .? https://www.site.com%{REQUEST_URI} [R=301,L]

#after one of those 2 pages is accessed, all the links go to https.

#if trafic is on https:// and the links are NOT https://www.site.com/link1 or https://www.site.com/link2, redirect to http://www. (and it does not work).
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{REQUEST_URI} !^(/link1|/link2|/link3)$

#If the next line is uncommented any/all links redirect to http://www... The links that should have stayed in https:// redirect to http://www.site.com/index.php?key=link1 (for link1) or http://www.site.com/index.php?var1 (for link3) (see the redirect rules at the bottom for details).
#RewriteRule .? http://www.site.com%{REQUEST_URI} [R=301,L]

# I think the fact that above links do not redirect to their form but to the index.php?key=... is somehow influenced by next redirects that don't trigger?
RewriteRule ^key/link1$ /link1 [L,R=301]
RewriteRule ^link1$ index.php?key=link1 [L]

RewriteRule ^link2$ index.php?link2 [L]

RewriteRule ^link3/err$ index.php?var1&var2 [NC,L]
RewriteRule ^link3$ index.php?var1 [NC,L]

I just don’t have the skills to solve this :frowning:

Alex,

Responses embedded (indented) in your post.

Regards,

DK

Hi dklynn,

I posted yesterday a another long post describing my progress (or lack of it :slight_smile: )… but I guess it’s still in moderation (it could have been concidered a double post). I hope a moderator will approve it soon…

EDIT: the SSL certificate is for the www version of the site.

p.s: the site could be considered an e-commerce site… but it’s made from scratch by me. It’s not a standard solution, or an engine developed by someone else.

Alex,

As the former Hosting Team Leader, I can assure you that posts are put online LIVE instantly!

Okay, the www is REQUIRED for the SSL cert. It’s nice that it does not conflict with the first mod_rewrite block.

Aha! Gudonya! I hope the {HTTP_REFERER} exclusion hint has allowed you to resolve your problem with the 3 special pages (for their “support files” - and please note that this need not be applied to the enforce-www as a relative link from an https link is also an https request).

Regards,

DK

Off Topic:

They were when we were running VB3, but in VB4 we have some sort of spam filter running (not sure which one) that stops some replies and puts them in the moderation queue to be approved, like the one alexandruc just mentioned.
It’s not always clear why some posts end up there, nor is there a way to find out (as is pretty common with spam filters).

My post just appeared :slight_smile:

Yes you did, I’m not sure what part of your post the auto-mod filter doesn’t like but its being a bit heavy handed!
If you post and it doesn’t come up, PM me and I will sort it.

Rémon/Mike,

Thanks for posting - and letting me know this horrible VB4 (layout et al) is the culprit.

Regards,

DK

ok this is what the browser gets in the headers, using the .htaccess code in my previous post, when accessing a page that should be https (/link1):

Request URL:http://www.site.com/link1
Request Method:GET
Status Code:301 Moved Permanently
Request headers:
Referer:http://www.site.com/
Response headers:
Location:https://www.site.com/link1

Request URL:https://www.site.com/link
Request Method:GET
Status Code:301 Moved Permanently
Request headers:
Referer:http://www.site.com/
Response headers:
Location:http://www.site.com/index.php?key=link1

Request URL:http://www.site.com/index.php?key=link1
Request Method:GET
Status Code:200 OK
Request headers:
Referer:http://www.site.com/
Response headers:
...

The above is obtained (and edited) from Google Chrome / Developer tools.

So this is what I understand:

  1. from http I access site.com/link1
  2. the server redirects with 301 to https://www.site.com/link1
  3. https://www.site.com/link1 is AGAIN redirected (why?) to http://www.site.com/index.php?key=link1

(if I am allowed, and if it helps I can give the link to real site or attach screen shots with info in Developer tools)

alex,

It’s the

RewriteRule ^link1$ index.php?key=link1 [L]

that’s “redirecting AGAIN” (ditto for link2 and link3). You must always remember that mod_rewrite will loop until no matches are found before allowing Apache to finally serve a file. If you don’t want those use a RewriteEngine off to comment out the remaining code.

Regards,

DK

If I comment that line the site goes to 404 since it doesn’t know who “site.com/link1” is (site.com/link1 is the rewrite for index.php?key=link1)


Request URL:http://www.site.com/link1
Request Method:GET
Status Code:301 Moved Permanently
Response headers:
Location:https://www.site.com/link1

Request URL:https://www.site.com/link1
Request Method:GET
Status Code:301 Moved Permanently
Response Headers
Location:http://www.site.com/404.php