module Merb class Dispatcher class << self attr_accessor :path_prefix def use_mutex=(val) @@use_mutex = val end @@mutex = Mutex.new @@use_mutex = ::Merb::Server.use_mutex # This is where we grab the incoming request REQUEST_URI 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, response) start = Time.now request_uri = request.params[Merb::Const::REQUEST_URI] request_uri.sub!(path_prefix, '') if path_prefix route = route_path(request_uri) allowed = route.delete(:allowed) rest = route.delete(:rest) namespace = route.delete(:namespace) cont = namespace ? "#{namespace}/#{route[:controller]}" : route[:controller] klass = resolve_controller(cont) controller = klass.build(request.body, request.params, route, response) if rest method = controller.request.method if allowed.keys.include?(method) && action = allowed[method] controller.params[:action] = action else raise Merb::HTTPMethodNotAllowed.new(method, allowed) end else action = route[:action] end controller._benchmarks[:setup_time] = Time.now - start if @@use_mutex @@mutex.synchronize { controller.dispatch(action) } else controller.dispatch(action) end [controller, action] end def route_path(path) path = path.sub(/\/+/, '/').sub(/\?.*$/, '') path = path[0..-2] if (path[-1] == ?/) && path.size > 1 Merb::Router.match(path) end # Take a controller class name string and reload or require the right # controller file then CamelCase it and return the class object. def resolve_controller(controller_name) segments = controller_name.split('/').map{|s| s.snake_case} path = "#{DIST_ROOT}/app/controllers/#{controller_name}.rb" cnt = segments.map{|s| s.camel_case }.join('::') if !File.exist?(path) raise "Bad controller! #{cnt}" end unless $TESTING begin if MERB_ENV == 'development' Object.send(:remove_const, cnt) rescue nil load(path) end return Object.full_const_get(cnt) rescue RuntimeError warn "Error getting instance of '#{controller_name.camel_case}': #{$!}" raise $! end end end # end class << self end end