Forum Moderators: phranque

Message Too Old, No Replies

Whats wrong with my rules

htaccess

         

khuram

5:46 pm on Nov 2, 2009 (gmt 0)

10+ Year Member



Hi,

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,

jdMorgan

7:53 pm on Nov 2, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You have back-referenced the local variable "%1". To what did you intend this to refer?

If this code is intended for use in .htaccess, then the "/?" at the beginning of each pattern is not really necessary.

Jim

khuram

10:15 am on Nov 3, 2009 (gmt 0)

10+ Year Member



Hi Jim,

I will remove my /? part but will it make any difference?
can you suggest me a tutorial of SSLing a set number of files and leave all others back to http?

Khuram

TheMadScientist

10:28 am on Nov 3, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



What jdMorgan means is %1 is a back-reference to a RewriteCond not a RewriteRule... To get the information stored in the () on your rule, you will need to use $1 rather than %1. You will also need to make an adjustment for your negative match (I think. I didn't test & don't remember off the top of my head, because I do things a bit different.), because your are saying 'not one of these pages' and the actual location requested will not be stored, even if I'm wrong and it is stored it's an easy adjustment and you can add some efficiency, because the information you need is already stored in %{REQUEST_URI}, so you can actually make your rules a bit better: (I left the first one with the back-reference, even though it could be changed to the same as the second...)

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.

khuram

12:02 pm on Nov 3, 2009 (gmt 0)

10+ Year Member



Hi,

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

jdMorgan

1:52 pm on Nov 3, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It sounds like you have other rules in this file or in a server config file "above" this file that are doing internal rewrites from extensionless URLs to \.php files. This code is executing before your http<->https external redirect code, and the result is that the previously-rewritten internal .php filepath is being 'exposed' to the client by the subsequent redirect.

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

khuram

10:05 am on Nov 4, 2009 (gmt 0)

10+ Year Member



Hi,

In my htaccess, the only rules above this https forcing are

<IfModule mod_rewrite.c>
Options FollowSymLinks
RewriteEngine on
RewriteBase /

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

TheMadScientist

10:34 am on Nov 4, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Try the following:

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]

khuram

11:56 am on Nov 4, 2009 (gmt 0)

10+ Year Member



Hi,

I changed my code with your code and now Firefox is not displaying the page saying "The page isn't redirecting properly".

Can you please suggest.

TheMadScientist

1:05 pm on Nov 4, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



It means you're stuck in an 'infinite loop' and I'm not seeing why from the code I posted, but I don't know if there are other rules in the file after what's posted here that could be conflicting and causing the loop or not... What you're doing in this section of code is fairly basic and straight-forward. One way to troubleshoot what I posted is to remove the rest of the rules from the file briefly (just cut and paste them to another file, so you can put them right back) then test the ruleset I posted and see if it works or not. (Make sure you empty your browser cache before testing.) If it works, then there's another conflict, if not, then it's what I posted. I'm not seeing anything wrong with it right now, but maybe a fresh set of eyes will notice something I'm missing.

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

khuram

1:29 pm on Nov 4, 2009 (gmt 0)

10+ Year Member



Hi Mad, Jim

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]

jdMorgan

1:42 pm on Nov 4, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The problem is likely the pipe characters. See the note below. Also, your domain canonicalization code always forces http, so that will also cause problems. Several optimizations are also possible:

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]

Important: Replace all broken pipe "Š" characters above with solid pipe characters before use; Posting on this forum modifies the pipe characters.

Jim

khuram

12:36 pm on Nov 26, 2009 (gmt 0)

10+ Year Member



Hi,

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,

jdMorgan

2:03 pm on Nov 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Any method you apply will do the same thing. That is, no matter how you implement the redirection, you'll have the same problems.

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

khuram

2:17 pm on Nov 26, 2009 (gmt 0)

10+ Year Member



Hi Jim,

Thanks for your reply.
So it means that I will have to make my links/form actions like

<?php echo SECURE_PROTOCOL.SITE_URL.'/login/';?>

I have many pages like this with user area and important stuff. Do I change everything ?

jdMorgan

4:10 pm on Nov 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Not necessarily. It is the client (e.g. browser or search robot) that resolves page-relative or server-relative links to the protocol + "full" URLs that must be used to make HTTP requests. If a link is relative, then the client will 'keep' any part of the current page's URL that is not specified in the link. So a page-relative link on an SSL page will be requested using "https://current-page-domain/directory-path-to-current-page's-directory/<relative-link-here>

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

khuram

4:36 pm on Nov 26, 2009 (gmt 0)

10+ Year Member



Hi 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.
:)

jdMorgan

6:45 pm on Nov 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This code is identical to what I posted above, except for the change to exclude /images and the deletion of a 'stray' end-anchor. It should work, as I have used code like this on dozens of sites, and despite appearances, it is actually very trivial code for those of us with a lot of experience...

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]

Again, you must edit this code and replace all broken pipe "Š" characters with solid pipe characters before use, otherwise it will not work at all. Also, be especially careful that the 'example.com' and 'www.example.com' references are correct. If the use of www and non-www is inconsistent/incorrect, then you can create a redirection loop.

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

khuram

9:19 pm on Nov 26, 2009 (gmt 0)

10+ Year Member



Hi 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

jdMorgan

9:33 pm on Nov 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Please confirm to us explicitly that you have replaced all broken pipe characters in the code above.

Jim

khuram

9:35 pm on Nov 26, 2009 (gmt 0)

10+ Year Member



Yes Jim, I did control + replace all ¦ symbols into pipe symbols. I swear :(

jdMorgan

11:24 pm on Nov 26, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Good -- We just need to know, to avoid wasting time. As you can tell, people check into this forum only infrequently, especially on holdays...

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.

These are all important -- If something is not clear, please ask!

Jim

khuram

7:14 am on Nov 27, 2009 (gmt 0)

10+ Year Member



Hi 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,

jdMorgan

2:07 pm on Nov 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks, it is helpful to know that all pre-conditions have been verified.

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

khuram

4:56 pm on Nov 27, 2009 (gmt 0)

10+ Year Member



Hi,
I have commented everything but your code above and then my only login -> login.php rule below.

Now when I click on /login/ link, it takes me to /login/ and not login.php as before. But still not https. its on http.

Please suggest

jdMorgan

5:11 pm on Nov 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



My only conclusion is that one of your answers to my five questions above (the pipe characters plus the four numbered questions) may not be completely correct. Otherwise, this code should work fine.

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]

If not, then this code is not being executed for http requests.

You might want to re-research your answers, because I have no more useful suggestions... :(

Jim

khuram

5:19 pm on Nov 27, 2009 (gmt 0)

10+ Year Member



Yes, this simple 1 rule works.
Means https is in right place. But doesnt L flag suggest that no more rules after that?

So /login/ becomes /login.php automatically. Its problem between login and login.php which is confusing apache.

Can I PM you my htaccess for you to see please :)

jdMorgan

5:44 pm on Nov 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm afraid you didn't understand my description of the HTTP redirect function above.

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

khuram

5:50 pm on Nov 27, 2009 (gmt 0)

10+ Year Member



Jim how can I show you my file

TheMadScientist

6:21 pm on Nov 27, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Try this before jdMorgan's ruleset:

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]

This 49 message thread spans 2 pages: 49