How to redirect / convert any URL to lowercase?
Solution 1
To implement such redirect using mod_rewrite and .htaccess you need to use RewriteMap
directive which cannot be placed in .htaccess -- only in server config / VirtualHost context. If you have such access:
1. Place this line inside <VirtualHost>
block for your site:
RewriteMap lc int:tolower
2. Place this in your .htaccess:
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule . ${lc:%{REQUEST_URI}} [R=301,L]
This will redirect (301 Permanent Redirect) any URL that has at least 1 capital letter (Latin letters only) in path part of URL (query string is ignored) to the same but in lower case.
For example:
http://mydomain.com/myfolder-sample-URL.html
=>
http://mydomain.com/myfolder-sample-url.html
http://mydomain.com/myfolder-sample-url.HTML
=>
http://mydomain.com/myfolder-sample-url.html
but will do nothing for these URLs:
http://mydomain.com/myfolder-sample-url.html?say=MEOW
http://MYDOMAIN.com/myfolder-sample-url.html
If you want to restrict it to .html files only:
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule ^.+\.html$ ${lc:%{REQUEST_URI}} [NC,R=301,L]
Where to place: I would place it after domain name redirect rule:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^domain\.com [NC]
RewriteRule (.*) http://mydomain.com/$1 [L,R=301]
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule . ${lc:%{REQUEST_URI}} [R=301,L]
# your other rules
I also recommend using rel="canonical" links:
<link rel="canonical" href="PROPER_URL_HERE" />
- http://www.google.com/support/webmasters/bin/answer.py?answer=139394
- http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html
If you do not need redirect, but rather ability to serve the file regardless of the file name case (case insensitive file names), then you can use mod_spelling ( http://httpd.apache.org/docs/current/mod/mod_speling.html ) and CheckCaseOnly On
directive.
Solution 2
On Apache 2.4 you can convert the URL-path to lowercase in .htaccess
(only) with an Apache Expression in a RewriteCond
(mod_rewrite) directive. No need to define a RewriteMap
in the server config (or write a plethora of rules to replace each letter one by one).
For example:
RewriteEngine On
RewriteCond expr "tolower(%{REQUEST_URI}) =~ /(.*)/"
RewriteRule [A-Z] %1 [R=301,L]
The RewriteRule
pattern [A-Z]
simply checks that there is at least one uppercase letter in the URL-path before continuing.
By passing expr
as the TestString (1st arg) to the RewriteCond
directive, the CondPattern (2nd arg) is treated as an Apache Expression. This performs a regex comparison which is always successful and the result of the tolower()
function is captured by the parenthesised subpattern in the regex. This is then accessible using the %1
backreference in the RewriteRule
substitution.
Note that this particular example just converts the URL-path. The query string (and hostname) remain unchanged.
The above checks every requested URL. To exclude all URLs that look like a static resource (ie. that end with what looks-like a file extension) then add a preceding condition with a negated expression. For example:
RewriteCond %{REQUEST_URI} !\.\w{2,4}$
RewriteCond expr "tolower(%{REQUEST_URI}) =~ /(.*)/"
RewriteRule [A-Z] %1 [R=301,L]
The \w
shorthand character class already includes both upper and lowercase letters, so no need for the NC
flag here.
To specifically target just .html
files (as mentioned in the question) then use a case-insensitive condition that checks for this. For example:
RewriteCond %{REQUEST_URI} \.html$ [NC]
RewriteCond expr "tolower(%{REQUEST_URI}) =~ /(.*)/"
RewriteRule [A-Z] %1 [R=301,L]
NB: Test first with a 302 (temporary) redirect before committing to a 301 (permanent) redirect so as to avoid potential caching issues.
Solution 3
Add this to the top of your .htaccess
SOURCE: Htaccess to Redirect Uppercase to Lowercase
RewriteEngine On RewriteBase / # If there are caps, set HASCAPS to true and skip next rule RewriteRule [A-Z] - [E=HASCAPS:TRUE,S=1] # Skip this entire section if no uppercase letters in requested URL RewriteRule ![A-Z] - [S=28] # Replace single occurance of CAP with cap, then process next Rule. RewriteRule ^([^A]*)A(.*)$ $1a$2 RewriteRule ^([^B]*)B(.*)$ $1b$2 RewriteRule ^([^C]*)C(.*)$ $1c$2 RewriteRule ^([^D]*)D(.*)$ $1d$2 RewriteRule ^([^E]*)E(.*)$ $1e$2 RewriteRule ^([^F]*)F(.*)$ $1f$2 RewriteRule ^([^G]*)G(.*)$ $1g$2 RewriteRule ^([^H]*)H(.*)$ $1h$2 RewriteRule ^([^I]*)I(.*)$ $1i$2 RewriteRule ^([^J]*)J(.*)$ $1j$2 RewriteRule ^([^K]*)K(.*)$ $1k$2 RewriteRule ^([^L]*)L(.*)$ $1l$2 RewriteRule ^([^M]*)M(.*)$ $1m$2 RewriteRule ^([^N]*)N(.*)$ $1n$2 RewriteRule ^([^O]*)O(.*)$ $1o$2 RewriteRule ^([^P]*)P(.*)$ $1p$2 RewriteRule ^([^Q]*)Q(.*)$ $1q$2 RewriteRule ^([^R]*)R(.*)$ $1r$2 RewriteRule ^([^S]*)S(.*)$ $1s$2 RewriteRule ^([^T]*)T(.*)$ $1t$2 RewriteRule ^([^U]*)U(.*)$ $1u$2 RewriteRule ^([^V]*)V(.*)$ $1v$2 RewriteRule ^([^W]*)W(.*)$ $1w$2 RewriteRule ^([^X]*)X(.*)$ $1x$2 RewriteRule ^([^Y]*)Y(.*)$ $1y$2 RewriteRule ^([^Z]*)Z(.*)$ $1z$2 # If there are any uppercase letters, restart at very first RewriteRule in file. RewriteRule [A-Z] - [N] RewriteCond %{ENV:HASCAPS} TRUE RewriteRule ^/?(.*) /$1 [R=301,L]
Alternatively your host may support mod_speling, in which if they do, you can use in the server config, virtual host, directory or within a .htaccess file, example below:
<IfModule mod_speling.c>
CheckCaseOnly On
CheckSpelling On
</IfModule>
Related videos on Youtube
CarrKnight
Updated on September 18, 2022Comments
-
CarrKnight over 1 year
I am using:
<IfModule mod_rewrite.c> Options +FollowSymLinks RewriteEngine On RewriteCond %{HTTP_HOST} ^example\.com [NC] RewriteRule (.*) http://example.com/$1 [L,R=301] </IfModule>
But I want to rewrite all UPPERCASE characters to lowercase characters, e.g:
- OLD:
/myfolder-sample-URL.html
- NEW:
/myfolder-sample-url.html
-
LazyOne over 12 yearsTo implement such redirect using mod_rewrite and .htaccess you need to use RewriteMap directive which cannot be placed in .htaccess -- only in server config / VirtualHost context. Do you have access to server config? Can you change it? If no -- then you can only implement it when executing the actual page (using PHP/ASP.NET etc).
-
CarrKnight over 12 yearsThanks for suggestion, Yes I have access to RewriteMap, so... what should I do now?
- OLD:
-
Stephen Ostermiller over 6 yearsIs there any reason to prefer to use these 26 separate rewrite rules opposed to the two line rewrite ruling using
lc:
from LazyOne's answer? -
Simon Hayter over 6 yearsDepends on the situation, the one I listed requires just on htaccess however the shorter version requires both virtual host and htaccess because of the initial
RewriteMap lc int:tolower
requirement. -
Simon Hayter over 6 yearsThe reason I posted this answer was because I closed a very similar question which asked for a htaccess only method.
-
MrWhite over 6 years"If you do not need redirect, ... you can use mod_spelling" - mod_speling (one L) will, in fact, issue a 301 redirect to the intended document.