Reverse-proxy a Rails app with Apache 25 Oct 2013
Recently I had to make one part of a Rails app available via a path of another Apache vhost.
The Rails app is running at http://app.example.com/engine-name
and has to be accessible at http://www.example.com/app
.
After spending some time figuring out mod_proxy
and mod_proxy_html
I came up with the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<VirtualHost *:80>
ServerName www.example.com
ProxyPreserveHost Off
RewriteEngine On
RewriteRule ^(?:/app)?/assets/swf/(.*) http://app.example.com/assets/swf/$1 [P]
RedirectMatch /engine-name(.*) http://www.example.com/app$1
<Location /app>
ProxyPass http://app.example.com/engine-name
ProxyPassReverse http://app.example.com/engine-name
SetOutputFilter proxy-html
ProxyHTMLDocType "<!DOCTYPE html>"
ProxyHTMLURLMap ^/assets http://app.example.com/assets R
ProxyHTMLURLMap ^/system http://app.example.com/system R
ProxyHTMLURLMap /engine-name/ /app/
RequestHeader unset Accept-Encoding
Order allow,deny
Allow from all
</Location>
</VirtualHost>
Devil of Details
1
ProxyPreserveHost Off
Disables forwarding of the original request’s Host
header to the backend server. This is important, for example, when the backend server is a name based virtual host.
1
2
RewriteEngine On
RewriteRule ^(?:/app)?/assets/swf/(.*) http://app.example.com/assets/swf/$1 [P]
Rewrites all incoming requests to assets, e.g. /assets/swf/soundmanager2.swf
, to the proxied backend.
1
2
ProxyPass http://app.example.com/engine-name
ProxyPassReverse http://app.example.com/engine-name
Proxies all requests to the given argument. The ProxyPassReverse
directive should cause redirects contained in the response from the backend server to be rewritten.
Since this somehow did not work I worked around the issue using the RedirectMatch
directive.
1
SetOutputFilter proxy-html
This puts all incoming HTML-type responses through mod_proxy_html
’s HTML filter.
1
ProxyHTMLDocType "<!DOCTYPE html>"
The mod_proxy_html
module scraps doc types. This adds the HTML5 doc type.
1
2
ProxyHTMLURLMap ^/assets http://app.example.com/assets R
ProxyHTMLURLMap ^/system http://app.example.com/system R
This rewrites all references to assets and /public/system
files to absolute URLs which go directly to the backend server. Just have look at the resulting HTML.
1
ProxyHTMLURLMap /engine-name/ /app/
Finally, replace all references to the backend server’s path to the proxy path.
1
RequestHeader unset Accept-Encoding
Browsers might have difficulties displaying/decoding the response. To handle this, I reset the Accept-Encoding
header.