Slashes and Duplicates

Trailing Slashes, Case and Duplicate Content

/About, /about/ and /index.php are three URLs to a crawler. Google counts a redirect as a strong canonical signal, so pick one spelling and redirect the rest to it:

Redirecting index files, stray slashes and uppercase to one spellingApache config
# /var/www/example/.htaccess: one spelling per page (after the 2.6.2 rules)
# Needs: mod_rewrite; AllowOverride FileInfo; "RewriteMap lc int:tolower" in the vhost
RewriteEngine On
# A directory's home page is its folder URL, not index.html or index.php
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*/)?index\.(html|php)$ https://example.com/$1 [R=301,L]
# No trailing slash on anything that is not a real directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ https://example.com/$1 [R=301,L]
# Lowercase paths, except files that really exist in mixed case
RewriteCond %{REQUEST_URI} [A-Z]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ https://example.com${lc:%{REQUEST_URI}} [R=301,L]

Line 5 limits the index rule to the browser's own request. After an internal rewrite to index.php (Front-Controller Routing), REDIRECT_STATUS is set; without the condition, every route in the combined file answered 301 to /. Real directories keep their slash, which mod_dir's DirectorySlash adds with its own 301. RewriteMap is not allowed in .htaccess, so the one-line lc map lives in the vhost.

Output of 52
/index.html          301 https://example.com/
/docs/index.php?x=1  301 https://example.com/docs/?x=1
/docs                301 https://example.com/docs/
/about/              301 https://example.com/about
/About.html          301 https://example.com/about.html
/img/Logo.PNG        200

For a copy you cannot redirect, such as a PDF, send Header set Link "<https://example.com/guide.pdf>; rel=\"canonical\"" inside <Files> (mod_headers).