From 09c945d4080bd97f16445d713b8b520b91d019f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Tue, 21 Dec 2010 22:29:22 +0100 Subject: [PATCH 1/3] Use rack instead of CGI --- lib/mongrel/rails.rb | 62 ++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/lib/mongrel/rails.rb b/lib/mongrel/rails.rb index 54bb830..38f4844 100644 --- a/lib/mongrel/rails.rb +++ b/lib/mongrel/rails.rb @@ -5,7 +5,6 @@ # for more information. require 'mongrel' -require 'cgi' module Mongrel @@ -35,6 +34,9 @@ class RailsHandler < Mongrel::HttpHandler @@file_only_methods = ["GET","HEAD"] def initialize(dir, mime_map = {}) + rails_app = Rails.respond_to?(:application) ? ::Rails.application : ActionController::Dispatcher.new + @app = Rack::Chunked.new(Rack::ContentLength.new(rails_app)) + @files = Mongrel::DirHandler.new(dir,false) @guard = Mutex.new @@ -65,25 +67,46 @@ def process(request, response) request.params[Mongrel::Const::PATH_INFO] = page_cached @files.process(request,response) else + env = {}.replace(request.params) + env.delete "HTTP_CONTENT_TYPE" + env.delete "HTTP_CONTENT_LENGTH" + + env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/" + + rack_input = request.body || StringIO.new('') + rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding) + + env.update({"rack.version" => Rack::VERSION, + "rack.input" => rack_input, + "rack.errors" => $stderr, + + "rack.multithread" => true, + "rack.multiprocess" => false, # ??? + "rack.run_once" => false, + + "rack.url_scheme" => "http", + }) + env["QUERY_STRING"] ||= "" + + status, headers, body = @app.call(env) + begin - cgi = Mongrel::CGIWrapper.new(request, response) - cgi.handler = self - # We don't want the output to be really final until we're out of the lock - cgi.default_really_final = false - - @guard.synchronize { - @active_request_path = request.params[Mongrel::Const::PATH_INFO] - Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body) - @active_request_path = nil + response.status = status.to_i + response.send_status(nil) + + headers.each { |k, vs| + vs.split("\n").each { |v| + response.header[k] = v + } } + response.send_header - # This finalizes the output using the proper HttpResponse way - cgi.out("text/html",true) {""} - rescue Errno::EPIPE - response.socket.close - rescue Object => rails_error - STDERR.puts "#{Time.now}: Error calling Dispatcher.dispatch #{rails_error.inspect}" - STDERR.puts rails_error.backtrace.join("\n") + body.each { |part| + response.write part + response.socket.flush + } + ensure + body.close if body.respond_to? :close end end end @@ -145,10 +168,9 @@ def rails(options={}) ENV['RAILS_ENV'] = ops[:environment] env_location = "#{ops[:cwd]}/config/environment" require env_location - require 'dispatcher' - require 'mongrel/rails' - ActionController::AbstractRequest.relative_url_root = ops[:prefix] if ops[:prefix] +# TODO: Is there some Rails 3 equivalent +# ActionController::AbstractRequest.relative_url_root = ops[:prefix] if ops[:prefix] @rails_handler = RailsHandler.new(ops[:docroot], ops[:mime]) end From b2299805cc3eb5355aac75c70cc78947f06d70ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Tue, 21 Dec 2010 22:34:41 +0100 Subject: [PATCH 2/3] Updated documentation --- lib/mongrel/rails.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mongrel/rails.rb b/lib/mongrel/rails.rb index 38f4844..94e4acb 100644 --- a/lib/mongrel/rails.rb +++ b/lib/mongrel/rails.rb @@ -23,7 +23,7 @@ module Rails # # * 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.dispatch to have Rails go. + # * Finally, run the Rails application Rack handler. # # 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 a static From 9aa5f7dc2c13e5d06e30d25acca0cc3de137a7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Tue, 21 Dec 2010 22:46:42 +0100 Subject: [PATCH 3/3] Remove reload on HUP signal. --- bin/mongrel_rails | 2 +- lib/mongrel/rails.rb | 43 ------------------------------------------- 2 files changed, 1 insertion(+), 44 deletions(-) diff --git a/bin/mongrel_rails b/bin/mongrel_rails index ea3839b..15600c0 100644 --- a/bin/mongrel_rails +++ b/bin/mongrel_rails @@ -124,7 +124,7 @@ module Mongrel run_config(defaults[:config_script]) end - setup_rails_signals + setup_signals end end diff --git a/lib/mongrel/rails.rb b/lib/mongrel/rails.rb index 94e4acb..4c6f8df 100644 --- a/lib/mongrel/rails.rb +++ b/lib/mongrel/rails.rb @@ -38,7 +38,6 @@ def initialize(dir, mime_map = {}) @app = Rack::Chunked.new(Rack::ContentLength.new(rails_app)) @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) } @@ -110,19 +109,6 @@ def process(request, response) end end end - - # 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. - def reload! - begin - @guard.synchronize { - $".replace $orig_dollar_quote - GC.start - Dispatcher.reset_application! - ActionController::Routing::Routes.reload - } - end - end end # Creates Rails specific configuration options for people to use @@ -164,7 +150,6 @@ def rails(options={}) ops[:docroot] ||= "public" ops[:mime] ||= {} - $orig_dollar_quote = $".clone ENV['RAILS_ENV'] = ops[:environment] env_location = "#{ops[:cwd]}/config/environment" require env_location @@ -174,34 +159,6 @@ def rails(options={}) @rails_handler = RailsHandler.new(ops[:docroot], ops[:mime]) end - - # Reloads Rails. This isn't too reliable really, but it - # should work for most minimal reload purposes. The only reliable - # way to reload properly is to stop and then start the process. - def reload! - if not @rails_handler - raise "Rails was not configured. Read the docs for RailsConfigurator." - end - - log "Reloading Rails..." - @rails_handler.reload! - log "Done reloading Rails." - - end - - # Takes the exact same configuration as Mongrel::Configurator (and actually calls that) - # but sets up the additional HUP handler to call reload!. - def setup_rails_signals(options={}) - ops = resolve_defaults(options) - setup_signals(options) - - unless RbConfig::CONFIG['host_os'] =~ /mingw|mswin/ - # rails reload - trap("HUP") { log "HUP signal received."; reload! } - - log "Rails signals registered. HUP => reload (without restart). It might not work well." - end - end end end end