Class: Mongrel::Rails::RailsHandler

Inherits:
HttpHandler show all
Defined in:
lib/mongrel/rails.rb

Overview

Implements a handler that can run Rails and serve files out of the Rails application’s public directory. This lets you run your Rails application with Mongrel during development and testing, then use it also in production behind a server that’s better at serving the static files.

The RailsHandler takes a mime_map parameter which is a simple suffix=mimetype mapping that it should add to the list of valid mime types.

It also supports page caching directly and will try to resolve a request in the following order:

  • If the requested exact PATH_INFO exists as a file then serve it.

  • If it exists at PATH_INFO+“.html” exists then serve that.

  • Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispath to have Rails go.

This means that if you are using page caching it will actually work with Mongrel and you should see a decent speed boost (but not as fast as if you use lighttpd).

An additional feature you can use is

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dir, mime_map = {}) ⇒ RailsHandler

Returns a new instance of RailsHandler.



32
33
34
35
36
37
38
# File 'lib/mongrel/rails.rb', line 32

def initialize(dir, mime_map = {})
  @files = Mongrel::DirHandler.new(dir,false)
  @guard = Mutex.new
  
  # register the requested mime types
  mime_map.each {|k,v| Mongrel::DirHandler::add_mime_type(k,v) }
end

Instance Attribute Details

#filesObject (readonly)

Returns the value of attribute files.



29
30
31
# File 'lib/mongrel/rails.rb', line 29

def files
  @files
end

#guardObject (readonly)

Returns the value of attribute guard.



30
31
32
# File 'lib/mongrel/rails.rb', line 30

def guard
  @guard
end

Instance Method Details

#process(request, response) ⇒ Object

Attempts to resolve the request as follows:

  • If the requested exact PATH_INFO exists as a file then serve it.

  • If it exists at PATH_INFO+“.html” exists then serve that.

  • Finally, construct a Mongrel::CGIWrapper and run Dispatcher.dispath to have Rails go.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/mongrel/rails.rb', line 46

def process(request, response)
  return if response.socket.closed?
  
  path_info = request.params[Mongrel::Const::PATH_INFO]
  page_cached = request.params[Mongrel::Const::PATH_INFO] + ".html"
  
  if @files.can_serve(path_info)
      # File exists as-is so serve it up
    @files.process(request,response)
  elsif @files.can_serve(page_cached)
    # possible cached page, serve it up      
    request.params[Mongrel::Const::PATH_INFO] = page_cached
    @files.process(request,response)
  else
    begin
      cgi = Mongrel::CGIWrapper.new(request, response)
      cgi.handler = self
      
      @guard.synchronize do
        # Rails is not thread safe so must be run entirely within synchronize 
        Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
      end
      
      # This finalizes the output using the proper HttpResponse way
      cgi.out {""}
    rescue Errno::EPIPE
      # ignored
    rescue Object => rails_error
      STDERR.puts "Error calling Dispatcher.dispatch #{rails_error.inspect}"
      STDERR.puts rails_error.backtrace.join("\n")
    end
  end
end

#reload!Object

Does the internal reload for Rails. It might work for most cases, but sometimes you get exceptions. In that case just do a real restart.



83
84
85
86
87
88
89
90
# File 'lib/mongrel/rails.rb', line 83

def reload!
  @guard.synchronize do
    $".replace $orig_dollar_quote
    GC.start
    Dispatcher.reset_application!
    ActionController::Routing::Routes.reload
  end
end