Forum Moderators: phranque
http://example.com/domainhacks/[/url] works
http://www.example.com/domainhacks/[/url] works (and forwards to above URL)
Now, remove the ending slash:
http://example.com/domainhacks[/url] works
http://www.example.com/domainhacks[/url] 404s!
Why? Here are the full .htaccess files, as I left everything in as experience has told me to never make assumptions:
"example.com" (root) dir:
(This rewrite is supposed to change "www.example.com" to "example.com" everywhere. I believe it works perfectly.)
ErrorDocument 400 http://example.com/error/400.html
ErrorDocument 401 http://example.com/error/401.html
ErrorDocument 403 http://example.com/error/403.html
ErrorDocument 404 http://example.com/error/404.html
ErrorDocument 500 http://example.com/error/500.html
Options +Includes
Options -Indexes
XBitHack On
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^example\.com [NC]
RewriteRule ^(.*) http://example.com/$1 [R=301] --- Again, I believe the above .htaccess to be perfect. I believe the problem is in the following .htaccess file below. I may be wrong. ---
"example.com/domainhacks" dir:
(This rewrite is supposed to change "www.example.com/domainhacks" to "example.com/domainhacks" everywhere. The reason the root .htaccess file listed above does not handle this, is because this .htaccess file overrides it simply by existing.)
RewriteEngine On
RewriteCond %{HTTP_HOST} !^example\.com [NC]
RewriteRule ^(.*)$ http://example.com/domainhacks/$1 [R=301]
RewriteRule ^search(.*)$ s.cgi$1 [NC]
RewriteRule ^suggestions(.*)$ suggest$1 [R=301] Any insight, what-so-ever, will be appreciated. I have gone over this lots of times. The bug eludes me.
[edited by: jdMorgan at 4:11 am (utc) on Feb. 27, 2006]
[edit reason] No URLs, please. See Terms of Service. [/edit]
It can be prevented by explicitly redirecting URL without trailing slash by RewriteRule before Apache does it (badly).
Here is an example of such redirect that covers boh http and https.
# Code for missing Trailing slashe problem
RewriteCond s%{HTTPS} ^((s)on¦s.*)$
RewriteRule ^/*(.+/)?([^.]*[^/])$ http%2://%{HTTP_HOST}/$1$2/ [L,R=301]
This code is efficient (because it doesn't perform -d check), but it doesn't work well if you use RewriteRules for 'SEO firendly URL', 'short URL'.
I didn't studied your code well, but noticed ErrorDocument directive with external redirects (with http://example.com/).
I don't recommend doingt it unless you know what you are doing and you really need to do that for some reason.
Web root .htaccess:
ErrorDocument 400 /error/400.html
ErrorDocument 401 /error/401.html
ErrorDocument 403 /error/403.html
ErrorDocument 404 /error/404.html
ErrorDocument 500 /error/500.html
Options +Includes -Indexes -MultiViews
XBitHack On
RewriteEngine on
RewriteCond %{HTTP_HOST} !^example\.com
RewriteRule (.*) http://example.com/$1 [R=301]--
"example.com/domainhacks" dir:
[code]
RewriteEngine on
RewriteOptions inherit
RewriteRule ^search(.*)$ /s.cgi$1 [NC]
RewriteRule ^suggestions(.*)$ http://www.example.com/domainhacks/suggest$1 [R=301]
Just to get the code straight, does your “code for missing trailing slashe problem” redirect from www.example.com/domainhacks --> www.example.com/domainhacks/ (adding a trailing slash without removing the www) whereas Apache would remove the www when it adds the trailing slash?
If Apache is removing the www when it redirects a request for a directory without a slash, www.example.com/domainhacks --> example.com/domainhacks/, what I don’t understand is why this 404s, because the latter works if I type it in directly to the browser.
I have tried inserting your “code for missing trailing slashe problem” above the RewriteCond and RewriteRule’s (in the domainhacks .htaccess directory, not the root), and it still reacts the same way.
I tried the "RewriteOptions inherit" and it forwards some requests for the domainhacks folder (example.com/domainhacks) back down to example.com. How can the "www --> non-www" redirect know that it is a subdirectory and only remove the www, not just blindly forward to "http://example.com"?
Thanks for the tips on ErrorDocument directives, I will look into this. I have taken your advice on combining the Options directives and turning off MultiViews.
Woah, but turning off MultiViews, the http://www.example.com/domainhacks requests (the one that 404'ed) still 404s, but this URL shows up in the address bar:
"http://example.com/domainhacks//home/example/public_html/domainhacks"
UPDATE: Check the error logs proves that they same request is made both WITH multiviews and WITHOUT multiviews. However, WITH multiviews, the URL shows up in the address bar. I should have posted my error log before, to share what was actually resulting with that www request without an ending slash that 404s.
It shows that the redirect is pulling the entire directory structure off my server and using it.
This may not help with the current problem, but you should include it anyway to avoid problems with HTTP/1.0 clients putting your serve into a loop.
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^example\.com
RewriteRule (.*) http://example.com/$1 [R=301]
Thanks for the replies again. I am going over them now...
I tried out your suggestion, but it did not solve my problem as you predicted. Can you elaborate on what this line (below) does, and how it breaks the infinite loop?
RewriteCond %{HTTP_HOST} .
From my understanding, "." (without quotes) is a wildcard that matches everything, but without ".*" (without quotes) it only matches one charcter. This confuses me on what the conditions the above line of code matches.
Is it a good idea to put rewrites of multiple subdirectories all in the same .htaccess root file instead of splitting them up as I have? The purpose being to have a better control and understanding of all the rewrites by having them all coded in the same spot.
For example, this is my structure, all of which require rewrites:
http://example.com/
http://example.com/domainhacks/
http://example.com/domainhacks/suggest
For the "domainhacks" and "suggest" directories, I could accomplish the rewrites in the root .htaccess with lines like this:
RewriteRule ^domainhacks/...
RewriteRule ^domainhacks/suggest/...
(Where "..." (without quotes) just stands for etcetera, and is not meant to be apart of the code.)
The "." will match any single character, but since it is un-anchored, it does not matter whether there are more characters after (or even before) it. Therefore, it will match any non-blank hostname in the request. By redirecting only if the hostname is non-blank and does not match the required hostname, you can redirect when needed, but not when the requested hostname is blank (and the redirect would be useless as well as causing a loop).
As to the centralized versus distributed rules approaches, there are two factors to consider: If you put all of the code in one place, it is easier to administrate. However, unless the rule order is optimized by placing the most-frequently-matched rules first, and using the [L] flag on them, then the number of rules that must be processed per HTTP request can go up dramatically using the centralized approach.
I prefer to keep most of my rules centralized, and only handle special cases on a per-subdirectory basis. This is because I believe that computers should work for man, and not the other way around, and because my sites are not too 'busy' to make that approach untenable. I'm sure if I were faced with a costly server hardware upgrade due to a traffic overload, I might be convinced to move some of my rules into subdirectories... :)
There are many server configuration factors that, when combined, can give 'odd' server behaviour like yours. I'm sorry that I haven't been able to figure out what's wrong, but I'm pretty sure that if your site were hosted on my server, it would work as expected. There's just a setting somewhere that isn't quite right, I suspect.
Jim
[doriat.com...]
This was the fix Richard suggested, which works:
----------------------------
Try this line:
Code:
RewriteRule .* [xona.com%{REQUEST_URI}...] [R=301,L]
instead of this line
Code:
RewriteRule ^(.*)$ [xona.com...] [R=301]
----------------------------
Please comment on it if you wish. I would like to learn more. It appears that his fix works in all sub-folders, so I could put this in the root .htaccess and inherit it to the sub-folders.