Forum Moderators: phranque

Message Too Old, No Replies

Rewrite one domain to our internal subdomain?

(Without changing the URL's original domain)

         

sublime1

7:39 pm on Apr 22, 2010 (gmt 0)

10+ Year Member



Is there a way to accept a request on one domain and internally rewrite it to a subdomain (without the URL in the browser changing)?

My problem:

We're hosting websites for customers on a subdomain of our main domain, e.g.

examplecustomer.example.com

but other customers have their own domain, e.g.

examplecustomer2.com

Naturally, they want everything to appear on their domain, and also naturally, we would prefer not to do any additional work to support this :-)

Our system is set up to recognize the subdomain on the request and route it correctly. Is there a way to change the domain on a request using apache rewriting or other methods?

I am quite certain that my 15th year of doing Apache rewriting will be the one where I finally figure it out :-)

Thanks --

Tom

g1smd

7:46 pm on Apr 22, 2010 (gmt 0)

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



Yes, there's plenty of ways to do that. It's one of the most popular questions here.

Have you checked any of the prior example threads? Let's see your best effort code.

sublime1

7:55 pm on Apr 22, 2010 (gmt 0)

10+ Year Member



Thanks -- yes, I looked and looked, and looked. And then looked. But nothing worked.

But that's simply because I was being an idiot (I should have known, that's always what it is with us idiots).

I forgot to set the proper servername (serveralias would have worked, too).

In the end, the rewrite was simple (here our domain is example.com):


# rewrite to our internal URL, not a redirect
RewriteCond ${HTTP_HOST} (www\.)?examplecustomer2\.com
RewriteRule ^/(.*)$ http://examplecustomer2.example.com/$1


I'll try to stop being an idiot (but nothing I have tried so far has worked :-)

Thanks.

Tom

[edited by: jdMorgan at 12:39 am (utc) on Apr 23, 2010]
[edit reason] de-linked hostname in code. [/edit]

g1smd

8:40 pm on Apr 22, 2010 (gmt 0)

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



RewriteRule pattern matching cannot see the leading slash of the incoming URL request. Your pattern will never match.

By including a domain name in the target you have coded a redirect. Specifically its a 302 redirect. A rewrite should map to an internal server filepath.

Always add the [L] flag to each rule.

sublime1

4:38 pm on Apr 23, 2010 (gmt 0)

10+ Year Member



g1smd --

Thanks for your reply. I thought I had actually resolved the problem, but I had not. Your response pointed out the flaws with my approach (which helped), but was not a solution to my problem.

I believe I have resolved the case I initially presented. If you (or anyone) sees a problem, please let me know.

My problem was that I needed to invisibly route requests coming in on one domain to another domain (both managed by our server), without any HTTP redirect (301, 302 or otherwise).

To accomplish this, I created a reverse proxy in the virtual host, as follows:


ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>

RewriteCond %{HTTP_HOST} examplecustomer.com
RewriteRule ^/(.*)$ httq://examplecustomer.com/$1 [P]


(note: httq used to suppress auto URL creation)

So: when the domain is examplecustomer.com apache does a reverse proxy passthrough, effectively changing the domain internally.

I needed to enable mod_proxy and mod_proxy_http for everything to work.

As an aside, you mentioned in your response that the pattern ^/(.*)$ would never match, as the path does not contain the leading /, but I think this is incorrect - I am able to see in the rewrite logs that it does match.

You are correct that I had left out the [L] flag. In this solution, the [P] (ProxyPass) flag accomplishes the same thing.

So I think this works. It seems to in various testing I have been able to do.

Thanks very much!

Tom

jdMorgan

7:21 pm on Apr 23, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If both 'sites' are in the same DocumentRoot path, consider using an internal rewrite, rather than the (already-rejected) redirect option or a proxy throughput.

This avoids some of the downsides of using a proxy:

1) All requests pass through the 'front-end' server, and will (normally) be logged. This skews your front-end stats and makes them less-useful (or useless) for marketing analysis.
2) Requests passing through the front-end consume server resources -- usually minimal or moderate, but non-zero.
3) If the 'front-end' server fails, so does the back-end.
4) The back-end server will log all requests as coming from the front-end server; It won't 'see' the original requestors' IP addresses. Again, this affects the usefulness of your 'stats.'

For these reasons, mapping the requested URLs into a different/non-default filepath (an internal URL-to-filepath rewrite) is to be preferred.

Otherwise, look into setting the HTTP X-Forwarded-For request header on the front end and sending that to the back-end. Then use mod_log_config to configure the back-end server's logging to use that header instead of the (usual) remote-client's IP address or hostname. You can also use custom logging to separate out requests arriving at the front-end which are bound for the back-end, to avoid polluting the front-end logs. You can either put the back-end log data into a separate file, or log it to the bit-bucket and discard it.

Jim

sublime1

9:18 pm on Apr 23, 2010 (gmt 0)

10+ Year Member



Jim --

Thanks for the advice. I would certainly like to avoid a reverse proxy if I can as it just adds layers of complexity. And yes, the DocumentRoot is the same.

But I am not sure I have any choice, given my constraint:

When a request from the domain customerexample.com makes its way through the virtual host it needs have its domain name rewritten to customerexample.example.com.

(simpler variant: request to foo.com needs to become foo.bar.com).

We also need to pass along cookies.

Is there a way other than using ProxyPass and the other reverse proxy Apache directives?

Thanks!

Tom

g1smd

12:12 am on Apr 24, 2010 (gmt 0)

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



When a request from the domain customerexample.com makes its way through the virtual host it needs have its domain name rewritten to customerexample.example.com.

Technically, the above makes no sense whatsoever.

The rewrite mechanism actually works like this:

When a user requests the URL example.com/something the rewrite needs to fetch content from /some-internal-path inside the server.


The server filesystem has no concept of domain names. It is just folders and files on a hard drive.

sublime1

3:35 am on Apr 24, 2010 (gmt 0)

10+ Year Member



Wow, that's a little harsh, dude -- I was just asking for some help in solving a problem. If I used the term "rewrite" in a way that is not the exact meaning of the Apache docs, it may be because I need some help understanding them from the experts here.

Tom

g1smd

7:32 am on Apr 24, 2010 (gmt 0)

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



What's harsh is that getting the coding wrong can literally put you out of business. This stuff is server configuration code. One tiny error can immediately take your site offline (if you are lucky) or can sit there silently eroding your search rankings over weeks and months. One day you see that your traffic and sales dry up, but have no idea why. Once you find the problem and fix it, it could be weeks or months before your sales start appearing again.

The point I was trying to make is that an external redirect redirects a URL request to a different URL (the browser makes a new request for a different URL), whereas a rewrite connects an external URL request to an internal file (the content is served at the originally requested URL). A rewrite involves a URL and an internal filepath, not two URLs. There's also proxies to consider, where the request is handled by one domain and then silently passed as an HTTP request to another domain, but this has many disadvantages as jdMorgan already explained above.

It is important to see and understand the distinction, as then the right question can be asked. We're happy to help, but don't want to end up giving the right answer to the wrong question. You have to also bear in mind that you're likely working on one or two project and that contributors here might have answered questions about multiple disparate problems as well as working on their own projects to earn a crust.

One thing I should have clarified earlier, but missed, is that RewriteRule cannot see the leading slash when used in .htaccess - which is what 99% of the people in this forum are doing. The leading slash can be seen when used in httpd.conf file. I overlooked adding those crucial words in the original answer. Apologies.

Most people spend 10% of the time working out what they think they want the code to do, and 90% of the time trying to get the code to work, because the requirements were poorly defined. It should be the other way round. The requirements have to be exactly defined. Once they are, the coding part becomes much easier. :)



simpler variant: request to foo.com needs to become foo.bar.com

Are you sure you aren't asking for a redirect?

sublime1

5:29 pm on Apr 24, 2010 (gmt 0)

10+ Year Member



Agreed. A wrong answer is worse than none at all, so thanks for the further detail. Despite my seeming ignorance on this subject, I have been working on Apache since v1.2 in the late 90's, have submitted patches that survive in the product to this day, and manage sites with up-time (no outages) measured in years. I'm not trying to brag, just to let you know that I get it.

I also dislike imprecise questions for the reasons you point out. As I re-read my initial question, I believe it accurately states my requirement.

No, I do not want a redirect. In the user's browser, the customer wants only their domain, not our internal variant.

The reason I need this is that we have an existing system that relies on the getting a request with the subdomain part of the hostname as a key for mapping to a namespace, specific to the particular site, that the rest of the code works in. So the "foo" in foo.bar.com is the key. Most customers are fine with foo.bar.com (bar.com is our domain), some customers prefer their own domain, foo.com. Otherwise, everything in the path part of the URL is the same. We would like a single back-end system that supports either approach.

Without changing code on the back end, I am seeking a way, within an Apache virtual host (not .htaccess), to have our code get the domain part of HTTP (or HTTPS) requests in the expected format, foo.bar.com. Because aspects of the customer sites require authentication and SSL, we need to manage cookies between the two domains, as well, and maybe even SSL certs, later.

It looks like these requirements are supported in Apache 2.2 using ProxyPass (or its alternative form, the P flag on a RewriteRule), as well as ProxyPassReverse, and ProxyPassReverseCookieDomain and perhaps a couple other related directives.

However, the proxy approach is not ideal for reasons pointed out by jdMorgan, so if there were another method (involving rewriting or some other approach), it would be great to know a better, simpler method.

Thanks,

Tom

jdMorgan

12:37 am on Apr 26, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I suspect that SSL is going to be problematic, and may only be workable for your "foo.com" domains. You're going to need a unique IP address for each SSL server, as I understand things.

So I think that that indicates where you'll need to "draw the line" between the two approaches -- individual VirtualHosts for the SSL-enabled foo.com sites, and ServerAliases for the non-SSL "foo.com" sites and foo.bar.com sites, all pointing to the same DocumentRoot filespace.

From that point, I'm not sure how you plan to pass the domain/subdomain information to your application, but I assume that it can check HTTP_HOST for either the foo.com- or foo.bar.com-format requested hostnames.

Jim