Forum Moderators: phranque
I have some non-www to www code in the root htaccess of a domain. I have now added a directory at www.example.com/dir/ which has its own .htaccess to load the index for the dir from another location.
The problem is, when visitng http://example.com/dir/, the url is rewritten to include the www AND the real location of the index eg www.example.com/dir.php
Here is my code in the dir:
RewriteEngine On
RewriteBase /dir/
RewriteRule ^$ /dir.php
any suggestions?
[edited by: Inspired at 11:59 am (utc) on July 25, 2007]
If you rewrite to dir.php first, then the redirect will "expose" the internal redirect, which is what you report happening here.
Make sure that you use mod_rewrite for both functions; Do not use mod_access for the redirect and mod_rewrite for the internal rewrite. If you do that, you cannot control the order in which they will execute, and this kind of problem can occur.
Jim
RewriteEngine On
RewriteBase /dir/
RewriteCond %{HTTP_HOST} ^example.(.*)
RewriteRule ^(.*)$ http://www.example.com/dir/$1 [R=301,L]
RewriteRule ^$ /dir.php
works great, except when the trailing slash isnt included (eg www.example.com/dir) which ends up revealing the servers local path to the file within the URL.
any other suggestions?
In the present case, it is mod_dir that is invoking a redirect to add the missing trailing slash, again exposing your previously-executed internal rewrite.
You can try moving all this code to root /.htaccess, or add a redirect rule *above* the www-non-www redirect to add the trailing slash if it's missing.
Two ways to do that: If your site URLs are well-organized, only filenames contain periods, and all filenames contain periods, then if a URL-path has no period and does not end with a slash, add one.
If on the other hand, you have some filenames without periods, or some of your directory URL-paths contain periods, then you'll have to use a RewriteCond "directory exists" check to see if the URL-path refers to a directory, and if so, add a trailing slash if missing. Unfortunately, this requires a call to the file manager, and so is very slow compared to the first method.
Jim
For example, when adding PHP, many times they just figure, "Well, I'll add it at the end -- That should be safe." Then they wonder why mod_auth (authorization/authentication), mod_rewrite, and all the others don't seem to work for PHP files... It's because PHP executes first, and goes straight to the content-delivery API phase, by-passing execution of all the other modules.
On Apache 2.x, module execution order is controlled by an internal priority scheme, and can't be changed unless you modify the Apache source and re-compile it.
To be very clear about all of the above: Each Apache module parses your .htaccess file(s) in turn, looking for directives that it understands and handles. So directives handled by any one specific module are executed in the order they appear in your .htaccess file. But you cannot control the order in which different module's directives execute by specifying their order in .htaccess -- The module execution order determines that.
So, for example, it makes no difference if you place all mod_alias directives first in your .htaccess file, followed by all mod_rewrite directives, or intersperse or reverse these directive groups instead; The server will execute all of one or the other module's directives first, as determined by the reverse LoadModule list order on Apache 1.x, or by the internal priority scheme on Apache 2.x
Jim
after ruling out the apache fix, I tried adding the trailing slash within the subdir htaccess, which ends up redirecting to http://www.example.com//home/user/example.com/public_html/dir/
at this point im not really sure what to do, this is a rather comlex solution for a seemingly simple issue.
RewriteBase /home/user/example.com/public_html
Jim
RewriteEngine On
# trailing slash
RewriteCond %{REQUEST_URI}!(.*)/$
RewriteRule ^(.*)$ http://www.example.com$1/ [L,R=301]
# non-www
RewriteCond %{HTTP_HOST} ^example.(.*)
RewriteRule ^(.*)$ [example...] [R=301,L]
RewriteRule ^$ /dir.php
I didnt add a check for periods in the filename yet, but i guess that shouldnt stop it from working
# trailing slash
# If URL-path does not contain a period or end with a slash
RewriteCond %{REQUEST_URI} !(\.¦/$)
# add a trailing slash
RewriteRule (.*) http://www.example.com/$1/ [R=301,L]
#
# Redirect non-www domain requests to www domain
RewriteCond %{HTTP_HOST} ^example\.
RewriteRule (.*) http://www.example.com/dir/$1 [R=301,L]
#
# Internally rewrite requests for index page to dir.php
RewriteRule ^$ dir.php [L]
Step #2 would be to add "RewriteOptions none" at the top. This will prevent your root .htaccess file from affecting this subdirectory (by disabling "RewriteOptions inherit"). Even if it has other negative side effects, finding out whether this helps with the server filepath exposure problem might be worthwhile.
Also, please be verbose about how you are testing, what specific results you get, and how those differ from what you expected. I can't look over your shoulder here and see what you're doing or seeing. I'm basically trying to watch the football match through a tiny hole in the side-wall of the stadium...
Jim
[edited by: jdMorgan at 7:14 pm (utc) on July 25, 2007]
I just tried your version, but this again resulted in the full server filepath being exposed with the double slash issue. I resolved the double slash issue by changing the first rewriterule (removed the slash after the tld) to:
RewriteRule (.*) http://www.example.com$1/ [R=301,L]
This still caused the filepath to be exposed when there was no trailing slash, although it works fine when there is no www but the last slash is included.
Adding "RewriteOptions none" at the top causes all requests to return a 500 Internal server error so some reason.
Not sure if this is related, but the root htaccess is rather bulky, around 600 lines or so of rewrites and redirects.
See: [webmasterworld.com...] and [webmasterworld.com...] for more.
I thought that the solution was getting a little too complicated for such a seemingly trivial issue, so I started over again trying to simplify things.
The solution to not revealing the internal rewritten URL was to use {REQUEST_URI} instead of the regex backtrace $1 which was being replaced with the internal path.
I placed the following code in the subdir htaccess:
RewriteEngine On
# Redirect non-www domain requests to www domain
RewriteCond %{HTTP_HOST} ^example\.
RewriteRule (.*) http://www.example.com%{REQUEST_URI} [R=301,L]
This takes care of the 301 for non-www or no trailing slash, or both. No other code was needed in the subdir or the root htaccess.
Thanks for your help everyone!
Edit:
I forgot to mention that downside to this solution is a double redirect in case of a non-www request thats also missing the trailing slash.
[edited by: Inspired at 3:48 pm (utc) on July 26, 2007]
# trailing slash
# If URL-path does not contain a period or end with a slash
RewriteCond %{REQUEST_URI} !(\.¦/$)
# add a trailing slash
RewriteRule .* http://www.example.com%{REQUEST_URI}/ [R=301,L]
#
# Canonicalize the domain
# Redirect non-www domain requests to www domain
RewriteCond %{HTTP_HOST} ^example\.
RewriteRule .* http://www.example.com%{REQUEST_URI} [R=301,L]
Jim
[edited by: jdMorgan at 5:56 pm (utc) on July 26, 2007]
I wanted to avoid having multiple redirects as g1smd mentioned, but I just noticed that apache does a double redirect for an actual subdir containing a static index.html with a "http://example.com/dir" request. That dir doesnt have a htaccess of its own, the first redir is the canonicalization code in the root htaccess followed by another apache redir adding the trailing slash... but thats probably fodder for another discussion.
Once again, thanks to everyone for their help.
Change all broken pipe "¦" characters in the code above to solid pipes before use; Posting on this forum modifies the pipe characters.
If that doesn't help, then adding an .htaccess file to the subdir with "RewriteOptions inherit" in it may help.
Jim