.htaccess rewrite http to https results in loop
On an apache 2.2 server running varnish, I am trying to redirect http -> to https for an entire Drupal Commons (http://commons.acquia.com/) site.
Since varnish caches some redirects (R=301, but not R=302, I think), I first got my redirect working at :8080 which is not served by varnish.
The below .htaccess code successfully redirects http:// foo.example.com:8080 to https:// foo.example.com. (Works in Chrome, FF and Safari.)
# RewriteBase /
### Standard Drupal7 .htaccess above here ###
# SSL REWRITES
RewriteCond %{SERVER_PORT} ^8080$
RewriteRule ^(.*)$ https://foo.example.com/$1 [NC,R=302,L]
### Standard Drupal7 .htaccess below here ###
# Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</IfModule>
If I
- Change 8080 in the above to 80
- save .htaccess
- restart varnish
- clear the Drupal cache
- clear the browser cache
- visit http:// foo.example.com
(I religiously did the above after every edit to .htaccess.)
I get a redirect loop in Chrome, FF, Safari when I visit http:// foo.example.com.
In an effort to understand the loop I changed the redirect as follows:
# SSL REWRITES
RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^(.*)$ https://foo.example.com/$1/%{SERVER_PORT} [NC,R=302,L]
and I got this in my location bar: https:// foo.example.com/80/80/80/80/80/80/80/80/80/80/80/80/80/80/80/80/80/80/80/80/80
When the browser is forwarded to the https url, shouldn't SERVER_PORT=443???
Changing to R=301 results in the same loop.
Testing %{HTTPS} results in the same loop.
# SSL REWRITES
#RewriteCond %{SERVER_PORT} ^80$
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://foo.example.com/$1/%{HTTPS} [NC,R=301,L]
now I get this in my location bar: https:// foo.example.com/off/off/off/off/off/off/off/off/off/off/off/off/off/off/off/off/off/off/off/off/off
Per http://drupal.org/node/181233#comment-278142 (and http://drupal.org/node/823232#comment-3075288) I also tried:
# SSL REWRITES
RewriteCond %{SERVER_PORT} ^80$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ https://foo.example.com/$1/%{SERVER_PORT} [NC,R=301,L]
Tried with and without the ! negation of -f and -d. Either way, the condition does not match so nothing happens. I don't know why these -f, -d tests would be needed....
I also tried removing the regular expression replacement in the RewriteRule
# SSL REWRITES
RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^.*$ https://foo.example.com/ [R=301,L]
this still results in a loop.
Any help would be much appreciated.
I found out from the server admins that they terminate SSL with Pound on this server. What that means is that SSL works, but the HTTP_SERVER variables do not reflect the values that I expected. SERVER_PORT will always be 80 and HTTPS will always be off regardless of the true state of things.
When using mod_rewrite, dump out your server variables to see what you can test with your RewriteCond's. See http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html#PHP_Code_access_Apache_Variables
You can also redirect http to https using most programming languages. I have Drupal's 443session module working with this site--it uses that approach. (I didn't have to tell the module to set up rules even though it couldn't detect that HTTPS was on.)
Make sure you use secure session cookies too. You need them in addition to mod_ssl to prevent session hijacking.
For Drupal this is old, but good http://drupalscout.com/knowledge-base/drupal-and-ssl-multiple-recipes-possible-solutions-https I think drupal.org/project/443session is the best module option currently.