Improve dispatcher failsafe responses. Beef up compatibility with Mongrel's CGI wrapper.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6307 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
8f94cc5cb4
commit
f1e08b351d
|
@ -39,7 +39,7 @@ class Dispatcher
|
|||
controller.process(request, response).out(output)
|
||||
end
|
||||
rescue Exception => exception # errors from CGI dispatch
|
||||
failsafe_response(output, '500 Internal Server Error', exception) do
|
||||
failsafe_response(cgi, output, '500 Internal Server Error', exception) do
|
||||
controller ||= ApplicationController rescue LoadError nil
|
||||
controller ||= ActionController::Base
|
||||
controller.process_with_exception(request, response, exception).out(output)
|
||||
|
@ -90,12 +90,12 @@ class Dispatcher
|
|||
attr_accessor_with_default :preparation_callbacks, []
|
||||
attr_accessor_with_default :preparation_callbacks_run, false
|
||||
alias_method :preparation_callbacks_run?, :preparation_callbacks_run
|
||||
|
||||
|
||||
# CGI.new plus exception handling. CGI#read_multipart raises EOFError
|
||||
# if body.empty? or body.size != Content-Length and raises ArgumentError
|
||||
# if Content-Length is non-integer.
|
||||
def new_cgi(output)
|
||||
failsafe_response(output, '400 Bad Request') { CGI.new }
|
||||
failsafe_response(nil, output, '400 Bad Request') { CGI.new }
|
||||
end
|
||||
|
||||
def prepare_application
|
||||
|
@ -131,34 +131,59 @@ class Dispatcher
|
|||
end
|
||||
|
||||
# If the block raises, send status code as a last-ditch response.
|
||||
def failsafe_response(output, status, exception = nil)
|
||||
def failsafe_response(cgi, fallback_output, status, exception = nil)
|
||||
yield
|
||||
rescue Exception # errors from executed block
|
||||
rescue Exception
|
||||
begin
|
||||
output.write "Status: #{status}\r\n"
|
||||
|
||||
if exception
|
||||
message = exception.to_s + "\r\n" + exception.backtrace.join("\r\n")
|
||||
error_path = File.join(RAILS_ROOT, 'public', '500.html')
|
||||
log_failsafe_exception(cgi, status, exception)
|
||||
|
||||
if defined?(RAILS_DEFAULT_LOGGER) && !RAILS_DEFAULT_LOGGER.nil?
|
||||
RAILS_DEFAULT_LOGGER.fatal(message)
|
||||
body = failsafe_response_body(status)
|
||||
if cgi
|
||||
head = { 'status' => status, 'type' => 'text/html' }
|
||||
|
||||
output.write "Content-Type: text/html\r\n\r\n"
|
||||
|
||||
if File.exists?(error_path)
|
||||
output.write(IO.read(error_path))
|
||||
else
|
||||
output.write("<html><body><h1>Application error (Rails)</h1></body></html>")
|
||||
end
|
||||
# FIXME: using CGI differently than CGIResponse does breaks
|
||||
# the Mongrel CGI wrapper.
|
||||
if defined?(Mongrel) && cgi.is_a?(Mongrel::CGIWrapper)
|
||||
# FIXME: set a dummy cookie so the Mongrel CGI wrapper will
|
||||
# also consider @output_cookies (used for session cookies.)
|
||||
head['cookie'] = []
|
||||
cgi.header(head)
|
||||
fallback_output << body
|
||||
else
|
||||
output.write "Content-Type: text/plain\r\n\r\n"
|
||||
output.write(message)
|
||||
cgi.out(head) { body }
|
||||
end
|
||||
else
|
||||
fallback_output.write "Status: #{status}\r\nContent-Type: text/html\r\n\r\n#{body}"
|
||||
end
|
||||
nil
|
||||
rescue Exception # Logger or IO errors
|
||||
end
|
||||
end
|
||||
|
||||
def failsafe_response_body(status)
|
||||
error_path = "#{RAILS_ROOT}/public/#{status[0..3]}.html"
|
||||
|
||||
if File.exists?(error_path)
|
||||
File.read(error_path)
|
||||
else
|
||||
"<html><body><h1>#{status}</h1></body></html>"
|
||||
end
|
||||
end
|
||||
|
||||
def log_failsafe_exception(cgi, status, exception)
|
||||
fell_back = cgi ? 'has cgi' : 'no cgi, fallback ouput'
|
||||
message = "DISPATCHER FAILSAFE RESPONSE (#{fell_back}) #{Time.now}\n Status: #{status}\n"
|
||||
message << " #{exception}\n #{exception.backtrace.join("\n ")}" if exception
|
||||
failsafe_logger.fatal message
|
||||
end
|
||||
|
||||
def failsafe_logger
|
||||
if defined?(RAILS_DEFAULT_LOGGER) && !RAILS_DEFAULT_LOGGER.nil?
|
||||
RAILS_DEFAULT_LOGGER
|
||||
else
|
||||
Logger.new($stderr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue