httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Garrett Rooney" <roo...@electricjellyfish.net>
Subject Rails and mod_proxy_fcgi, a match made in... well... someplace anyway.
Date Sat, 04 Mar 2006 23:50:04 GMT
So I've been trying to make Rails work with mod_proxy_fcgi (since the
whole point of writing mod_proxy_fcgi was to make it easier to use
rails/django type web apps with httpd, and I'm more of a Ruby person
than a Python person), and I think I've made enough progress that it's
worth sharing with the world.

Note that this doesn't completely work yet.  It'll render some pages
in a basic Rails application, but for reasons I don't completely
understand it occasionally just hangs.  YMMV.

My current httpd.conf configuration looks something like this:

# create a balancer group for the app
<Proxy balancer://helloworld>
  BalancerMember fcgi://localhost:4747
</Proxy>

# NOTE: the name dispatch.fcgi is IMPORTANT, Rails uses it internally
#       to determine the relative root url.
ProxyPass /helloworld/dispatch.fcgi balancer://helloworld

# you need a symlink in your htdocs dir for this, named helloworld
# pointing to the public dir in your app
<Location /helloworld>
  RewriteEngine On

  # don't loop
  RewriteCond %{REQUEST_URI} !^/helloworld/dispatch.fcgi

  # let files pass through normally
  RewriteCond %{REQUEST_FILENAME} !-f

  # other stuff gets passed through the proxy
  RewriteRule /helloworld/(.*)$ /helloworld/dispatch.fcgi/$1 [QSA,L]
</Location>

I then start the Rails dispatcher.fcgi with the spawn-fcgi program
from lighttpd, like this:

RAILS_ENV=production ./spawn-fcgi -f `pwd`/public/dispatch.fcgi -p 4747

Eventually we'll want to ship something like this with mod_proxy_fcgi,
but swiping the one from lighttpd will do for now.

Now to get from this to basic functionality you need to hack
action_controller/request.rb's relative_url_root method:

--- /usr/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/request.rb.orig
2006-03-04 15:40:43.000000000 -0800
+++ /usr/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/request.rb
     2006-03-04 13:53:18.000000000 -0800
@@ -169,7 +169,8 @@
     # Returns the path minus the web server relative installation directory.
     # This method returns nil unless the web server is apache.
     def relative_url_root
-      @@relative_url_root ||= server_software == 'apache' ?
env["SCRIPT_NAME"].to_s.sub(/\/dispatch\.(fcgi|rb|cgi)/, '') : ''
+      # XXX hack
+      @@relative_url_root ||= server_software == 'apache' ?
env["SCRIPT_NAME"].to_s.sub(/\/dispatch\.(fcgi|rb|cgi).*$/, '') : ''
     end

     # Returns the port number of this request as an integer.

The original implementation assumes that you're using a handler type
module that routes through dispatch.fcgi, thus it has a SCRIPT_NAME
that ends in dispatch.fcgi.  For mod_proxy_fcgi that's not the case
though, the SCRIPT_NAME ends up getting set to
/helloworld/dispatch.fcgi/more/stuff, and we need to rip off
everything all the way to the end.  I'm not sure who's wrong in this
case, mod_proxy_fcgi or Rails, but in any event this is a quick
solution to the problem.

Finally, just add a symlink from 'helloworld' in your htdocs directory
to the 'public' directory of your rails application.

At this point you should be far enough along to view the default
index.html you get when you create a new rails application, and
clicking on the "About your application's environment" link will do
its ajax magic and hit the backend fcgi process to pull down info
about the various libraries you're using.

Doing more than this may or may not work.  For example, if you use
rails scaffolding to create a model, view, and controller for some
object you'll be able to view some pages, but some will hang.  Oddly,
clicking on links that direct you to another part of the app often
seem to hang, but cutting and pasting the same URL into the address
bar of the browser will work fine.  I still need to figure out what's
causing this, but I suspect a problem in mod_proxy_fcgi, because when
you break into httpd with a debugger you find it sitting in apr_poll.

Anyway, just wanted to share what I've come up with so far, in case
anyone else wants to give this stuff a shot.  Once I manage to get a
Rails app (or Django or any other significant fcgi based web framework
for that matter, but I'm most concerned about Rails) working reliably
I think mod_proxy_fcgi will be suitable for merging back into trunk.

-garrett

Mime
View raw message