1

I have a problem with mod_rewrite configuration. I have a website, where I need to push every request through index.php. I also would like to have redirect from http to https on every website, with one exception (folder /free). It sounds like trivial task, but I still have problems. My .htaccess configuration:

<IfModule mod_rewrite.c>
   SetEnv CAKEPHP_DEBUG 1
   RewriteEngine On

   RewriteCond %{HTTPS} on
   RewriteCond %{REQUEST_URI} ^/free$ [NC]
   RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] 

   RewriteCond %{HTTPS} off
   RewriteCond %{REQUEST_URI} !^/free$ [NC]
   RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-l
   RewriteCond %{REQUEST_URI} !^/(img|css|js|shared)/(.*)
   RewriteRule ^(.*)$ index.php [QSA,L]
 </IfModule>

It works well, except /free path. when https://test/free is called, there is a forward to http. After http call, redirect to https://website/index.php is returned. This is wrong - I would like to stay in http /free folder. How can I do this forward correctly? If I comment out forward from http to https, everything works well. Any ideas?

Edit: proposal from duplicated link did not work. The problem was duplicate processing by index.php rewrite - great answer with "end" flag resolved my issue

  • Possible duplicate of [.htaccess 301 redirect for all https to http EXCEPT ONE PAGE](http://stackoverflow.com/questions/2079015/htaccess-301-redirect-for-all-https-to-http-except-one-page) – Spartan May 11 '16 at 14:48

1 Answers1

2

For apache 2.3.9 and later:

If you are on apache 2.3.9 or later, you can use the END Flag in your last RewriteRule:

RewriteRule ^(.*)$ index.php [QSA,END]

From the docs:

Stop the rewriting process immediately and don't apply any more rules. Also prevents further execution of rewrite rules in per-directory and .htaccess context. (Available in 2.3.9 and later)

If you don't use the end flag, your request will be rechecked and therefore the rewritten request containing /index.php is different to /free and will be externally redirected to your https page.

For apache before 2.3.9:

If you cant use the END flag, you would have to go with %{THE_REQUEST} which contains the full HTTP request line which is not rewritten by internal redirects:

RewriteEngine on

RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} ^GET\ /free [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !^GET\ /free [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !^/(img|css|js|shared)/(.*)
RewriteRule .* index.php [QSA,L]