Search code examples
regexapache.htaccessmod-rewriteurl-rewriting

Redirect non-www to www giving me hundreds of 404's


Thanks to anyone who can take a moment to look at this.

Recently I created a new section "subdomain" in my website and in this new folder I have includes a Joomla CMS installation the url looks like this: http://www.example.com/subdomain/

In this folder I have a htaccess file to which I have added.

## No directory listings
# Redirect non-www to www:
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]

When I try to access say http://example.com/subdomain/anytrailingstring then it's NOT redirecting me to http://www.example.com/subdomain/anytrailingstring as I expected, it is redirecting to http://www.example.com/anytrailingstring leaving out the /subdomain/ and this is of course a page that doesnt exist and therefore a 404.

This is a problem.

I do not have any directive in the root .htacces file except for this :

DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Can someone perhaps see why the subdomain htaccess isnt redirecting to correctly? Did I miss something?

I am not good with htaccess at all, if anybody can help me I would really appreciate it. Thanks!


Solution

  • RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
    

    You need to use the REQUEST_URI server variable instead of the backreference ($1). The URL-path matched by the RewriteRule pattern (first argument) is relative to the current directory, so excludes the parent subdirectory (ie. /subdomain in your example).

    Do it like this instead:

    RewriteCond %{HTTP_HOST} !^www\.
    RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    

    You will need to clear your browser cache since the erroneous (301 - permanent) redirect will have been cached by the browser. Test with 302 (temporary) redirects to avoid potential caching issues.

    However, a couple of questions:

    • Why are you not using HTTPS? (You are redirecting to HTTPS in the parent .htaccess file - but this is now being overridden by the mod_rewrite directives in the subdirectory.)
    • Why not include this in the parent .htaccess file?

    UPDATE: So, taking the above points into consideration... if you want to move this rule to the parent .htaccess file in the root then have it like this:

    DirectoryIndex index.php
    Options +FollowSymLinks
    RewriteEngine on
    
    # Redirect non-www to www (and HTTPS)
    RewriteCond %{HTTP_HOST} !^www\.
    RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    
    # Redirect HTTP to HTTPS
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    

    The order of the directives is to ensure there is only ever at most 1 redirect (assuming you are not implementing HSTS).

    You were unnecessarily duplicating the RewriteEngine directive (so I removed the second instance).

    The RewriteBase directive was not being used.

    The capturing subgroup in your HTTP to HTTPS rule was not required. ie. ^ is better than ^(.*)$ in this instance.


    Aside:.

    ...a new section "subdomain" in my website and in this new folder I have includes a Joomla CMS installation the url looks like this: http://www.example.com/subdomain/

    This is a subdirectory, not a "subdomain".

    This is a "subdomain":

    http://subdomain.example.com/