I write a lot of RewriteRule in my .htaccess
file , but problem occurs when I switch from https to http pages; it
For your HTTPS issue I would match on port or HTTPS as there are known apache problems relating to the HTTPS tag.
To cover this match on both (as shown in your edited answer)
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} != on
##REWRITE RULE
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTPS} = on
##REWRITE RULE
A valid point is also that %{REQUEST_URI}
isn't affected by any substitutions.
The way you are using it at the moment, if any rule matches you will send them to the original url (before any substitution started).
If you want to take the url after and substition and matching use $1
Answers to your further questions:
This is because your [NC]
isn't on the rewrite cond for the HTTPS section of your .htaccess
You match RewriteCond %{REQUEST_URI} /login [OR]
this is only looking for lower case login, if you want to accept uppercase login append NC.
No, it depends what you want to do [NC]
says don't match case on this rule, if you don't want to match case on that rule (or condition) then add it.
Not matching the case with [NC]
means site.com/login.php = sYte.cOm/LoGin.PHP
[L]
means if this is true, stop processing everything
QSA applies when you have a ? in your substitution and you want to append toe old string to the new URL
Consider the following rule:
RewriteRule /pages/(.+) /page.php?page=$1 [QSA]
With the [QSA]
flag, a request for /pages/123?one=two
will be mapped to /page.php?page=123&one=two
. Without the [QSA] flag, that same request will be mapped to /page.php?page=123
- that is, the existing query string will be discarded.
Do use QSA if you want to keep any additional get arguments.
Another further question
The only way for this to happen is if you have a redirect [R=301]
somewhere in your code, the only place I can see that is this section:
# Rewrite to https
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} != on
RewriteCond %{REQUEST_URI} (/login|/do_login)\.php [NC]
RewriteRule ^(.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Where this will only match the following URL's
.php, /login.php, /do_login.php
I believe the culprit is as I outlined in the first response with %{REQUEST_URI}
Your code essentially says, if these conditions are met, send them to https://theurltheywentto, which is not what you want to do, you want to send them to /login.
Have you tried using (as mentioned in my https section)
RewriteRule ^(.*) https://%{HTTP_HOST}/login [R=301,L]
Or perhaps (if you have /do_login) and other options
RewriteRule ^(.*).php https://%{HTTP_HOST}/$1 [R=301,L]
Where test.com/do_login.php will become https://test.com/do_login
How about you try:
# Rewrite to https
RewriteCond %{REQUEST_URI} (/login|/do_login)\.php [NC]
RewriteCond %{HTTPS} != on
RewriteRule ^(.*)\.php https://%{HTTP_HOST}/$1 [R=301,L]