aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/middleware
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware')
-rw-r--r--actionpack/lib/action_dispatch/middleware/callbacks.rb40
-rw-r--r--actionpack/lib/action_dispatch/middleware/failsafe.rb52
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/show_exceptions.rb87
4 files changed, 84 insertions, 105 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb
new file mode 100644
index 0000000000..0a2b4cf5f7
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb
@@ -0,0 +1,40 @@
+module ActionDispatch
+ class Callbacks
+ include ActiveSupport::Callbacks
+ define_callbacks :prepare, :before, :after
+
+ class << self
+ # DEPRECATED
+ alias_method :prepare_dispatch, :prepare
+ alias_method :before_dispatch, :before
+ alias_method :after_dispatch, :after
+ 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 self.to_prepare(identifier = nil, &block)
+ @prepare_callbacks ||= ActiveSupport::Callbacks::CallbackChain.new
+ callback = ActiveSupport::Callbacks::Callback.new(:prepare, block, :identifier => identifier)
+ @prepare_callbacks.replace_or_append!(callback)
+ end
+
+ def initialize(app, prepare_each_request = false)
+ @app, @prepare_each_request = app, prepare_each_request
+ run_callbacks :prepare
+ end
+
+ def call(env)
+ run_callbacks :before
+ run_callbacks :prepare if @prepare_each_request
+ @app.call(env)
+ ensure
+ run_callbacks :after, :enumerator => :reverse_each
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/middleware/failsafe.rb b/actionpack/lib/action_dispatch/middleware/failsafe.rb
deleted file mode 100644
index 836098482c..0000000000
--- a/actionpack/lib/action_dispatch/middleware/failsafe.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-module ActionDispatch
- class Failsafe
- cattr_accessor :error_file_path
- self.error_file_path = Rails.public_path if defined?(Rails.public_path)
-
- def initialize(app)
- @app = app
- end
-
- def call(env)
- @app.call(env)
- rescue Exception => exception
- # Reraise exception in test environment
- if defined?(Rails) && Rails.env.test?
- raise exception
- else
- failsafe_response(exception)
- end
- end
-
- private
- def failsafe_response(exception)
- log_failsafe_exception(exception)
- [500, {'Content-Type' => 'text/html'}, failsafe_response_body]
- rescue Exception => failsafe_error # Logger or IO errors
- $stderr.puts "Error during failsafe response: #{failsafe_error}"
- end
-
- def failsafe_response_body
- error_path = "#{self.class.error_file_path}/500.html"
- if File.exist?(error_path)
- [File.read(error_path)]
- else
- ["<html><body><h1>500 Internal Server Error</h1></body></html>"]
- end
- end
-
- def log_failsafe_exception(exception)
- message = "/!\\ FAILSAFE /!\\ #{Time.now}\n Status: 500 Internal Server Error\n"
- message << " #{exception}\n #{exception.backtrace.join("\n ")}" if exception
- failsafe_logger.fatal(message)
- end
-
- def failsafe_logger
- if defined?(Rails) && Rails.logger
- Rails.logger
- else
- Logger.new($stderr)
- end
- end
- end
-end
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 58d527a6e7..e83cf9236b 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -32,16 +32,14 @@ module ActionDispatch
when Proc
strategy.call(request.raw_post)
when :xml_simple, :xml_node
- body = request.raw_post
- body.blank? ? {} : Hash.from_xml(body).with_indifferent_access
+ request.body.size == 0 ? {} : Hash.from_xml(request.body).with_indifferent_access
when :yaml
- YAML.load(request.raw_post)
+ YAML.load(request.body)
when :json
- body = request.raw_post
- if body.blank?
+ if request.body.size == 0
{}
else
- data = ActiveSupport::JSON.decode(body)
+ data = ActiveSupport::JSON.decode(request.body)
data = {:_json => data} unless data.is_a?(Hash)
data.with_indifferent_access
end
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 71c1e1b9a9..108355da63 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -4,8 +4,11 @@ module ActionDispatch
LOCALHOST = '127.0.0.1'.freeze
- DEFAULT_RESCUE_RESPONSE = :internal_server_error
- DEFAULT_RESCUE_RESPONSES = {
+ RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates')
+
+ cattr_accessor :rescue_responses
+ @@rescue_responses = Hash.new(:internal_server_error)
+ @@rescue_responses.update({
'ActionController::RoutingError' => :not_found,
'ActionController::UnknownAction' => :not_found,
'ActiveRecord::RecordNotFound' => :not_found,
@@ -15,25 +18,19 @@ module ActionDispatch
'ActionController::MethodNotAllowed' => :method_not_allowed,
'ActionController::NotImplemented' => :not_implemented,
'ActionController::InvalidAuthenticityToken' => :unprocessable_entity
- }
+ })
- DEFAULT_RESCUE_TEMPLATE = 'diagnostics'
- DEFAULT_RESCUE_TEMPLATES = {
+ cattr_accessor :rescue_templates
+ @@rescue_templates = Hash.new('diagnostics')
+ @@rescue_templates.update({
'ActionView::MissingTemplate' => 'missing_template',
'ActionController::RoutingError' => 'routing_error',
'ActionController::UnknownAction' => 'unknown_action',
'ActionView::TemplateError' => 'template_error'
- }
-
- RESCUES_TEMPLATE_PATH = File.join(File.dirname(__FILE__), 'templates')
-
- cattr_accessor :rescue_responses
- @@rescue_responses = Hash.new(DEFAULT_RESCUE_RESPONSE)
- @@rescue_responses.update DEFAULT_RESCUE_RESPONSES
+ })
- cattr_accessor :rescue_templates
- @@rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE)
- @@rescue_templates.update DEFAULT_RESCUE_TEMPLATES
+ FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/html'},
+ ['<html><body><h1>500 Internal Server Error</h1></body></html>']]
def initialize(app, consider_all_requests_local = false)
@app = app
@@ -43,34 +40,35 @@ module ActionDispatch
def call(env)
@app.call(env)
rescue Exception => exception
- raise exception if env['rack.test']
+ raise exception if env['action_dispatch.show_exceptions'] == false
+ render_exception(env, exception)
+ end
- log_error(exception) if logger
+ private
+ def render_exception(env, exception)
+ log_error(exception)
- request = Request.new(env)
- if @consider_all_requests_local || local_request?(request)
- rescue_action_locally(request, exception)
- else
- rescue_action_in_public(exception)
+ request = Request.new(env)
+ if @consider_all_requests_local || local_request?(request)
+ rescue_action_locally(request, exception)
+ else
+ rescue_action_in_public(exception)
+ end
+ rescue Exception => failsafe_error
+ $stderr.puts "Error during failsafe response: #{failsafe_error}"
+ FAILSAFE_RESPONSE
end
- end
- private
# Render detailed diagnostics for unhandled exceptions rescued from
# a controller action.
def rescue_action_locally(request, exception)
template = ActionView::Base.new([RESCUES_TEMPLATE_PATH],
- :template => template,
:request => request,
:exception => exception
)
file = "rescues/#{@@rescue_templates[exception.class.name]}.erb"
body = template.render(:file => file, :layout => 'rescues/layout.erb')
-
- headers = {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}
- status = status_code(exception)
-
- [status, headers, body]
+ render(status_code(exception), body)
end
# Attempts to render a static error page based on the
@@ -86,11 +84,11 @@ module ActionDispatch
path = "#{public_path}/#{status}.html"
if locale_path && File.exist?(locale_path)
- render_public_file(status, locale_path)
+ render(status, File.read(locale_path))
elsif File.exist?(path)
- render_public_file(status, path)
+ render(status, File.read(path))
else
- [status, {'Content-Type' => 'text/html', 'Content-Length' => '0'}, []]
+ render(status, '')
end
end
@@ -99,24 +97,21 @@ module ActionDispatch
request.remote_addr == LOCALHOST && request.remote_ip == LOCALHOST
end
- def render_public_file(status, path)
- body = File.read(path)
- [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, body]
- end
-
def status_code(exception)
interpret_status(@@rescue_responses[exception.class.name]).to_i
end
+ def render(status, body)
+ [status, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, body]
+ end
+
def public_path
- if defined?(Rails)
- Rails.public_path
- else
- "public"
- end
+ defined?(Rails.public_path) ? Rails.public_path : 'public_path'
end
- def log_error(exception) #:doc:
+ def log_error(exception)
+ return unless logger
+
ActiveSupport::Deprecation.silence do
if ActionView::TemplateError === exception
logger.fatal(exception.to_s)
@@ -136,9 +131,7 @@ module ActionDispatch
end
def logger
- if defined?(Rails.logger)
- Rails.logger
- end
+ defined?(Rails.logger) ? Rails.logger : Logger.new($stderr)
end
end
end