Forum Moderators: phranque

Message Too Old, No Replies

redirect internal rewrite root to subdir with exception

redirect internal rewrite root to subdir with exception

         

babushka

8:38 pm on Feb 17, 2010 (gmt 0)

10+ Year Member



I use the code below in my .htaccess. It does some home page redirects and then it does an internal rewrite of the root directory to the subdirectory with the current website. This works great, however, I need to exclude some subdirs from the internal rewrite.

For example, if I have this:

public_html
subdirA
subdirB
subdirC

and I do the rewrite as below, all requests get internally rewritten to subdirA. I would like to exclude requests to subdirB and subdirC from being internally rewritten to subdirA. How would I do that?

tia


AddHandler server-parsed .htm .html
#
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.(php|html)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^subdirA(/(.*))?$ http://example.com/$2 [R=301,L]
#
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
#
RewriteRule !^subdirA(/.*)?$ /subdirA%{REQUEST_URI} [QSA,L]
#
ErrorDocument 404 /missing.html

[edited by: jdMorgan at 4:03 am (utc) on Feb 18, 2010]
[edit reason] example.com [/edit]

babushka

9:14 pm on Feb 17, 2010 (gmt 0)

10+ Year Member



To be more clear. I want to redirect all requests to public_html to sudirA EXCEPT requests to subdirB or subdirC.

babushka

11:08 pm on Feb 17, 2010 (gmt 0)

10+ Year Member



I think I still said this wrong.

I want to "rewrite" all requests to subdirA except requests to subdirB.

I have added this line to the code below:
RewriteCond %{REQUEST_URI} !^/subdirB/

subdirB happens to be a subdomain. When I add this line, the url now stays at subdirB.mydomain.com. However, file is not found. Error log shows it is being rewritten as public_html/subdirA/subdirB

So I need to also change the last rewrite rule I think but not sure how to add an exception in there. I wish there was a "rewrite" for dummies book.


#
RewriteCond %{REQUEST_URI} !^/subdirB/
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

[edited by: jdMorgan at 4:04 am (utc) on Feb 18, 2010]
[edit reason] example.com [/edit]

babushka

11:12 pm on Feb 17, 2010 (gmt 0)

10+ Year Member



Ok, so I added the same line right above the last rewrite and all appears to work

babushka

11:18 pm on Feb 17, 2010 (gmt 0)

10+ Year Member



Ok I spoke too soon.

Now it redirects subdirB.example.com to example.com/subdirB
I don't want it to do that. I would rather it stay subdirB.example.com

Also, I now want to do similar redirects for the subdomain as I do for the main domain.

I want to redirect subdirB.example.com/index.php or html to subdirB.example.com

And I want to do an internal rewrite so that

subdirB.example.com/subsubdir

redirects to:

subdirB.example.com

Hope that makes sense.

[edited by: jdMorgan at 4:05 am (utc) on Feb 18, 2010]
[edit reason] example.com [/edit]

jdMorgan

12:16 am on Feb 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Exclude subdirB.example.com from your third rule.
Exclude /subdirb from the last rule.
Copy the last rule, and exclude subdirA and subdirC from this new copy.

You also need to look at your other rules, and add exclusions and/or duplicate them for your all of your subdomains.

Also, you will be much happier if you put all subdomain/subdirs into one "master" subdirectory, such as
/subs/subdirA
/subs/subdirB
/subs/subdirC

In this way, only the "/subs/" part of the URL-path needs to be checked to prevent recursion, and you won't have to exclude each and every subdomain/subdirectory from each and all of the other subdomain/subdirectory's rules explicitly. This method simply 'scales' better, and allows you to 'share' many of the rules among all subdomain/subdirectories simply by back-refrencing the subdomain from the HTTP_HOST variable.

Jim

babushka

12:50 am on Feb 18, 2010 (gmt 0)

10+ Year Member



Thank you for your response.

I'm still not doing it right. Copying the last rule gives me an internal 500 error.

AddHandler server-parsed .htm .html
#
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.(php|html)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^subdirA(/(.*))?$ http://example.com/$2 [R=301,L]
#
RewriteCond %{REQUEST_URI} !^subdirB.example\.com$
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{REQUEST_URI} !^/subdirB
RewriteRule !^subdirA(/.*)?$ /subdirA%{REQUEST_URI} [QSA,L]
RewriteRule !^subdirB(/.*)?$ /subdirA%{REQUEST_URI} [QSA,L]
#
ErrorDocument 404 /missing.html

[edited by: jdMorgan at 4:06 am (utc) on Feb 18, 2010]
[edit reason] example.com [/edit]

jdMorgan

1:32 am on Feb 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You are missing a RewriteCond.

> Copy the last rule, and exclude subdirA and subdirC from this new copy.

Jim

babushka

1:54 am on Feb 18, 2010 (gmt 0)

10+ Year Member



oh ok. Ignoring subdirC for the moment and just trying to get one subdomain to work. I think I don't need two subdomains.

When I use the code below, the following happens:

http://subdirB.example.com

gets visibly redirected to:

http://example.com/subdirB

I would like the vistor to see:
http://subdirB.example.com

Also, when I type the following into the address bar of the browser:

http://subdirB.example.com/subsubdir
or
http://example.com/subdirB/subsubdir

I get a 500 error

AddHandler server-parsed .htm .html
#
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.(php|html)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^subdirA(/(.*))?$ http://example.com/$2 [R=301,L]
#
RewriteCond %{REQUEST_URI} !^subdirB.example\.com$
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{REQUEST_URI} !^/subdirB
RewriteRule !^subdirA(/.*)?$ /subdirA%{REQUEST_URI} [QSA,L]
#
ErrorDocument 404 /missing.html

[edited by: jdMorgan at 4:08 am (utc) on Feb 18, 2010]
[edit reason] example.com [/edit]

jdMorgan

3:03 am on Feb 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member




# Redirect requests for "index.php", "index.html",
# or "index.htm" to canonical "/" URL-path
#
RewriteCond %{HTTP_HOST} ^((www|subdirA|subdirB)\.)?example\.com
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.(php|html?)$ http://%1example.com/$1 [R=301,L]
#
# Redirect to canonical hostnames (to correct added "www.",
# casing errors, FQDN requests, and appended port numbers)
#
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{HTTP_HOST} !^example\.com$
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{HTTP_HOST} ^(www\.)?subdirA\.example\.com [NC]
RewriteCond %{HTTP_HOST} !^subdirA\.example\.com$
RewriteRule ^(.*)$ http://subdirA.example.com/$1 [R=301,L]
#
RewriteCond %{HTTP_HOST} ^(www\.)?subdirB\.example\.com [NC]
RewriteCond %{HTTP_HOST} !^subdirB\.example\.com$
RewriteRule ^(.*)$ http://subdirB.example.com/$1 [R=301,L]
#
# Rewrite subdomain requests to subdomains' subdirectories
#
RewriteCond %{HTTP_HOST} ^subdirA\.example\.com$
RewriteCond $1 !^subdirA/
RewriteRule ^(.*)$ /subdirA/$1 [L]
#
RewriteCond %{HTTP_HOST} ^subdirB\.example\.com$
RewriteCond $1 !^subdirB/
RewriteRule ^(.*)$ /subdirB/$1 [L]

Please review the documentation cited in our Apache Forum Charter if any of this is unclear. Frankly, I feel I have done you no favors by posting this unless you understand every single character of it -- and everything that it does, and why, as well.

Jim

babushka

3:23 pm on Feb 18, 2010 (gmt 0)

10+ Year Member



I messed up explaining my problem. I have modified the code and am close, just one small problem.

What I have is this directory structure:

public_html
subDirA (This is where the website for example.com resides and is internally rewritten to public_html. The user never sees subDirA.

subDirB (This is actually the new subdomain. Internally it looks like a subdirectory under public_html. In the code below, the subdomain displays as subDirB.example.com which is what I want and it no longer is being rewritten to subDirA. So this is working the way I want now.)

subsubdir (This is a subdirectory under subDirB.example.com. This needs to be internally rewritten back to subDirB.example.com . This is the problem. I can not make this happen. It is still being displayed as subDirB.example.com/subsubDir instead of subDirB.example.com.


Here is the latest code where everything works right except the internal rewrite of subsubdir back to [subDirB.example.com...]



AddHandler server-parsed .htm .html
#
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
#
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.(php|html?)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{HTTP_HOST} ^subDirB\.example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.(php|html?)$ http://subDirB.example.com/$1 [R=301,L]
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^subDirA(/(.*))?$ http://example.com/$2 [R=301,L]
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} ^subDirB\.example\.com [NC]
RewriteRule ^subsubDir(/(.*))?$ http://subDirB.example.com/$1 [R=301,L]
#
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{HTTP_HOST} !^subDirB\.example\.com$ [NC]
RewriteRule !^subDirA(/.*)?$ /subDirA%{REQUEST_URI} [QSA,L]
#
RewriteCond %{HTTP_HOST} ^subDirB\.example\.com$ [NC]
RewriteRule !^subsubDir(/.*)?$ /subsubDir%{REQUEST_URI} [QSA,L]
#
#
ErrorDocument 404 /missing.html

[edited by: babushka at 4:09 pm (utc) on Feb 18, 2010]

babushka

3:25 pm on Feb 18, 2010 (gmt 0)

10+ Year Member



It is still creating links using example.com

I'm sorry, I do not see how to post the above without it creating links.

babushka

4:11 pm on Feb 18, 2010 (gmt 0)

10+ Year Member



RewriteCond %{ENV:REDIRECT_STATUS} ^$
This does the internal rewrite of subDirA just fine:

RewriteRule ^subDirA(/(.*))?$ http://example.com/$2 [R=301,L]

I don't understand why this does not internally rewrite subsubDir back to the subDirB example.com

#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} ^subDirB\.example\.com [NC]
RewriteRule ^subsubDir(/(.*))?$ http:// subDirB .example.com/$1 [R=301,L]

NOTE: I put spaces in the url so it doesn't link

g1smd

4:22 pm on Feb 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This does the internal rewrite of subDirA just fine:


It cannot possibly do that. The R=301 makes it an external 301 redirect.

babushka

4:37 pm on Feb 18, 2010 (gmt 0)

10+ Year Member



Sorry, that does the redirect of the subdir. back to the root for the domain. But the redirect of the subdirectory of the subdomain back to the root of the subdomain results in 500 error in IE8 and no change in Firefox. In other words, the redirect is not happening in Firefox.

So instead of seeing subDirb .example.com/subsubdir, the user should see subDirb .example.com (note spaces added so it doesn't link)

The redirect works fine for the main domain, but not for the subdomain.

jdMorgan

5:21 pm on Feb 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Two possibilities -- simple one first...

Are you deleting your browser cache before testing each new version of this code? If you don't, your browser will show you old cached pages and server responses.

It's possible that REDIRECT_STATUS is undefined on your server. If so, an alternate method to prevent looping due to redirect/rewrite interaction is to check the original client request line -- exactly as it appears in your raw server access log:

RewriteCond %{HTTP_HOST} ^subDirB\.example\.com [NC]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /subsubDir(/[^\ ]*)?\ HTTP/
RewriteRule ^subsubDir(/(.*))?$ http://subDirB.example.com/$1 [R=301,L]

In this way, only direct client requests for the "subsubdir" are redirected. Internal requests due to the action of your internal rewrite rule will not be redirected. The function is identical to checking REDIRECT_STATUS, but based on a different variable.

Yes, the RewriteCond and the RewriteRule pattern are somewhat redundant. That's OK.

Jim

babushka

6:17 pm on Feb 18, 2010 (gmt 0)

10+ Year Member



Thank you. I have cleared the cache and IE8 is now same as firefox, no redirect.

Shows as:
subdirB .example.com/subsubdir

No errors, no redirect. The additional RewriteCond did not do anything either.

I tried taking out the other RewriteCond, and still has no effect.

Because internally, subdomains are a subdirectory under public_html ( /home/example/public_html/subdirB), I tried:

RewriteRule ^subdirB/subsubdir(/(.*))?$ [subdirB...] .example.com$1 [R=301,L]

Now the redirect is happening. I took out the conditions as they did not seem to be needed.

However, the "rewrite" is not happening. It gives me a 500 internal error when I use the first RewriteCond and no error when I use the second - it just doesn't do the rewrite.

I tried both of these conditions separately:

#RewriteCond %{HTTP_HOST} ^subdirB\.example\.com$ [NC]
RewriteCond %{HTTP_HOST} ^/subdirB/$ [NC]
RewriteRule !^subsubdir(/.*)?$ /subsubdir%{REQUEST_URI} [QSA,L]

But no rewrite.

Ok I see I am using HTTP_HOST for the second one which ofc won't work. REQUEST_URI doesn't work and I tried no conditions which results in a 500 error. Nothing is written to the error log though.

Solved!

I added subdirB/ to the rewrite rule (no conditions):

RewriteRule !^subdirB/subsubdir(/.*)?$ /subsubdir%{REQUEST_URI} [QSA,L]

Thanks for the help!

Do you think I should put conditions in for any reason?

babushka

7:12 pm on Feb 18, 2010 (gmt 0)

10+ Year Member



Ok I was wrong, it doesn't solve it. Well it does to a degree but then I have two other problems.

1) example.com now gives a 500 error
2) subDirB .example.com/newsubsubdir/index.php gets redirected to subDirB .example.com/subDirB/newsubsubdir

sigh

babushka

3:43 pm on Feb 19, 2010 (gmt 0)

10+ Year Member



I'm actually starting to understand this stuff. I have it all working. Final code below.



AddHandler server-parsed .htm .html
#
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
#
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.(php|html?)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{HTTP_HOST} ^subdirB\.example\.com [NC]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^subdirB/index\.(php|html?)$ http://subdirB.example.com/$1 [R=301,L]
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^subdirA(/(.*))?$ http://example.com/$2 [R=301,L]
#
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^subdirB/subsubdir(/(.*))?$ http://subdirB.example.com$1 [R=301,L]
#
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
#
RewriteCond %{HTTP_HOST} !^subdirB\.example\.com$ [NC]
RewriteRule !^subdirA(/.*)?$ /subdirA%{REQUEST_URI} [QSA,L]
#
RewriteCond %{HTTP_HOST} !^(www\.)?example\.com$ [NC]
RewriteRule !^subdirB/subsubdir(/.*)?$ /subsubdir%{REQUEST_URI} [QSA,L]
#
#
ErrorDocument 404 /missing.html
#
#


jdMorgan

4:33 pm on Feb 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



In your domain canonicalization rule, do not use the [NC] flag on the second RewriteCond. Doing so defeats one of the purposes of this rule -- To make sure that the requested hostname is *exactly* the right one.

RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
[i]RewriteCond %{HTTP_HOST} !^example\.com$[/i]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

You should not need to use the [QSA] flag on any rule that does not (or is not intended to) *append* new query string parameters to the existing ones in the request. The default behavior of RewriteRule is to pass-through query strings unchanged. Adding [QSA] to a rule where it's not needed wastes CPU time.

While this is a minor inefficiency, the problem with inefficiencies is that they tend to accumulate, resulting in a slow site and an early and unnecessary server upgrade.

Jim