Search code examples
apachemod-rewritecanonical-link

Non www to www redirect doesn't removes trailing backslash


I'm having a bit of problem with Apache redirect. While bellow rules work for any page on site, mydomain.com will get redirected to mydomain.com//, which ignores trailing slash removal rule.

Also is it efficient to use multiple rules such as this or should I try to combine them or chain them somehow together in order to avoid multiple redirects for single url?

Thanks

#Turn on options for url rewriting
         Options +FollowSymlinks
         RewriteEngine on

 #lovercase all urls
         RewriteMap  lc int:tolower
         RewriteCond %{REQUEST_URI} [A-Z]
         RewriteCond %{REQUEST_URI} ^/fonts/.*
         RewriteCond %{REQUEST_URI} ^/css/.*
         RewriteCond %{REQUEST_URI} ^/js/.*
         RewriteRule (.*) ${lc:$1} [R=301,L]

 #redirect all requests made to http:// to http://www.
         RewriteCond %{HTTP_HOST} ^mydomain\.com$ [NC]
         RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R=301,L]

 #removes trailing slash
         RewriteCond %{REQUEST_FILENAME} !-f
         RewriteCond %{REQUEST_FILENAME} !-d
         RewriteCond %{HTTP_HOST} !^\.localhost$ [NC]
         RewriteRule ^(.+)/$ http://%{HTTP_HOST}$1 [R=301,L]

Solution

  • The reason the mydomain.com gets redirected to www.mydomain.com// is because you have an extra "/" in your rewrite rule target:

    RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R=301,L]
                                              ^----here
    

    When you have rules in your server/vhost config, the leading slash isn't removed so that gets match and used as a backreference, so mydomain.com is / which matches ^(.*)$ and the target becomes http://www.mydomain.com//. So you can either remove the slash in the target or add one to the regex:

    RewriteRule ^(.*)$ http://www.mydomain.com$1 [R=301,L]
    or
    RewriteRule ^/(.*)$ http://www.mydomain.com/$1 [R=301,L]
    

    Your other rule you have:

         RewriteCond %{REQUEST_FILENAME} !-f
         RewriteCond %{REQUEST_FILENAME} !-d
         RewriteCond %{HTTP_HOST} !^\.localhost$ [NC]
         RewriteRule ^(.+)/$ http://%{HTTP_HOST}$1 [R=301,L]
    

    are fine. They are for removing trailing slashes when there is something between them, e.g. /something/, because of the (.+). It wouldn't match // anyways because that inherently gets turned into just /. You just need to prevent redirecting to http://www.mydomain.com//