- we have an example.com access site, that could or could not has some contents of its own;
- we have a first Rail application, called First App, that should be accessed with the starting URL http://example.com/firstapp;
- we have a second Rail application, called Second App, that should be accessed with the starting URL http://example.com/secondapp;
- (we need someone payed to find fancy names for our applications, by the way);
$ cat firstapp.ports ports 3000|3001|3002 $ cat secondapp.ports ports 3003|3004
<VirtualHost *:80>
ServerName example.com
ProxyRequests Off
# First app
ProxyPassReverse /firstapp http://127.0.0.1:3000/
ProxyPassReverse /firstapp http://127.0.0.1:3001/
ProxyPassReverse /firstapp http://127.0.0.1:3002/
# Second App
ProxyPassReverse /secondapp http://127.0.0.1:3003/
ProxyPassReverse /secondapp http://127.0.0.1:3004/
ProxyPreserveHost On
RewriteEngine On
# Rewriting maps
RewriteMap mongrelfirstapp rnd:/path-to/firstapp.ports
RewriteMap mongrelsegreteria rnd:/path-to/secondapp.ports
# Rewrite for example.com/firstapp
RewriteCond %{REQUEST_URI} ^/firstapp.*
RewriteRule ^/(.*) http://localhost:${mongrelfirstapp:ports}/$1 [P,L]
# Rewrite for example.com/secondapp
RewriteCond %{REQUEST_URI} ^/secondapp.*
RewriteRule ^/(.*) http://localhost:${mongrelsecondapp:ports}/$1 [P,L]
#RewriteLogLevel 9
#RewriteLog logs/rewrite-example.com.log
ErrorLog logs/error-example.com.log
The ProxyPassReverse directives instruct Apache on how to deal with the Mongrel back-end servers, you need one directive for every listening Mongrel. Then, we define two RewriteMap, one for each application, called mongrelfirstap and mongrelsecondapp. These rewriting maps choose a random value for the port parameter, due to the rnd: prefix. Then we tell Apache that: if the URI starts with /firstapp, it should proxy [P] the request to one of the three Mongrel serving the first application, choosing it randomly (mongrelfirstapp:ports), and this must be the last URL rewriting rule to apply for this request [L]. Otherwise, if the URL is starting with /secondapp, it should do the same with respect che Mongrel servers serving Second App. Otherwise, it will serve the URI with the standard Apache mechanism. If example.com is itself served via mongrel, you can add other configuration directives where the prefix is not /firstapp but a simple /.
Speaking about prefix, the Mongrel istances must be started with the –prefix parameter that should equal the part defined in the RewriteCond (so, –prefix=/firstapp and no trailing slash). It’s possible to made some syntactic sugar to avoid this, but I prefer that the application itself has an idea on where is located.
About performance: this configuration will proxy every request, included the ones asking for static content. It’s possible to define some rewrite conditions that result in the intervention of Mongrel instances only when there’s actually some Rails code to parse, otherwise relying on Apache, but I don’t need this in my setup.
Filed under: ruby on rails, apache, mongrel, proxy, rails, rhel

Recent Comments