Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

We're trying to enforce HTTPS on certain URLs and HTTP on others. We are also rewriting URLs so all requests go through our index.php. Here is our .htaccess file.

# enable mod_rewrite
RewriteEngine on

# define the base url for accessing this folder
RewriteBase /

# Enforce http and https for certain pages
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/(en|fr)/(customer|checkout)(.*)$ [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/(en|fr)/(customer|checkout)(.*)$ [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# rewrite all requests for file and folders that do not exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?query=$1 [L,QSA]

If we don't include the last rule (RewriteRule ^(.*)$ index.php?query=$1 [L,QSA]), the HTTPS and HTTP rules work perfectly however; When we add the last three lines our other rules stop working properly.

For example if we try to goto https:// www.domain.com/en/customer/login, it redirects to http:// www.domain.com/index.php?query=en/customer/login.

It's like the last rule is being applied before the redirection is done and after the [L] flag indicating the the redirection is the last rule to apply.

UPDATE

We added [NS] flags to all our rules but it made no difference.

share|improve this question
    
Did you ever figure this out? I think this is the same issue I'm asking about here: serverfault.com/questions/560565/… –  Jay F Dec 12 '13 at 0:19
    
Received a great answer to (my version) of this same issue here: serverfault.com/a/561353/202138 –  Jay F Dec 16 '13 at 2:53
add comment

2 Answers

Your first two rules are hitting it the first time and then making an additional request (because of the 301), which will hit the third RewriteRule on re-entry. Try this one instead: I added an exception for your "checkout" path:

# enable mod_rewrite
RewriteEngine on

# define the base url for accessing this folder
RewriteBase /

# Enforce http and https for certain pages
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/(en|fr)/(customer|checkout)(.*)$ [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/(en|fr)/(customer|checkout)(.*)$ [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(en|fr)/(customer|checkout)(.*)$ [NC]
RewriteRule ^(.*)$ index.php?query=$1 [L,QSA]

Hope that helps!

share|improve this answer
    
Since the customer and checkout URLs are not files or directories, I need the last rule to be applied to these URLs as well. This makes it so I get a page not found. –  user39461 Apr 2 '10 at 16:22
add comment

What behavior are you expecting?

https://site.com/en/customer/login would not be affected by the first or second rule in your .htaccess, and since /en/customer/login isn't a file or directory on your system, it will rewrite.

http://site.com/en/customer/login would be affected by your first rule, and would be redirected to https://site.com/en/customer/login. Since it was redirected, it is now a new response, would not be affected by the first or second rule in your .htaccess, and would match the last test (/en/customer/login doesn't exist as a file or directory) and it would rewrite.

http://site.com/en/somethingelse would not be affected by your first or second rule, and since /en/somethingelse doesn't exist, it would rewrite the url.

https://site.com/en/somethingelse would not be affected by the first rule, would be redirected to http://site.com/en/somethingelse. Since it was redirected, it is a new response, would not be affected by the first or second rule in your .htaccess, and would match the last test (/en/somethingelse doesn't exist as a file or directory) and it would rewrite.

share|improve this answer
    
This is the exact behavior I'm expecting. I want anybody accessing the customer or checkout sections at our site to be under https and everywhere else to be under http. The first two rules are suppose to check if the correct protocol is being used (if not, it redirects) otherwise it should continue to the third rule to actually rewrite the URL so our web application know what page to serve up. Everything works as expected until we add the third rule. It's like it does the rewriting before it does the redirection (see second paragraph after .htaccess code) –  user39461 Apr 2 '10 at 16:18
    
https:// www.domain.com/en/customer/login would not match either of your first two rules, and would be rewritten internally. If you are getting a 301/302 redirect at that point, your application is likely the culprit. RewriteLogLevel 9 RewriteLog /tmp/rewrites restart apache, watch those to see what happens when the site is hit. But, based on the .htaccess you have posted, apache would not do a redirect to http:// www.domain.com/index.php?query=en/customer/login –  deleted Apr 2 '10 at 17:19
    
https:// www.domain.com/en/customer/login is getting rewritten as http:// www.domain.com/index.php?query=en/customer/login. I've checked my code and using firebug and it seems really seems like it's apache that's doing it. We're doing the redirects using php for now but it's a bit of pain. I would much prefer if we could get it to work with mod_rewrite. –  user39461 Apr 2 '10 at 21:24
    
put a temporary index file in with print_r($_SERVER); Does it redirect then? If so, it is apache. But, the last redirect you have does an internal rewrite and wouldn't do a 301/302. If it is rewriting the URL in the browser, something external is doing the rewrite. Also, if apache did 301/302 it, it would redirect to the proper http/https url, and you're saying that isn't what you are witnessing. –  deleted Apr 2 '10 at 23:51
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.