8

I would like to redirect a URL with uppercase characters http://localhost/A/B to a lowercase version http://localhost/a/b using the .htaccess file.

Using regex I can capture A and B but is it possible to convert them to lowercase?

0
10

In .htaccess

<IfModule mod_speling.c>
CheckSpelling on
</IfModule>

Tested, works, if you have the mod_speling enabled.

Or, in a serverwide httpd.conf:

RewriteEngine On
RewriteMap  lc int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule (.*) ${lc:$1} [R=301,L]

From: http://www.chrisabernethy.com/force-lower-case-urls-with-mod_rewrite/

4
  • he specifically said using .htaccess ! you should had read the comments before even copying the link. – Prix Sep 3 '10 at 9:10
  • Indeed, well spotted. My answer will cause a server error in an .htaccess file. :o – Grizly Sep 3 '10 at 9:28
  • oops! I was about to jump in joy looking at Grizly's reply :-( – tintin Sep 3 '10 at 9:33
  • Added a working .htaccess version.. ;-) Of course, if you don't have access to httpd.conf, you probably won't have access to load the speling module.. will only lowercase if the folder/file is in lowercase on filesystem. – Grizly Sep 3 '10 at 10:43
2
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]
3
  • 1
    You should reference where you got your solution from: askapache.com/htaccess/rewrite-uppercase-lowercase – cdmckay Oct 28 '16 at 2:34
  • 1
    It's not working. Did you test it before posting Answer? – Pratik Kamani Nov 16 '17 at 5:24
  • This won't work as written if you are wanting to convert virtual URL paths that contain additional pathname information (path-info). You will need the DPI flag (Apache 2.2.12+) on each of the internal rewrites in order to discard the path-info and prevent it being re-appended to the rewritten URL. – MrWhite Nov 24 '20 at 18:32
0

If you are on Apache 2.4 then in .htaccess you can use mod_rewrite with an Apache expression in a RewriteCond directive to make use of the tolower() function.

For example, the following will need to go near the top of your .htaccess file:

RewriteEngine On

RewriteCond expr "tolower(%{REQUEST_URI}) =~ /(.*)/"
RewriteRule [A-Z] %1 [R=301,L]

This redirects/corrects any URL containing uppercase letters to the same - all lowercase - URL.

The RewriteRule pattern [A-Z] simply checks there is at least one uppercase letter in the requested URL-path. The RewriteCond directive then calls the tolower() function on the URL-path (REQUEST_URI server variable) the result of which is then effectively captured using the regex /(.*)/.

The %1 backreference in the substitution string then holds the result of the tolower() function call (as stored by the capturing group in the preceding condition), ie. the lowercase'd URL-path.

Test first with a 302 (temporary) redirect to avoid potential caching issues and only change to a 301 (permanent) when you are sure it's working OK. 301s are cached persistently by the browser so can making testing problematic.

Not the answer you're looking for? Browse other questions tagged or ask your own question.