Class: Nitro::MongrelAdapter

Inherits:
Mongrel::HttpHandler
  • Object
show all
Defined in:
lib/nitro/adapter/mongrel.rb

Overview

A Mongrel Adapter for Nitro. This is the prefered adapter to use in production mode. Typically you will have a front-end web server (for example apache) handle static content and proxy dynamic content request to a cluster of mongrel servers.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(server) ⇒ MongrelAdapter

Returns a new instance of MongrelAdapter.



90
91
92
93
# File 'lib/nitro/adapter/mongrel.rb', line 90

def initialize(server)
  @server = server
  @handle_static_files = Server.handle_static_files
end

Instance Attribute Details

#serverObject

Returns the value of attribute server.



88
89
90
# File 'lib/nitro/adapter/mongrel.rb', line 88

def server
  @server
end

Instance Method Details

#handle(req, res) ⇒ Object

Handle the request. – TODO: recode this like the camping mongrel handler. ++



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/nitro/adapter/mongrel.rb', line 136

def handle(req, res)
  unless handle_file(req, res)
    begin
      path = req.path_info
    
      context = Context.new(@server)

      context.in = if req.body.is_a? String
                     StringIO.new(req.body)
                   else
                     req.body
                   end

      context.headers = {}
      req.params.each { |h, v|
        if h =~ /\AHTTP_(.*)\Z/
          context.headers[$1.gsub("_", "-")] = v
        end
        context.headers[h] = v
      }
      
      # hackfix: make it behave like webrick and fcgi
      context.headers['REQUEST_URI'] << "?#{context.headers['QUERY_STRING']}" if context.headers['QUERY_STRING']
      context.headers['QUERY_STRING'] ||= ''

      Cgi.parse_params(context)
      Cgi.parse_cookies(context)

      context.render(path)
=begin
      res.start(context.status,true) do |head,out|
        out.write(Cgi.response_headers(context))    
        out.write(context.out)
      end 
=end

      # what is the error code if a request without a handler 
      # is comming?! al 2006-Aug-05
      
      res.start(context.status, true) do |head,out|
        context.response_headers.each do |key, value|
          head[key] = value
        end
        
        context.response_cookies.each do |cookie|
          head['Set-Cookie'] = cookie
        end if context.response_cookies
        
        out.write(context.out)
      end
    
      context.close
    ensure
      $autoreload_dirty = false
      Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager) and Og.manager
    end
  end
end

#handle_file(req, res) ⇒ Object

Handle a static file. Also handles cached pages.



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/nitro/adapter/mongrel.rb', line 101

def handle_file(req, res)
  rewrite(req)
  
  # gmosx, FIXME: this is a nasty hack that fixes a really
  # *nasty* caching bug. Find a better solution. When hitting
  # the backend server, if the index method takes parameters
  # the dispatcher considers all static files as parameters.
  # If you have output caching enabled for the index page, 
  # all your static files get corrupted.
  
  if (@handle_static_files == false) and (req.path_info =~ /\.html$/)
    return false
  end
  
  # TODO: handle If-Modified-Since and add Last-Modified headers

  filename = File.join(@server.public_root, req.path_info).squeeze('/')

  File.open(filename, "rb") do |f|
    # TODO: check whether path circumvents public_root directory?
    res.status = 200
    res.body << f.read # XXX inefficient for large files, may cause leaks
  end
  return true
rescue Errno::ENOENT => ex # TODO: Lookup Win32 error for 'file missing'
  return false
ensure
  unrewrite(req)
end

#process(req, res) ⇒ Object



95
96
97
# File 'lib/nitro/adapter/mongrel.rb', line 95

def process(req, res)
  handle(req, res)
end

#rewrite(req) ⇒ Object

Try to rewrite the path to a filename.



197
198
199
200
201
202
203
# File 'lib/nitro/adapter/mongrel.rb', line 197

def rewrite(req)
  if req.path_info == '/' || req.path_info == ''
    req.path_info = '/index.html'
  elsif req.path_info =~ /^([^.]+)$/
    req.path_info = "#{$1}.html"
  end
end

#unrewrite(req) ⇒ Object

Rewrite back to the original path.



207
208
209
210
211
212
213
# File 'lib/nitro/adapter/mongrel.rb', line 207

def unrewrite(req)
  if req.path_info == '/index.html'
    req.path_info = '/'
  elsif req.path_info =~ /^([^.]+)\.html$/    
    req.path_info = $1
  end
end