Search code examples
apache.htaccessmod-rewriteurl-rewriting

htaccess changing automaticly the RewriteRule


I am trying to fix this error I had after adding these rules for HTTPS and non-www to .htaccess file on top

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301,QSA]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.%{HTTP_HOST}%{REQUEST_URI} [L,NE,R=301,QSA]

it did fix the HTTPS and non-www but it messed this rule

RewriteRule ^product/([0-9]+)$ product.php?p=$1 [NC,L,QSA]

it's now changing this URL whenever there is no HTTPS or no www

  • from : www.example.com/product/2443
  • to : www.example.com/product.php/2443?p=2443

I want it to go back to this again:

  • www.example.com/product/2443

Solution

  • It sounds like you've put the directives in the wrong order. Your canonical redirects (HTTP to HTTPS and non-www to www) need to be at the top of the .htaccess file before your internal rewrites.

    Also, since you are internally rewriting to a file with the same basename as the requested URL-path you will need to make sure that MultiViews is disabled to prevent mod_negotiation from internally issuing a subrequest for /product.php/2443 before mod_rewrite is able to process the request. For example, at the top of your .htaccess file add the following to ensure that MultiViews is disabled:

    Options -MultiViews
    

    You will need to clear your browser cache, since these erroneous (301 - permanent) redirects will have been cached by the browser.

    Aside:

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

    Reverse these two rules to avoid a double redirect when requesting HTTP + non-www. However, you should leave these as they are if you are planning to implement HSTS.

    The QSA flag is not required on either of these rules.

    And the capturing RewriteRule pattern (ie. (.*)) is superfluous. It would be more efficient to just use ^ (or $) - an assertion - since it only needs to be successful for everything, it doesn't need to actually match anything.