3

I'm trying to design a system that allows for multiple public endpoints that funnel into a single web service. The web service must be able to determine which endpoint was the intended destination of the request. Here's a little sample configuration that might fit the bill:

Sample proxy configuration

In this system, the "reverse proxies" (for lack of a better term) add an HTTP header to the incoming requests before they hit the web service. Otherwise, the proxies are entirely transparent to the request and response.

We're a Windows shop using IIS7/WCF.

The goal is 1) to maintain only a single web service, rather than one per domain, and 2) to decouple domain/web site management from the business logic in the web service. That is, if we know that context will always be specified with a key in the HTTP header, then we don't have to worry about domains changing or the specific content of Request.Headers["HOST"].

My questions are: is this a reasonable approach? If so, is there an app out there that will do the job of the "reverse proxies"? (Squid? IIS itself?)

Thank you for the help!

ladenedge
  • 146
  • 1
  • 10
  • Is there something about the service itself that requires an instance per domain? – Paul Mar 08 '12 at 04:17
  • It doesn't technically require an *instance* per domain - that's really what I'm trying to avoid - but the service does behave differently depending on the domain used to access it. – ladenedge Mar 08 '12 at 04:22
  • 1
    I was trying to understand why it is better to have reverse proxies just to have the service query look at Request.Headers["X-Extra-Header"] than having them just look at Request.Headers["Host"] without the reverse proxies, and assumed a separate service was required per domain. – Paul Mar 08 '12 at 04:30
  • Ah, good question. I'm hoping to insulate the web service from hostnames changing, being masked by load balancers and other operational concerns. Basically, `Request.Headers["HOST"]` feels brittle to me. I'm certainly willing to entertain the position that this approach is excessive or unnecessarily complicated, however! – ladenedge Mar 08 '12 at 05:51
  • 1
    Have you considered using an API key / HMAC to provide context? – HTTP500 Mar 12 '12 at 17:16
  • @HTTP500: A good idea, but unfortunately we're required to support older clients that don't send relevant identifying information in their requests. We also support generic web browsers in some cases. – ladenedge Mar 12 '12 at 17:31
  • This will receive more attention on StackOverflow. It's a web programming architecture probem as much as it is a sysadmin problem – SimonJGreen Mar 12 '12 at 21:45
  • @SimonJGreen: yeah, I wasn't sure. :-( – ladenedge Mar 13 '12 at 02:13

3 Answers3

2

It sounds to me as though what you're trying to do is have a single app that does 2 wholly separate things. At a certain point theres going to be overlap in the code base and functionality, but I don't know your app well enough to help you with that. I have 2 possible solutions for you:

  1. I would try to separate the view related code out from your controllers and models if you're going the MVC direction. That would give you a cleaner separation of the business logic. One possible way to do that is to put your views into 2 separate directories, but then include code from a shared 3rd directory. That gives you one shared library that handles the backend logic while cleanly separating the presentation logic.

  2. I wouldn't be afraid of the HTTP Host header. It's required by HTTP/1.1 and all modern browsers use it. Heck, virtual hosting is entirely dependent on it and you'd be hard pressed to find an IIS or Apache admin who would tell you not to use virtual hosts on production. The big downside of course, if you're doing the header check on the application side, is you can run into some pretty ugly if/case statements. The only thing a reverse proxy setup does is look for a Host and add another header in addition to the Host. So you're really just adding more headers and complexity to your architecture with the reverse proxying.

Kyle
  • 1,589
  • 9
  • 14
  • Thank you for the thoughts! Regarding (1), you can think of it as switching a brand. Eg. when a new user comes in via rp2.com, we have to display the "RP2" landing page, and we have to put them in the RP2 user store. – ladenedge Mar 13 '12 at 02:12
1

Firstly, your HTTP Host field should be preserved by your reverse proxy as it passes the request through. If it's not, then your proxy is wrongly (and weirdly!) configured.

Secondly, passing extra headers and identifying traffic by that is the standard and accepted way to identify traffic handled by a load balancer. For example, that's how load balancers are usually configured to inform web servers that traffic is coming in over SSL (as SSL can't be proxied at that level).

Finally, I think you may be overcomplicating your problem. Realistically how often do domain names change compared to the content behind them?! That's not really how the web is meant to work... There's nothing wrong with your application serving content based on domain name in the HTTP Host header, it's very common practice.

SimonJGreen
  • 3,205
  • 5
  • 33
  • 55
0

One way to do this would be to have a small array of cloud load-balancers each aimed at your web service. Rackspace provides LBaas, and possibly others do as well.

http://www.rackspace.com/cloud/cloud_hosting_products/loadbalancers/

Full disclosure: I do work for Rackspace, however not in sales.

pbr
  • 216
  • 1
  • 3