Forum Moderators: phranque

Message Too Old, No Replies

How to rewrite subfolder to subdomain?

         

Lomacar

2:20 am on Feb 9, 2012 (gmt 0)

10+ Year Member



I have tried all sorts of things but keep getting goofy behaviour. How can I simply rewrite all pages in a sub folder like

example.com/sub

to

sub.example.com


I only have a have a handful of pages affected so it would be ok if I have to explicitly state the page as well. I would think something like this would work but it give me a redirect loop:

RewriteRule ^sub\/(.*)$ "http://sub.example.com$1" [R=301,L]

Other things I try just give me mangled URLs or do nothing.

Lomacar

2:24 am on Feb 9, 2012 (gmt 0)

10+ Year Member



I'm weird. This isn't actually the problem I wanted a solution to. But I think the reason I get the loop is because the website is already set up to access that folder when using the subdomain. It would be nice to block access to the subfolder URL since the webpage doesn't display correctly from there.

lucy24

9:35 am on Feb 9, 2012 (gmt 0)

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



By "access that folder" do you mean rewrite or redirect? You may simply need to add a RewriteCond looking at THE_REQUEST.

I'm surprised your rule as posted gives you anything other than a browser error. For starters, you don't need to escape slashes in mod_rewrite. Apparently it doesn't mind too much, though, if it still executes the Rewrite. But what you've got is

Request
www.example.com/sub/blahblah.html

gets redirected to
sub.example.comblahblah.html

?!

g1smd

10:08 am on Feb 9, 2012 (gmt 0)

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



Which one is the URL that you want users to use to access the site?

You see, most people describe rewrites "exactly backwards" which leads to confusion.

Please form the question like this (there are two parts):

When user requests URL like "this" (a URL including hostname and path), that incoming request should be rewritten (or is already being rewritten from the clues in your original question) so that the server fetches content from "here" (a server internal path name without hostname) without revealing the true location.

When user requests URL like "this" (a URL including hostname and path) the user will be redirected to the new URL like "this" (a URL including hostname and path) as I don't want them to be able to access the old or native URL for the content. (I think this is the problem you are trying to solve?)

If lucy's guess is correct (post right before this one) as to what you want to do you will need to add a RewriteCond that tests THE_REQUEST to make sure that the internal request for /sub/ as a folder was also present in the original URL request made by the browser and is not as a result of a previous internal rewrite from a subdomain URL request.

Lomacar

1:11 am on Feb 10, 2012 (gmt 0)

10+ Year Member



Sorry, I was experimenting with escaping, it didn't seem to make a difference in the end. Even when I did have a slash in replacement string it tended to ignore it for some reason.

I think you know what I want, but what exactly do I do with THE_REQUEST then?

I have set up sub domains via cPanel so that when users type in sub.domain.com it serves them content from a folder on the server: public_html/sub/.

That's great. What I want to do is have it so that if a user tries to access domain.com/sub/page.html, the URL is rewritten/redirected to sub.domain.com/page.html. But apparently I am using the same mechanics to change the URL as the subdomain dealy is using to map the subdomain request back to the subfolder on the server, resulting in a loop.

The reason I need this is because I have absolute-relative URLs like "/images/logo.png", which I want to be relative to each subdomain.

So what is the terminology? Are you saying that rewrites are the invisible remapping and redirects are the URL-changing? Because that does seem backwards to me.

g1smd

1:30 am on Feb 10, 2012 (gmt 0)

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



the URL is rewritten/redirected to

Be very sure which one you want. Although both can be coded using a RewriteRule, a redirect and a rewrite are each very different things.

Are you saying that rewrites are the invisible remapping and redirects are the URL-changing?

A redirect returns a response telling the user to ask for a different URL in a new HTTP transaction.
A rewrite alters the default internal filehandler pointer to instead fetch content from a different place on the server hard drive.

You'll need a RewriteRule for your redirect and you'll also need a RewriteCond testing THE_REQUEST to be sure that the folder in the pointer came from the users original request and not as a result of a previous internal rewrite.

There's a thread with similar code within the last 48 hours right here in this forum.

lucy24

4:32 am on Feb 10, 2012 (gmt 0)

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



Are you saying that rewrites are the invisible remapping and redirects are the URL-changing? Because that does seem backwards to me.

In case the preceding answer was too complicated: Yes, that's what he is telling you ;)

If it helps, think of the redirect in physical terms. You're taking the user by the shoulders, turning them around in a different direction and telling them to go around the back.

"User" of course means "user agent". It's the browser that does the fresh asking. The human sitting in front of the browser has no idea what's going on-- unless they look at their browser's address bar and notice that it now says something different.

Lomacar

6:13 pm on Feb 10, 2012 (gmt 0)

10+ Year Member



Well it would be nice to know what the solution to this problem is. I don't know what that post was in the last 48 hours that purportedly has some similar code that might help me. I also can't find any straightforward explanation online of how to use THE_REQUEST in a situation like this. I believe every forum thread deserves an explicit solution to the question.

g1smd

8:49 pm on Feb 10, 2012 (gmt 0)

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



The problem is, the solution is already here in this forum in excesss of 2000 times and maybe as many as 10 000 times. I often answer almost the exact same question only hours after the previous incantation.

Lomacar

9:14 pm on Feb 10, 2012 (gmt 0)

10+ Year Member



Well then there should be a sticky thread with the solution. I can't find these solutions using the search or by manually visiting threads that seem like they might be helpful.

I think I understand that I need something like:

RewriteCond %{THE_REQUEST} ...

But I don't know what I'm actually accomplishing with this. How does Apache tell the difference between a direct request and a rewritten request?

Lomacar

9:32 pm on Feb 10, 2012 (gmt 0)

10+ Year Member



OK, with some experimentation I solved it. You don't need to use THE_REQUEST. I already had something similar in my .htaccess. The full file was like this:


RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^index\.php$ "http://www\.example\.com/index\.html" [R=301,L]

RewriteRule ^sub/(.*).html$ "http://sub.example.com/$1.html" [R=301,L]


I thought that should already be preventing loops. What I didn't realize was that as soon as you declare a rule it resets the RewriteCond's. So all I had to do was reverse the order of those rules:


RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.example.com$

RewriteRule ^sub/(.*).html$ "http://sub.example.com/$1.html" [R=301,L]

RewriteRule ^index\.php$ "http://www\.example\.com/index\.html" [R=301,L]


Sorry, I guess I should have posted my full code in the first place.

Lomacar

9:37 pm on Feb 10, 2012 (gmt 0)

10+ Year Member



What I still don't understand is why I actually need the RewriteCond, because I specifically say in my rule that the URL needs to have a slash after "sub" so how would it match "sub.example.com" ?

lucy24

9:57 pm on Feb 10, 2012 (gmt 0)

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



How does Apache tell the difference between a direct request and a rewritten request?

Would you be content with an assurance that yes, it can tell?

In human terms again: THE_REQUEST is what you see in your logs. If the request leads to a redirect (301 or 302) you will see two consecutive requests in your logs. But if it leads to a rewrite, the logs are silent. Your only hint is if you study the logs closely; then you might notice that the filesize (the number after the 200) is different from the size of the "real" file. The "real" file may not even exist.

Also: search-engine robots can "see" a Redirect and can choose not to follow it. But they are powerless against a Rewrite.

What I didn't realize was that as soon as you declare a rule it resets the RewriteCond's.

That's an important thing to remember, and it's one reason people tell you to leave a blank space after each Rule. Any given Condition or group of Conditions applies only to the immediately following Rule.

I've got a nasty feeling that either you've got your code backward or everyone has been reading your original question backward. I thought what you wanted to do was:

If the user requests
sub.example.com/blahblah

serve content from
www.example.com/sub/blahblah {rewrite with L flag only}

So far so good. Only then, to avoid duplicate content, you have to deal with the users who type in the "sub/" version on purpose:

www.example.com/sub/blahblah
has to get redirected [R=301,L] to
sub.example.com/blahblah

so that everyone's address bar shows the same thing. This is the rule that requires a THE_REQUEST condition to keep from going into an infinite loop. You are only redirecting people who actually asked for this form. You are not doing anything to Apache's internal request for this identical form.

Finally: index.html should never appear in a Redirect target. The official name of a directory ends in / slash. For a Rewrite target you do have to include the index.html (or .php or whatever you've got), because that's where the content lives. And speaking of slashes: you don't need to escape \. full stops-- or anything else-- in the target (the part on the right in the Rule). Only in the Pattern.

Lomacar

7:22 pm on Feb 11, 2012 (gmt 0)

10+ Year Member



Well it works now, so whatever. When I asked

How does Apache tell the difference between a direct request and a rewritten request?


I meant what instructions do you give Apache to tell it to apply the rule only if the URL was requested by the user as opposed to being an internal rewrite? It seems I have achieved it somehow. I guess part of the confusion is that I don't know what the other half of this system looks like. That part that rewrites from sub.domain.com to domain.com/sub. I just used cPanel to set it up, I don't know where the code is that handles it.

lucy24

10:23 pm on Feb 11, 2012 (gmt 0)

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



I meant what instructions do you give Apache to tell it to apply the rule only if the URL was requested by the user as opposed to being an internal rewrite?


RewriteCond %{THE_REQUEST} blahblah

That's what THE_REQUEST means.