Someone gave me a script for my .htaccess file that’s supposed to make URL’s with capital letters and/or underscores default to lower case URL’s with dashes. Unfortunately, they don’t seem to really understand it and haven’t been able to tell me how to implement it.
So I played around with it and discovered that it works to an extent if I insert RewriteRules from my original .htaccess file near the end of the code (see the example below).
If I type MySite/World/NEW_YORK into my browser, it works perfectly, defaulting to mysite/world/new-york. However, if I type in MySite/World/Arizona, nothing happens. In other words, it seems that the script is triggered by underscores and doesn’t function without them.
Can anyone tell me how to modify this script so it works properly?
<IfModule mod_rewrite.c>
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
# There are similar lines for every letter of the alphabet...
# If there are any uppercase letters, restart at very first RewriteRule in file.
RewriteRule [A-Z] - [N]
#RewriteRule ^/?(.*) work/arfanweb/$1 [R=301,L]
RewriteCond %{ENV:HASCAPS} TRUE
RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N]
# RewriteRule ^([^_]*)_([^_]*)$ http://example.com/$1-$2 [L,R=301]
# RewriteRule ^([^_]*)_([^_]*)$ http://example.com/new/$1-$2 [L,R=301]
# I modified the above two lines...
RewriteRule ^([^_]*)_([^_]*)$ http://GS/$1-$2 [L,R=301]
RewriteRule ^([^_]*)_([^_]*)$ http://GS/new/$1-$2 [L,R=301]
# * * * * * * * * * *
# I added the following two lines...
ErrorDocument 404 /404.php
RewriteRule ^/?world/([a-zA-Z0-9()_/-]+)$ world/index.php?area=$1 [L]
</IfModule>
RewriteRule ![A-Z] - [S=28]
I’d comment this line out for now, and remove the skip flag (S=1) from the line above it. It’s trying to optimize performance, but it’s fragile. It will cause the following 28 rewrite rules to be skipped, so if you comment one line out or add more, then the correct number would no longer be 28, and this attempt to optimize performance would then inadvertently introduce a bug. I think you should keep it simple and just worry about getting correct behavior first.
RewriteCond %{ENV:HASCAPS} TRUE
RewriteRule ^([^]*)([^]*.*) $1-$2 [N]
I see a few problems here. First, that pattern actually matches two underscores instead of just the one it would replace. And second, if there are capital letters, then it won’t execute at all, which doesn’t seem right. I don’t see any reason why the lowercase operation and the hyphen operation would need to be linked at all. And third, by this point, there won’t be any capital letters, so this will actually never run.
> RewriteRule ^([^A]*)A(.*)$ $1a$2
# There are similar lines for every letter of the alphabet...
If you have access to your server’s config (as opposed to limited to htaccess files), then we could make this tremendously simpler.
# Create a tolower mapping-function using the internal tolower
# Rewrite maps are not allowed in htaccess files, so this line must go in the server config
RewriteMap tolower int:tolower
# And back in the htaccess...
# Replace CAP with cap
RewriteRule (.*) ${tolower:$1}
Thanks for the tips. I’ve seen comments about modifying the server’s config, but my understanding was that this is something users never have access to (online). However, this is so complex, I think I’ll e-mail my host and ask if they can let me access it.
On edit: I just e-mailed my host, and he said I was asking a coding question, which is outside their scope. He said I can default to lower case by simply adding this code to my .htaccess file:
RewriteMap lc int:tolower
Travis: RewriteRule (.*?[A-Z]+.*) ${lc:$1} [R]
But he also said I’m welcome to modify my server config file, while is located at /usr/local/apache/conf/httpd.conf
But first, I need to make sure it’s working locally before I publish it online. So I’ll try to find my local server config file and modify it as you suggested. Thanks again.
Dumb question, but how can you tell which httpd.conf is the right one? I’m using MAMP on a Mac, so I easily found a httpd.conf in Applications > MAMP. However, I modified it as you expected, but nothing changed with my URL’s. I then discovered there are at least one or two other httpd.conf files on my computer, but I’m not sure which is the “active” one. If I delete all the content, my pages display as before. Is there some kind of test I can do to determine which httpd.conf file is associated with my sites?
I don’t know how the files are organized on the Mac, sorry. 
And just to be clear, the only line that goes into the httpd.conf is…
RewriteMap tolower int:tolower
And this line by itself doesn’t convert your URLs to lowercase, but rather it allows your rewrites rules to invoke ${tolower:string}
OK, here’s where I’m at now…
I forgot that you have to restart your servers after changing a httpd.conf file. So I modified BOTH of the httpd.conf files that I found, then restarted my servers. I then modified my .htaccess file…
RewriteRule (.*) ${tolower:$1}
RewriteRule ^/?world/([a-zA-Z0-9()_/-]+)$ world/index.php?area=$1 [L]
Now I’m getting an Internal Server Error message.
Can you check what your error.log says?
I THINK this is the most relevant entry:
[Fri Apr 04 21:58:30 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
Other entries include…
[Sat Apr 05 05:59:45 2014] [error] [client 127.0.0.1] Attempt to serve directory: /Applications/MAMP/htdocs/
That certainly helps pinpoint the problem. Can you also post the full htaccess you’re using now, and the URL you tried to access that resulted in that error?
Sorry for the delay…just got home from work, slept and woke up.
Anyway, I was playing around with my .htaccess file before I saw your latest message. However, I think I’ve pretty much restored it as it was, plus I copied the latest errors from my log.
The URL’s I was trying to access are http://gs/world/Arizona and http://gs/world/NEW-YORK (which I ultimately want to default to arizona and new-york). If I capitalize the section name - World - then the links don’t work at all; I get a 404 error page.
P.S. What’s the correct way to edit a log? Is it OK to simply delete all the contents, or can I even delete the log file completely, then create a new file with the same name?
RewriteEngine On
RewriteRule ^test\\.htm$ test.php [L]
Options -MultiViews
php_flag magic_quotes_gpc Off
ErrorDocument 404 /404.php
RewriteRule (.*) ${tolower:$1}
RewriteRule ^/?about/([a-zA-Z0-9_/-]+)$ about/index.php?bout=$1 [L]
RewriteRule ^/?world/([a-zA-Z0-9()_/-]+)$ world/index.php?area=$1 [L]
RewriteRule ^/?topics/([a-zA-Z0-9_/-]+)$ topics/index.php?topic=$1 [L]
RewriteRule ^/?reference/([a-zA-Z0-9_/-]+)$ reference/index.php?ref=$1 [L]
# Note: I'm probably going to delete all the following rules...
RewriteRule ^/?ecosymbols/([a-zA-Z_]+)$ ecosymbols/index.php?taxon=$1 [L]
RewriteRule ^/?plants/([a-zA-Z0-9()_/-]+)$ plants/index.php?taxon=$1 [L]
RewriteRule ^/?animals/([a-zA-Z0-9()_/-]+)$ animals/index.php?taxon=$1 [L]
RewriteRule ^/?minerals/([a-zA-Z0-9()_/-]+)$ minerals/index.php?gem=$1 [L]
RewriteRule ^/?fossils/([a-zA-Z0-9()_/-]+)$ fossils/index.php?taxon=$1 [L]
RewriteRule ^/?soils/([a-zA-Z_]+)$ soils/index.php?soil=$1 [L]
RewriteRule ^/?flags/([a-zA-Z_]+)$ flags/index.php?vex=$1 [L]
RewriteRule ^/?names/([a-zA-Z_]+)$ names/index.php?nick=$1 [L]
RewriteRule ^/?mottoes/([a-zA-Z_]+)$ mottoes/index.php?motto=$1 [L]
RewriteRule ^/?songs/([a-zA-Z_]+)$ songs/index.php?tune=$1 [L]
RewriteRule ^/?symbols/([a-zA-Z0-9()_/-]+)$ symbols/index.php?etc=$1 [L]
Log Errors
[Sat Apr 05 14:54:31 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 14:54:31 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 14:54:31 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 14:54:56 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/GS/World/Arizona
[Sat Apr 05 14:55:05 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/2B/CSS/Misc/GW, referer: http://gs/world/Arizona
[Sat Apr 05 14:55:05 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/2B/CSS/World/HomeW.css, referer: http://gs/world/Arizona
[Sat Apr 05 14:55:06 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/2B/inc/D/Shared/Body/Bottom/Footer, referer: http://gs/world/Arizona
[Sat Apr 05 15:01:07 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/2B/CSS/Misc/GW, referer: http://gs/world/Arizona
[Sat Apr 05 15:01:07 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/2B/CSS/World/HomeW.css, referer: http://gs/world/Arizona
[Sat Apr 05 15:01:07 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/2B/inc/D/Shared/Body/Bottom/Footer, referer: http://gs/world/Arizona
[Sat Apr 05 15:01:14 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/GS/World/Arizona
[Sat Apr 05 15:01:30 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/2B/CSS/World/HomeW.css, referer: http://gs/world/NEW-YORK
[Sat Apr 05 15:01:30 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/2B/CSS/Misc/GW, referer: http://gs/world/NEW-YORK
[Sat Apr 05 15:01:30 2014] [error] [client 127.0.0.1] File does not exist: /Users/me/Sites/MySite/images/Maps/location/.png, referer: http://gs/world/NEW-YORK
[Sat Apr 05 15:01:52 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 15:01:52 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 15:01:59 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 15:01:59 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
I copy-pasted your htaccess, and I was able to reproduce the “exceeded internal redirects” issue, but only if I din’t define the RewriteMap in the server config. Can you double check that you have RewriteMap tolower int:tolower in the server config and that it’s working?
I verified that I pasted the code near the beginning the file:
<IfModule !mpm_netware.c>
PidFile logs/httpd.pid
</IfModule>
# Create a tolower mapping-function using the internal tolower
# Rewrite maps are not allowed in htaccess files, so this line must go in the server config
RewriteMap tolower int:tolower
However, I don’t know how to verify if it’s working. It’s in the same MAMP directory that includes the log file I’ve been looking at. The log file is obviously recording my activity, so I’m assuming this is the active server config file.
I found another server config file, which appears to be an invisible file located in my primary website. I don’t really understand why it’s there, but I pasted the code in there as well, just to be on the safe side:
Include "/usr/local/apache/conf/includes/post_virtualhost_global.conf"
Include "/usr/local/apache/conf/includes/post_virtualhost_2.conf"
RewriteMap tolower int:tolower
# DO NOT EDIT. AUTOMATICALLY GENERATED. IF YOU NEED TO MAKE A CHANGE PLEASE USE THE INCLUDE FILES.
There are also a few httpd.conf files with various extensions, like httpd.conf.easyapache_save and httpd.conf.bak.
I was playing around with Drupal and WordPress recently, so maybe these are related to those installations, though most seem to be located in my primary website. I’m not sure how those files got there or how to view them, other than finding and opening them with Apple’s finder.
P.S. I just deleted all the content on the other httpd.conf file, then restarted my servers. There was no change; I still get the Internal Server Error. I’m pretty sure this is just an extraneous file that’s completely removed from my websites.
Let’s do this. Add one more line into the server config:
LogLevel trace8
This will make the error.log extremely verbose. Apache will write out every step of everything it does.
When you come back to share the verbose logs, you’ll probably need to attach it rather than paste.
I decided to start with a blank slate, so I deleted the entire contents of the log, restarted my servers, then reloaded two web pages. I was able to post the entire content of the log below.
Apr 05 22:00:25 2014] [notice] Digest: generating secret for digest authentication …
[Sat Apr 05 22:00:25 2014] [notice] Digest: done
[Sat Apr 05 22:00:25 2014] [notice] Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8y DAV/2 PHP/5.3.6 configured – resuming normal operations
[Sat Apr 05 22:00:40 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 22:00:40 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 22:00:43 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 22:00:43 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
Can you do that again but with LogLevel trace8?
Hmmmm… I have the following code in my httpd.conf file:
# Create a tolower mapping-function using the internal tolower
# Rewrite maps are not allowed in htaccess files, so this line must go in the server config
RewriteMap tolower int:tolower
LogLevel trace8
I just repeated the process, deleting everything from my Apache log file, then restarting my servers and reloading both web pages. It looks my log has the same content as before:
[Sat Apr 05 23:00:57 2014] [notice] Digest: generating secret for digest authentication …
[Sat Apr 05 23:00:57 2014] [notice] Digest: done
[Sat Apr 05 23:00:57 2014] [notice] Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8y DAV/2 PHP/5.3.6 configured – resuming normal operations
[Sat Apr 05 23:01:04 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 23:01:04 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 23:01:09 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
[Sat Apr 05 23:01:09 2014] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.
Does this mean my log is doing what it’s supposed to but my httpd.conf file is somehow missing in action?
(Thanks for all the help; this has turned into a wild goose chase!)
That almost certainly means that whatever configuration file you’re editing isn’t one that’s being used by the server. The RewriteMap likely isn’t being processed, which would explain the “exceeds internal redirect” issue. And the LogLevel definitely isn’t being processed. If it were, you’d see things like this in the error.log
[Sat Apr 05 23:08:57.857356 2014] [rewrite:trace3] [pid 7332:tid 1012] mod_rewrite.c(475): [client ::1:51750] ::1 - - [localhost/sid#47ca58][rid#3ace0f0/initial] [perdir /Apache24/htdocs/] add path info postfix: /Apache24/htdocs/world -> /Apache24/htdocs/world/Arizona
[Sat Apr 05 23:08:57.857356 2014] [rewrite:trace3] [pid 7332:tid 1012] mod_rewrite.c(475): [client ::1:51750] ::1 - - [localhost/sid#47ca58][rid#3ace0f0/initial] [perdir /Apache24/htdocs/] strip per-dir prefix: /Apache24/htdocs/world/Arizona -> world/Arizona
[Sat Apr 05 23:08:57.857356 2014] [rewrite:trace3] [pid 7332:tid 1012] mod_rewrite.c(475): [client ::1:51750] ::1 - - [localhost/sid#47ca58][rid#3ace0f0/initial] [perdir /Apache24/htdocs/] applying pattern '^test\\\\.htm$' to uri 'world/Arizona'
[Sat Apr 05 23:08:57.857356 2014] [rewrite:trace3] [pid 7332:tid 1012] mod_rewrite.c(475): [client ::1:51750] ::1 - - [localhost/sid#47ca58][rid#3ace0f0/initial] [perdir /Apache24/htdocs/] add path info postfix: /Apache24/htdocs/world -> /Apache24/htdocs/world/Arizona
[Sat Apr 05 23:08:57.857356 2014] [rewrite:trace3] [pid 7332:tid 1012] mod_rewrite.c(475): [client ::1:51750] ::1 - - [localhost/sid#47ca58][rid#3ace0f0/initial] [perdir /Apache24/htdocs/] strip per-dir prefix: /Apache24/htdocs/world/Arizona -> world/Arizona
[Sat Apr 05 23:08:57.857356 2014] [rewrite:trace3] [pid 7332:tid 1012] mod_rewrite.c(475): [client ::1:51750] ::1 - - [localhost/sid#47ca58][rid#3ace0f0/initial] [perdir /Apache24/htdocs/] applying pattern '(.*)' to uri 'world/Arizona'
[Sat Apr 05 23:08:57.857356 2014] [rewrite:trace5] [pid 7332:tid 1012] mod_rewrite.c(475): [client ::1:51750] ::1 - - [localhost/sid#47ca58][rid#3ace0f0/initial] map lookup OK: map=tolower key=world/arizona -> val=world/arizona
[Sat Apr 05 23:08:57.857356 2014] [rewrite:trace2] [pid 7332:tid 1012] mod_rewrite.c(475): [client ::1:51750] ::1 - - [localhost/sid#47ca58][rid#3ace0f0/initial] [perdir C:/Apache24/htdocs/] rewrite 'world/Arizona' -> 'world/arizona'
Wow, it looks like I may have no choice but modify my .htaccess file. I’ve found six httpd.conf files on my computer. I added the following code to each of them and restarted my servers:
# Create a tolower mapping-function using the internal tolower
# Rewrite maps are not allowed in htaccess files, so this line must go in the server config
RewriteMap tolower int:tolower
LogLevel trace8
But my log always looks the same. Is it possible for an Apache server to write to two logs at the same time? Maybe I should look for another Apache log file…
On Edit: I can find just one apache_error.log on my computer. Also, if I rename Applications > MAMP > conf to Applications > MAMP > confX, I can’t restart my servers. When I change the name back to conf, they start like normal.
However, if I open the conf folder and rename httpd.conf, it has no effect on the servers. The only file that has an effect is one named mime.types. If I rename it, the servers won’t start.
Unfortunately I’ve never used MAMP, so I can’t help much here.