module ActionController # Dispatches requests to the appropriate controller and takes care of # reloading the app after each request when Dependencies.load? is true. class Dispatcher @@guard = Mutex.new class << self def define_dispatcher_callbacks(cache_classes) unless cache_classes # Development mode callbacks before_dispatch :reload_application after_dispatch :cleanup_application end # Common callbacks to_prepare :load_application_controller do begin require_dependency 'application' unless defined?(::ApplicationController) rescue LoadError => error raise unless error.message =~ /application\.rb/ end end if defined?(ActiveRecord) before_dispatch { ActiveRecord::Base.verify_active_connections! } to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers } end after_dispatch :flush_logger if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER.respond_to?(:flush) end # Backward-compatible class method takes CGI-specific args. Deprecated # in favor of Dispatcher.new(output, request, response).dispatch. def dispatch(cgi = nil, session_options = CgiRequest::DEFAULT_SESSION_OPTIONS, output = $stdout) new(output).dispatch_cgi(cgi, session_options) end # Add a preparation callback. Preparation callbacks are run before every # request in development mode, and before the first request in production # mode. # # An optional identifier may be supplied for the callback. If provided, # to_prepare may be called again with the same identifier to replace the # existing callback. Passing an identifier is a suggested practice if the # code adding a preparation block may be reloaded. def to_prepare(identifier = nil, &block) @prepare_dispatch_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new callback = ActiveSupport::Callbacks::Callback.new(:prepare_dispatch, block, :identifier => identifier) @prepare_dispatch_callbacks | callback end # If the block raises, send status code as a last-ditch response. def failsafe_response(fallback_output, status, originating_exception = nil) yield rescue Exception => exception begin log_failsafe_exception(status, originating_exception || exception) body = failsafe_response_body(status) fallback_output.write "Status: #{status}\r\nContent-Type: text/html\r\n\r\n#{body}" nil rescue Exception => failsafe_error # Logger or IO errors $stderr.puts "Error during failsafe response: #{failsafe_error}" $stderr.puts "(originally #{originating_exception})" if originating_exception end end private def failsafe_response_body(status) error_path = "#{error_file_path}/#{status.to_s[0..3]}.html" if File.exist?(error_path) File.read(error_path) else "