Varnish Cache Url Rewriting

Hi All,

I’ve been playing with getting a varnish cache in front of my event store.

I have varnish running on 6801 and forwarding requests to 2113 (my EventStore http port).

It all works fine except that all the urls in the response come back with full URLs that point to 2113.

ie:

“links” : [

{

“uri”: “http://localhost:2113/streams/%24all”,

“relation”: “self”

},

etc

]

So as soon as I follow one of the links I’m no longer hitting varnish. Do I need to set varnish up to do some rewriting of the response bodies or is there a way

to get EventStore to return the proxy’s absolute urls/relative urls?

I followed the code a little way and it just seems to be prepending HttpListenerRequest.Url to the urls.

cheers

Andrew

In general, if you have to tweak the config of the backend system, you’re creating a dependency you really don’t want; it should be transparent for ES that a proxy sits in front of it.

So the answer is to have rewrite rules on requests and responses.

–larsw

Thanks Lars,

The wiki suggests setting up varnish which seems not to have the capability to modify the content as it comes back out. Also it feels like a brittle solution to have to inspect the traffic and doing string replacement - I might get all the places now but not in the future.

After doing some research I’ve found that hostname part can be solved already. By having the proxy server pass through the original host header that is the response you get back from EventStore

On windows this just works:

curl http://localhost:2113/streams/%24all -u admin:changeit -H ‘Host: abc.com:1234

Gives me links like: http://abc.com:2113/streams/%24stats-127.0.0.1%3A2113/39963

On the linux build I get a Bad Request (Invalid Host) response. I was able to overcome this by starting EventStore like so:

./clusernode --http-prefixes=“http://*:2114” (note the different port it still seems to bind to localhost:2113 which means you can’t also do *:2113)

Most reverse proxies seems to support passing through the Host header unchanged: http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypreservehost. This looks trivial to do with varnish as well.

The next challenge is the port. There doesn’t appear to be a nice way to do this translation. From what I could see the url helpers for MVC and WebAPI don’t support anything for this either. Some proxy servers seem to send through the external port as an additional header. Amazon’s Elastic Load Balancer adds an X-Forwarded-Port header which eventstore could use for generating URLs if it’s present.

http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/TerminologyandKeyConcepts.html (right down the bottom). Something similar should be doable with varnish pretty easily.

So my (hopefully) small proposal is can we have EventStore support a header (X-Forwarded-Port?) from the proxy server that would allow the Port of generated URLs to be controlled. While we are doing this it could probably support X-Forwarded-Proto for http vs https. I am happy to put together a pull request if this sounds reasonable.

If I’ve missed something and it’s possible to have EventStore behind a reverse proxy as is please let me know. (I guess I could have the reverse proxy and event store on different machines and the same port)

cheers

Andrew

Did you try host http://ipaddress/ on linux?

apparently there may be some differences between them http://lists.ximian.com/pipermail/mono-list/2013-October/050348.html

Cheers,

Greg

Hi Greg,

using ./clusernode --http-prefixes=“http://127.0.0.1:2113” has the same problem. EventStore starts up fine but I get the ‘Invalid host’ error if I set the host header

to something else.

cheers

Andrew

We can add an argument for this quite easily I am thinking however there is someway to get the equivalent working in mono (or maybe we should patch mono)

Hey Greg,

Thanks for looking into this. Sorry my email might have been a little confusing. There are two different port problems.

  1. On mono I cannot use 2113 for both localhost and binding to *. That’s a minor thing and so long as I can bind * to some port that’s no big deal.

  2. On both windows and mono I cannot work out how to put a reverse proxy in front of eventstore without having to either:

a) Do string replacement on all the responses in the revere proxy to rewrite urls.

b) Run the proxy and eventstore on different machines but on the same port.

It’s number 2 that is the real thing I am trying to find a fix for. (sorry if this was already clear).

cheers

Andrew

We can easily add config for a replyasbaseuri I would prefer to get it working with plain config though

Would be great if there was a way around that. I spent a few hours today working out what other apps do about ports when reverse proxying and it seems all over the place.

What I like about the X-Forwarded-Port and the X-Forwarded-Proto headers is that if ES supports them they are just headers that the reverse proxy adds to the request - there is no need for EventStore’s config to change at all you just put the reverse proxy in front and configure it to send the headers.

cheers

Andrew

https://github.com/EventStore/EventStore/issues/243