.htaccesshttp-redirecthttp-status-code-302

302 "Found" page when trying to redirect from HTTP to HTTPS


I'm am trying to set up a redirect from HTTP to HTTPS for a client site. I added the following code to the .htaccess file:

RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

But doing so brought users to a 302 "Found" page when visiting HTTP pages on the site, instead of redirecting them to the HTTPS version.

I'm trying to figure out why this happens, and how to fix the issue to get the desired outcome. The site already forces a www subdomain - which could be contributing to the issue..?

Using apache on an Ubuntu server.


Solution

  • This sounds like you have a conflict with other directives. You are missing the L (last) flag from your rule, so processing continues through the file instead of triggering an immediate redirect.

    You should also be explicit and include the R flag, which you will need to do when this is changed to a 301 (permanent) redirect.

    Note also that this rule must be near the top of the file before any existing rewrites.

    For example:

    :
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
    

    I changed the pattern from (.*) to ^ which is more efficient and since you are not using the backreference in the substitution.

    Detail on the L and R flags...

    The L (last) flag prevents any mod_rewrite rules that follow being processed during the current pass by the rewrite engine. Effectively saying this is the last rule (although, to complicate matters, that's not necessarily the case when combined with internal rewrites in a directory context). In the case of an external redirect, processing stops completely and the redirect response is sent back to the client. The L (or END) flag nearly always needs to be used with external redirects. (There is no difference between L and END when it comes to external redirects. END is only available on Apache 2.4+)

    The R flag triggers an external redirect. ie. A redirect response is sent back to the client with a Location HTTP response header. If an HTTP response code is not stated then it defaults to a 302 (temporary) redirect. You need to state the HTTP response code to make it a 301 (permanent) redirect - which an HTTP to HTTPS redirect should ultimately be. Note that 301 (permanent) redirects are cached by the browser (and possibly intermediary) caches, so can make testing problematic. For this reason always test with 302 (temp) redirects first.

    If an R flag is not included and you specify an absolute URL in the substitution string (as you did here) then - on most systems - it actually defaults to a 302 (temp) redirect. But you should be explicit and include the R flag to formerly declare your meaning.

    Reference, from the Apache docs: