phpapache.htaccessmod-rewriteno-www

.htaccess redirect www to non-www but not doing anything


If I go to https://example.com, then everything is working fine. However if I go to https://www.example.com, then none of my static files load because it says that it goes against the CSP. Thus, I'm trying to redirect all www requests to non-www.

Here is my .htaccess code:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule ^$ public/ [L]
    RewriteRule (.*) public/$1 [L]

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

    RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

</IfModule>

<IfModule mod_headers.c>
    Header set Content-Security-Policy: "default-src 'self'; font-src https://fonts.gstatic.com; style-src 'self' https://fonts.googleapis.com; img-src 'self'; child-src 'none';"
...
</IfModule>

Solution

  • <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteRule ^$ public/ [L]
        RewriteRule (.*) public/$1 [L]
    
        RewriteCond %{HTTPS} off 
        RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
        RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
        RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
    </IfModule>
    

    Your rules are in the wrong order (and incorrect). The canonical redirects need to go before the internal rewrites to the /public subdirectory (where I assume you have another .htaccess file). As written, they are not doing anything. But also, your redirect to supposedly remove the www prefix is not doing that, but instead redirecting to the same host, which would have resulted in a redirect loop.

    Your rules should be written like this instead:

    RewriteEngine On
    
    # Redirect www to non-www (and HTTPS)
    RewriteCond %{HTTP_HOST} ^www\.(.+?)\.?$ [NC]
    RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
    
    # Redirect HTTP to HTTPS (already non-www)
    RewriteCond %{HTTPS} off 
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    
    # Rewrite everything to the "public" subdirectory
    RewriteRule (.*) public/$1 [L]
    

    No need for the <IfModule> wrapper and the first rule (ie. RewriteRule ^$ public/) is redundant since this would be handled by the second rule anyway.

    By redirecting from www to non-www (and HTTPS) first we minimise the number of canonical redirects to at most one. But this does assume you are not intending to implement HSTS.

    if I go to https://www.example.com, then none of my static files load because it says that it goes against the CSP.

    Probably because you are referencing your "static files" using absolute URLs of the form https://example.com/..., not www.example.com.