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