views:

52

answers:

3

My setup: thin running on port 1234 with --prefix /foobar apache running on port 80 apache reverse proxies /foobar to thin on port 1234

I would like the static assets to not be served via the proxy to thin, but instead be served at /assets directly via apache instead.

I have to use a relative path because I don't know the host name/ip of the rails application before startup (it's app-in-a-box that should be able to be moved around).

I found config.action_controller.asset_host in production.rb, but I can't set that to a relative path. When I do it gets confused and creates really bogus URLs.

How can I make this work?

A: 

You don't need to call it through the config block in the environment, you can call it from the application controller, which gives you access to the request object. So you could do:

class ApplicationController < ActionController::Base
  before_filter :set_asset_url

  def set_asset_url
    ActionController::Base.asset_host = "http://#{request.host}"
  end
end

It feels a little hackish but I know of no better way.

and if you need to worry about ssl and different ports, you could go crazy:

ActionController::Base.asset_host = "http#{request.ssl? ? 's' : ''}://#{request.host_with_port}"
Geoff Lanotte
Thanks. That's definitely another way to go. I wish Rails had a way to do this natively, but the apache solution is really good too.
The Doctor What
I said it felt hackish, I think you went the right way.
Geoff Lanotte
+1  A: 

This depends in your server environment somewhat, but basically you want something along the lines of what is described here: http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/

darkliquid
Your link was really helpful. I had forgotten about `RewriteCond` with `!-f`. I used that info plus some more apache mojo to make answer work.
The Doctor What
A: 

First, I want to thank Geoff and darkliquid. I took what was in darkliquid's link and worked on it to make it work for my case. The big challenge was that I wasn't serving the rails application from the root of the webserver.

Notes:

  • thin is run with --prefix '/railsapp' on port 9999.
  • This works for windows and linux. W00T!
  • I have to use the LA-U (look-ahead) to get the final filename apache would use.
  • The IS_SUBREQ check is to prevent the look-ahead (a sub request) from ever returning the proxy.
  • The /railsapp/index.html rewrite is required because otherwise another rule in my apache conf would rewrite it to /index.html, which is a default 'here's what's here' page; 404s are served elsewhere, though.

Here's the relevant part of the apache configuration:

# Only proxy the thin stuff.
<Proxy /railsapp/*>
    Order deny,allow
    Allow from all
</Proxy>

## Add an alias for filename mapping.
Alias /railsapp "/website/root/railsapp/public"

## We need the Rewrite Engine for this.
RewriteEngine on
<IfDefine debug>
    ## If debugging, turn on logging.
    RewriteLogLevel 9
    RewriteLog "/website/logs/http.rewrite.log"
</IfDefine>

## Check for a static root page.
RewriteRule ^/railsapp/?$ /railsapp/index.html [QSA]

## Check for Rails caching.
RewriteRule ^(/railsapp/[^.]+)$ $1.html [QSA]

## Redirect all non-static requests to Rails.
# Don't proxy on sub-requests (needed to make the LA-U work).
RewriteCond %{IS_SUBREQ} false
# Use look-ahead to see if the filename exists after all the rewrites.
RewriteCond %{LA-U:REQUEST_FILENAME} !-f
# Proxy it to Rails.
RewriteRule ^/railsapp(.*)$  http://127.0.0.1:9999%{REQUEST_URI} [P,QSA,L]

## Make sure Rails requests are reversed correctly.
ProxyPassReverse /railsapp http://127.0.0.1:9999/railsapp

## Disable keepalive; railsappd doesn't support them.
SetEnv proxy-nokeepalive 1
The Doctor What