Forum Moderators: phranque
I am trying to force https on some pages and default back to http on the rest. My rules are,
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/?(user-welcome.phpŠuser-details.php)$ [example.com...] [R=301]
RewriteCond %{SERVER_PORT} ^443$
RewriteRule !^/?(user-welcome.phpŠuser-details.php)$ http://www.example.com/%1 [R=301,L]
However, its not happening correctly. https pages are showing 404 whereas the rest of the pages if called from http redirect to homepage. Can you please help.
Kind Regards,
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^user-(welcomeŠdetails)\.php$ https://www.example.com/user-$1.php [R=301,L]
RewriteCond %{SERVER_PORT} ^443$
RewriteRule !^user-(welcomeŠdetails)\.php$ http://www.example.com%{REQUEST_URI} [R=301,L]
I also escaped your . (dots) so they match a literal . (dot) rather than the regular expression version, which is 'anything except the end of a line', added L to the first rule, because you should always use it unless you know you don't need it, and rather than storing / back referencing with the second rule, changed it to a negative comparison with a shorter OR statement, and used the predefined server variable %{REQUEST_URI} for the new location if it's *not* one of the two URLs you did not want redirected from the secure version of the site.
I am currently doing this.
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(loginŠuser/welcomeŠuser/details)$ [example.com...] [R=301,L]
RewriteCond %{SERVER_PORT} ^443$
RewriteRule !^(loginŠuser/welcomeŠuser/details)$ http://www.example.com%{REQUEST_URI} [R=301,L]
I have rewrite rules like,
www.example.com/login.php becomes www.example.com/login/
This is done through htaccess. However, it is done after this https forcing. Now something crazy is happening.
Although, I am not asking it to add .php to any links in htaccess, it still is.
now my www.example.com/login/ is becoming www.example.com/login.php automatically. And, also the https isnt being forced on /login/ link.
Please help
The cure is to move your external redirect code (*all* of your redirect code) so that it is always executed before any internal rewrite code, and to be sure to use the [L] flag on all rules unless you know why a particular rule should not specify [L].
Jim
Please pay special attention to the bold characters and the order of the rules below. Also, if you copy + paste, make sure you replace the Š (broken bar) with an actual bar character or you will receive a 500 server error. Your rules do not match /login/ they match /login ... With Mod_Rewrite, details are highly important, and the more attention you pay to them, the better off you will be... Mod_Rewrite is much like this post, you *must* read the fine print.
<IfModule mod_rewrite.c>
Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteBase /
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(login/Šuser/welcome/Šuser/details/)$ [example.com...] [R=301,L]
RewriteCond %{SERVER_PORT} ^443$
RewriteRule !^(login/Šuser/welcome/Šuser/details/)$ http://www.example.com%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
The other thing you might do is try:
(Just because.)
Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteBase /
RewriteCond %{HTTPS} !^on$
RewriteRule ^(login/Šuser/welcome/Šuser/details/)$ [example.com...] [R=301,L]
RewriteCond %{HTTPS} ^on$
RewriteRule !^(login/Šuser/welcome/Šuser/details/)$ http://www.example.com%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
* On a brighter note: At least now it's trying to redirect...
ok its not redirecting again and again anymore but its not doing https. Infact, putting https in the address bar automatically redirects it to http.
My htaccess is as starts below.
<IfModule mod_rewrite.c>
Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteBase /
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(login/Š/user/welcome/Š/user/details/)$ [example.com...] [R=301,L]
RewriteCond %{SERVER_PORT} ^443$
RewriteRule !^(login/Š/user/welcome/Š/user/details/)$ http://www.example.com%{REQUEST_URI} [R=301,L]
Options +FollowSymLinks -MultiViews
RewriteEngine on
#
# Redirect secure pages requested via http to https
RewriteCond %{SERVER_PORT} !=443
RewriteRule ^((loginŠuser/welcomeŠuser/details)/.*)$ https://www.example.com/$1 [R=301,L]
#
# Redirect non-secure pages requested via https back to http
RewriteCond %{SERVER_PORT} =443
RewriteRule !^(loginŠuser/welcomeŠuser/details)/ http://www.example.com%{REQUEST_URI} [R=301,L]
#
# Redirect non-canonical hostname requests to canonical hostname using originally-requested protocol
RewriteCond %{HTTP_HOST} !^(www\.example\.com)?$
RewriteCond %{SERVER_PORT}>s ^(443>(s)Š[0-9+]>s)$
RewriteRule ^(.*)$ http%2://www.example.com/$1 [R=301,L]
Jim
thank you for your help. However, I do not think, this is the right method of applying SSL on a domain. You see, I can force that following URLs will all be served with https but all my image paths are relative and hence do not get served because of our ban of not giving anything else to https.
As a result, my pages are effed up (sorry).
Do you suggest any other method of implementing SSL on a domain without hardcoding links and form actions.
Kind Regards,
The code above assumes several things, all of which must be true:
1) The code is located in the root folder "the home page folder" of the domain.
2) Both SSL and non-SSL requests resolve to the root folder.
3) All resources "included" on SSL pages are requested using SSL URLs.
4) Exceptions are made in this rule and others to allow #3.
If all of your images are located in an 'images' folder, then it would be a simple matter of adding that folder path to the exclusions already present in the https->http redirect rule (but not in the http->https rule).
It's important to realize that if #3 and #4 requirements are not met, then your users will see "Mixed secure/insecure content" warnings when viewing your SSL pages, and this will scare off enough of them to make you lose business.
Use this code only to 'fix' bad incoming links from other sites and search engines, and to correct typed-in URLs referring to the wrong protocol. All links on your own site must be correct in all respects -- correct protocol, canonical domain, canonical URL.
Jim
Basically, it should work as you expect.
You must, however, make sure that if you're on an SSL page, all images, CSS, and external JavaScript includes are referenced correctly as either relative links or as full URLs including the https protocol. Otherwise, the visitor will see mixed-secure/insecure content warnings.
You must also exclude requests for these objects from being forced (redirected) to http -- or to https, for that matter -- as I described in my previous post.
Jim
You are awfully kind and I am must say that I am really stupid. I dont much understand your solutions. Can you please also give me a sample htaccess to try. I dont want to rewrite my links to force ssl but I would like to do this through htaccess and I would like SSL only on a few pages on my domain. All my images and links are written in relative paths like /images/logo.gif etc... Please give me something to work on as team lead is getting on my back a bit.
:)
However, it can take several years to get really good at mod_rewrite, and your 'team lead' should recognize that fact. This is not a matter of 'being stupid', but rather of the fact that this is a specialized area of Webmastering, requires familiarity and knowledge of specialized modules, terms, and coding techniques, and can be made especially difficult by language barriers if English is not your native language -- If you haven't been given training or had six months to read the Apache mod_rewrite documentation and experiment, then team lead's demands are unreasonable...
Options +FollowSymLinks -MultiViews
RewriteEngine on
#
# Redirect secure pages requested via http to https
RewriteCond %{SERVER_PORT} !=443
RewriteRule ^((loginŠuser/welcomeŠuser/details)[b]/.*)[/b] https://www.example.com/$1 [R=301,L]
#
# Redirect non-secure pages requested via https back to http
RewriteCond %{SERVER_PORT} =443
RewriteRule !^(loginŠuser/welcomeŠuser/details[b]Šimages[/b])/ http://www.example.com%{REQUEST_URI} [R=301,L]
#
# Redirect non-canonical hostname requests to canonical hostname using originally-requested protocol
RewriteCond %{HTTP_HOST} !^(www\.example\.com)?$
RewriteCond %{SERVER_PORT}>s ^(443>(s)Š[0-9+]>s)$
RewriteRule ^(.*)$ http%2://www.example.com/$1 [R=301,L]
I assume that '/images/ is the only directory that is 'shared' between SSL and non-SSL pages. If not, then the additional directories must also be excluded as shown for '/images' above.
Jim
Its not happening for me. The problem is with this rule.
I am putting this code at the top of my htaccess before other rewrite rules.
one of the rules after these is
RewriteRule ^login/?$ login.php [L]
However, when I click on the link <a href="/login/">login</a>, instead of rewriting it takes me to /login.php page and from there, its not really working as it wont even log me in. Also, its still pulling the page through http://
Can you please suggest a change.
Kind Regards,
Khuram
Now, please confirm all of these points from my previous post:
The code above assumes several things, all of which must be true:
1) The code is located in the root folder "the home page folder" of the domain.
2) Both SSL and non-SSL requests resolve to this root folder.
3) All resources "included" on SSL pages are requested using SSL URLs (relative URLs are OK).
4) Exceptions are made in this rule and others to allow #3.
Jim
Thank you for your help. Let me answer to these questions.
1. Yes, code is at the root folder(httpdocs)
2. Both sets of request go to this folder for code ( I dont know any other way).
3. All includes are relative with a start slash like /images/welcome.gif
4. My htaccess starts with the code you provided above and then further down the CSS I have rule,
RewriteRule ^login/?$ login.php [L]
So that login.php can be rewritten as /login/. It is this rule that is colliding with our above rules. You see, [L] flag is provided in your SSL exception rules and this one never gets written.
Do you suggest I put the SSL code at the end of the document?
I have your given rules at the top, then some rules of filename rewriting and 404 redirection at the end.
I hope it helps you determine my problem.
Yours truly,
Actually, if both SSL and non-SSL requests resolve to this .htaccess file, then the [L] flag has nothing to do with it. Why? Because a redirect response terminates the current HTTP transaction and asks the client (e.g. browser) to start a new one.
So if the request has the 'wrong' http/https protocol, it is redirected to use the correct protocol, and .htaccess is re-invoked when that new request arrives using the correct protocol. At this time, the internal rewrite to login.php takes place.
I suggest that you comment-out all but the first two of the three rules (the ones I posted above) and your own login->login.php rule. Then test with only those three rules enabled and see what happens. Given your answers to my five questions above, this should be working flawlessly. However, if any of your answers was not fully-correct, then it likely won't work at all.
Jim
It won't work if the code is in a location where it is not executed for the current HTTP request, or if any of the RewriteCond or RewriteRule patterns are incorrect for any reason (URL-path/file location errors, non-UTF-8 embedded characters, broken pipes, etc.).
You could in fact temporarily replace all of your code with one rule and see if that works:
RewriteCond %{SERVER_PORT} !=443
RewriteRule ^login https://www.example.com/login.php [R=302,L]
You might want to re-research your answers, because I have no more useful suggestions... :(
Jim
A redirect ends the current client-serer transaction and tells the client that it needs to start a new one, using the new URL supplied in the server's redirect response.
So no, your internal rewrite is not invoked in this current trqnsaction because the redirect to the correct protocol takes precedence -- it must be done first. Once the client "comes back" with a new HTTP request --this time using the correct protocol-- then your internal rewrite will be invoked.
If the simple rule works, then there are very likely still broken pipe characters in the http->https rule. Either that, or you are not typing the (required) trailing slash on "example.com/login/".
Jim
RewriteCond %{SERVER_PORT} =443
RewriteRule ^login/$ /login.php [L]
# HtAccess Below
Options +FollowSymLinks -MultiViews
RewriteEngine on
#
RewriteCond %{SERVER_PORT} =443
RewriteRule ^login/$ /login.php [L]
#
# Redirect secure pages requested via http to https
RewriteCond %{SERVER_PORT} !=443
RewriteRule ^((loginŠuser/welcomeŠuser/details)/.*)$ [example.com...] [R=301,L]
#
# Redirect non-secure pages requested via https back to http
RewriteCond %{SERVER_PORT} =443
RewriteRule !^(loginŠuser/welcomeŠuser/details)/ http://www.example.com%{REQUEST_URI} [R=301,L]
#
# Redirect non-canonical hostname requests to canonical hostname using originally-requested protocol
RewriteCond %{HTTP_HOST} !^(www\.example\.com)?$
RewriteCond %{SERVER_PORT}>s ^(443>(s)Š[0-9+]>s)$
RewriteRule ^(.*)$ http%2://www.example.com/$1 [R=301,L]