Apache mod_proxy

Apache webserver is a widely deployed modular web server.
One of its module is called mod_proxy. It aims to turn the web server into a proxy / reverse proxy server with load-balancing capabilities.

At HAProxy Technologies, we only use HAProxy :). Heh, what else ???
And during some deployments, customers ask us to migrate Apache mod_proxy configuration into HAProxy.
Present article explains how to translate ProxyPass related rules.

ProxyPass, ProxyPassReverse, etc…

Apache mod_proxy defines a few directives which let it forward traffic to a remote server.
They are listed below with a short description.

Note: I know the directives introduced in this article could be used in much complicated ways.

ProxyPass

ProxyPass maps local server URLs to remote servers + URL.
It applies on traffic from client to server.

For example:
[sourcecode language=”text”]
ProxyPass /mirror/foo/ http://backend.example.com/
[/sourcecode]

This makes the external URL http://example.com/mirror/foo/bar to be translated and forwarded to a remote server this way: http://backend.example.com/bar

This directive makes apache to update URL and headers to match both external traffic to internal needs.

ProxyPassReverse

ProxyPassReverse Adjusts the URL in HTTP response headers sent from a reverse proxied server. It only updates Location, Content-Location and URL.
It applies to traffic from server to client.

For example:
[sourcecode language=”text”]
ProxyPassReverse /mirror/foo/ http://backend.example.com/
[/sourcecode]

This directive makes apache to adapt responses generated by servers following internal urls to match external urls.

ProxyPassReverseCookieDomain

ProxyPassReverseCookieDomain adjusts the Set-Cookie header sent by the server to match external domain name.

It’s usage is pretty simple. For example:
[sourcecode language=”text”]
ProxyPassReverseCookieDomain internal-domain public-domain
[/sourcecode]

ProxyPassReverseCookiePath

ProxyPassReverseCookiePath adjusts the Set-Cookie header sent by the server to match external path.

It’s usage is pretty simple. For example:
[sourcecode language=”text”]
ProxyPassReverseCookiePath internal-path public-path
[/sourcecode]

Configure ProxyPass and ProxyPassReverse in HAProxy

Bellow, an example HAProxy configuration to make HAProxy work the same way as apache ProxyPass and ProxyPassReverse configuration. It should be added in the backend section while the frontend ensure that only traffic matching this external URL would be redirected to that backend.
[sourcecode language=”text”]
frontend ft_global
acl host_dom.com req.hdr(Host) dom.com
acl path_mirror_foo path -m beg /mirror/foo/
use_backend bk_myapp if host_dom.com path_mirror_foo

backend bk_myapp
[…]
# external URL => internal URL
# http://dom.com/mirror/foo/bar => http://bk.dom.com/bar

# ProxyPass /mirror/foo/ http://bk.dom.com/bar
http-request set-header Host bk.dom.com
reqirep ^([^ :]*)\ /mirror/foo/(.*) \1\ /\2

# ProxyPassReverse /mirror/foo/ http://bk.dom.com/bar
# Note: we turn the urls into absolute in the mean time
acl hdr_location res.hdr(Location) -m found
rspirep ^Location:\ (https?://bk.dom.com(:[0-9]+)?)?(/.*) Location:\ /mirror/foo3 if hdr_location

# ProxyPassReverseCookieDomain bk.dom.com dom.com
acl hdr_set_cookie_dom res.hdr(Set-cookie) -m sub Domain= bk.dom.com
rspirep ^(Set-Cookie:.*)\ Domain=bk.dom.com(.*) \1\ Domain=dom.com\2 if hdr_set_cookie_dom

# ProxyPassReverseCookieDomain / /mirror/foo/
acl hdr_set_cookie_path res.hdr(Set-cookie) -m sub Path=
rspirep ^(Set-Cookie:.*)\ Path=(.*) \1\ Path=/mirror/foo2 if hdr_set_cookie_path
[/sourcecode]

Notes:
  * http to https redirect rules should be handled by HAProxy itself and not by the application server (to avoid some redirect loops)

Links