lib/merb/merb_handler.rb in merb-0.1.0 vs lib/merb/merb_handler.rb in merb-0.2.0
- old
+ new
@@ -1,14 +1,26 @@
+class Mongrel::HttpResponse
+ NO_CLOSE_STATUS_FORMAT = "HTTP/1.1 %d %s\r\n".freeze
+ def send_status_no_connection_close(content_length=@body.length)
+ if not @status_sent
+ @header['Content-Length'] = content_length unless @status == 304
+ write(NO_CLOSE_STATUS_FORMAT % [@status, Mongrel::HTTP_STATUS_CODES[@status]])
+ @status_sent = true
+ end
+ end
+end
+
+
+
class MerbHandler < Mongrel::HttpHandler
@@file_only_methods = ["GET","HEAD"]
# take the name of a directory and use that as the doc root or public
# directory of your site. This is set to the root of your merb app + '/public'
# by default.
def initialize(dir, opts = {})
@files = Mongrel::DirHandler.new(dir,false)
- @guard = Mutex.new
end
# process incoming http requests and do a number of things
# 1. check for rails style cached pages. add .html to the
# url and see if there is a static file in public that matches.
@@ -28,11 +40,11 @@
if response.socket.closed?
return
end
- MERB_LOGGER.info("\nRequest: PATH_INFO: #{request.params[Mongrel::Const::PATH_INFO]} (#{Time.now.strftime("%Y-%m-%d %H:%M:%S")})")
+ MERB_LOGGER.info("\nRequest: REQUEST_URI: #{request.params[Mongrel::Const::REQUEST_URI]} (#{Time.now.strftime("%Y-%m-%d %H:%M:%S")})")
# Rails style page caching. Check the public dir first for
# .html pages and serve directly. Otherwise fall back to Merb
# routing and request dispatching.
path_info = request.params[Mongrel::Const::PATH_INFO]
@@ -48,27 +60,15 @@
MERB_LOGGER.info("Serving static file: #{page_cached}")
request.params[Mongrel::Const::PATH_INFO] = page_cached
@files.process(request,response)
else
begin
- # This handles parsing the query string and post/file upload
- # params and is outside of the synchronize call so that
- # multiple file uploads can be done at once.
+ # dLet Merb:Dispatcher find the route and call the filter chain and action
controller = nil
- controller, action = handle(request)
- MERB_LOGGER.info("Routing to controller: #{controller.class} action: #{action}\nParsing HTTP Input took: #{Time.now - start} seconds")
+ controller, action = Merb::Dispatcher.handle(request, response)
- # We need a mutex here because ActiveRecord code can be run
- # in your controller actions. AR performs much better in single
- # threaded mode so we lock here for the shortest amount of time
- # possible. Route recognition and mime parsing has already occured
- # at this point because those processes are thread safe. This
- # gives us the best trade off for multi threaded performance
- # of thread safe, and a lock around calls to your controller actions.
- @guard.synchronize {
- controller.dispatch(action)
- }
+ MERB_LOGGER.info("Routing to controller: #{controller.class} action: #{action}\nRoute Recognition & Parsing HTTP Input took: #{Time.now - start} seconds")
rescue Object => e
response.start(500) do |head,out|
head["Content-Type"] = "text/html"
MERB_LOGGER.info(Merb.exception(e))
out << Merb.html_exception(e)
@@ -111,47 +111,19 @@
response.write(chunk)
end
if controller.body.respond_to? :close
controller.body.close
end
+ elsif Proc === controller.body
+ controller.body.call
else
MERB_LOGGER.info("Response status: #{response.status}\nComplete Request took: #{Time.now - start} seconds\n\n")
# render response from successful controller
body = (controller.body.to_s rescue '')
response.send_status(body.length)
response.send_header
response.write(body)
end
end
end
-
- # This is where we grab the incoming request PATH_INFO
- # and use that in the merb routematcher to determine
- # which controller and method to run.
- # returns a 2 element tuple of:
- # [controller, action]
- def handle(request)
- path = request.params[Mongrel::Const::PATH_INFO].sub(/\/+/, '/')
- path = path[0..-2] if (path[-1] == ?/) && path.size > 1
- route = Merb::RouteMatcher.new.route_request(path)
- [ instantiate_controller(route[:controller], request.body, request.params, route),
- route[:action] ]
- end
-
- # take a controller class name string and reload or require
- # the right controller file then CamelCase it and turn it
- # into a new object passing in the request and response.
- # this is where your Merb::Controller is instantiated.
- def instantiate_controller(controller_name, req, env, params)
- if !File.exist?(DIST_ROOT+"/app/controllers/#{controller_name.snake_case}.rb")
- raise Merb::MissingControllerFile
- end
- begin
- controller_name.import
- return Object.const_get( controller_name.camel_case ).new(req, env, params)
- rescue RuntimeError
- warn "Error getting instance of '#{controller_name.camel_case}': #{$!}"
- raise $!
- end
- end
end
\ No newline at end of file