I wonder if anyone got a jRuby Rails 3.0 app to work behind an Apache 2 proxy, through an AJP mount. I'd like the following configuration to work, without uncommenting the last statement.
<VirtualHost *:80>
ServerName app.example.com
ProxyRequests Off
ProxyPass / ajp://127.0.0.1:8009/app/
ProxyPassReverse / ajp://127.0.0.1:8009/app/
# ProxyPassReverse / http://app.example.com/app/
</VirtualHost>
First, there seems to be no way to get relative redirects for named routes in the rails app (i.e. login and logout routes for restful_authentication). The Rails app does not even hook the reverse proxy statement on the AJP mount, but must be caught on a static HTTP reverse proxy rule for the full URI (shown in the comment). Second, there seems to be no proper way of suggesting assets output of HTML helpers on a level according to the reverse proxy rules.
I could do this, but it feels rather like an exploit, much like the static reverse proxy rule:
config.asset_path = proc { |path| path.gsub(/\/app\//, '/') }
Adding an RAILS_RELATIVE_URL_ROOT apparantly only adds to the already configured scope of the deployed warble WAR, and does not help reduce routes.
There must surely be mod_proxy_ajp solutions for running proxy and reverseproxy with unexact match routes.
Any ideas on how to solve this or point me in the direction of a resource covering the problem?
Solution 1
I think that if you need the HTTP rewrite magic you need to switch from using ajp and use the http proxying it fixes a couple of corner cases in proxying between different paths, it rewrites the http headers, I'm not sure proxy ajp does that. I'd just try to serve the rails app as ROOT.war or on a virtual host or something on the tomcat server to minimize the source of error proxying a folder as root. There's always something that doesn't work or needs adjustment. Ports and local domain names are cheap.
Add this to your production environment config file:
config.action_controller.relative_url_root = '/app'
see more @ What is the replacement for ActionController::Base.relative_url_root?
Solution 2:
If you want to you can reset the incoming paths in the rails app with some easy rack middleware. This way the rails app would not know anything about not serving in the root path. You might also want to add config.serve_static_assets = true to make rails serve static assets in production mode.
# application.rb
require "proxy_path_reset_filter"
config.middleware.use "ProxyPathResetFilter"
config.action_controller.relative_url_root = '/'
apologies for typing this freehand, but it should work.
# proxy_path_reset_filter.rb
class ProxyPathResetFilter
def initialize(app)
@app = app
end
def call(env)
# some servers use REQUEST_URI and some use PATH_INFO for routing use both
if (env['REQUEST_URI'] || env['PATH_INFO']) =~ /^\/app\//
env.update({
'REQUEST_URI' => env['REQUEST_URI'].gsub(/^\/app\//, '/')),
'PATH_INFO' => env['PATH_INFO'].gsub(/^\/app\//, '/')) })
end
@app.call(env)
end
end