1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Allow rescue from parameter parse errors

[Gannon McGibbon + Josh Cheek]
This commit is contained in:
Gannon McGibbon 2018-10-29 13:45:26 -04:00
parent 0b75743e34
commit 6b3faf8e50
8 changed files with 95 additions and 8 deletions

View file

@ -1,3 +1,13 @@
* Allow rescue from parameter parse errors:
```
rescue_from ActionDispatch::Http::Parameters::ParseError do
head :unauthorized
end
```
*Gannon McGibbon*, *Josh Cheek*
* Reset Capybara sessions if failed system test screenshot raising an exception.
Reset Capybara sessions if `take_failed_screenshot` raise exception

View file

@ -253,7 +253,10 @@ module ActionController
# This will display the wrapped hash in the log file.
request.filtered_parameters.merge! wrapped_filtered_hash
end
super
ensure
# NOTE: Rescues all exceptions so they
# may be caught in ActionController::Rescue.
return super
end
private

View file

@ -41,6 +41,8 @@ module ActionDispatch
# Returns a hash of parameters with all sensitive data replaced.
def filtered_parameters
@filtered_parameters ||= parameter_filter.filter(parameters)
rescue ActionDispatch::Http::Parameters::ParseError
@filtered_parameters = {}
end
# Returns a hash of request.env with all sensitive data replaced.

View file

@ -7,6 +7,11 @@ module ActionDispatch
module MimeNegotiation
extend ActiveSupport::Concern
RESCUABLE_MIME_FORMAT_ERRORS = [
ActionController::BadRequest,
ActionDispatch::Http::Parameters::ParseError,
]
included do
mattr_accessor :ignore_accept_header, default: false
end
@ -59,7 +64,7 @@ module ActionDispatch
fetch_header("action_dispatch.request.formats") do |k|
params_readable = begin
parameters[:format]
rescue ActionController::BadRequest
rescue *RESCUABLE_MIME_FORMAT_ERRORS
false
end

View file

@ -111,13 +111,23 @@ module ActionDispatch
begin
strategy.call(raw_post)
rescue # JSON or Ruby code block errors.
my_logger = logger || ActiveSupport::Logger.new($stderr)
my_logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{raw_post}"
log_parse_error_once
raise ParseError
end
end
def log_parse_error_once
@parse_error_logged ||= begin
parse_logger = logger || ActiveSupport::Logger.new($stderr)
parse_logger.debug <<~MSG.chomp
Error occurred while parsing request parameters.
Contents:
#{raw_post}
MSG
end
end
def params_parsers
ActionDispatch::Request.parameter_parsers
end

View file

@ -383,9 +383,6 @@ module ActionDispatch
end
self.request_parameters = Request::Utils.normalize_encode_params(pr)
end
rescue Http::Parameters::ParseError # one of the parse strategies blew up
self.request_parameters = Request::Utils.normalize_encode_params(super || {})
raise
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
end

View file

@ -0,0 +1,34 @@
# frozen_string_literal: true
require "abstract_unit"
class ParamsParseTest < ActionController::TestCase
class UsersController < ActionController::Base
def create
head :ok
end
end
tests UsersController
def test_parse_error_logged_once
log_output = capture_log_output do
post :create, body: "{", as: :json
end
assert_equal <<~LOG, log_output
Error occurred while parsing request parameters.
Contents:
{
LOG
end
private
def capture_log_output
output = StringIO.new
request.set_header "action_dispatch.logger", ActiveSupport::Logger.new(output)
yield
output.string
end
end

View file

@ -70,6 +70,10 @@ class RescueController < ActionController::Base
render plain: "io error"
end
rescue_from ActionDispatch::Http::Parameters::ParseError do
render plain: "parse error", status: :bad_request
end
before_action(only: :before_action_raises) { raise "umm nice" }
def before_action_raises
@ -130,6 +134,11 @@ class RescueController < ActionController::Base
raise ResourceUnavailableToRescueAsString
end
def arbitrary_action
params
render plain: "arbitrary action"
end
def missing_template
end
@ -306,6 +315,23 @@ class RescueControllerTest < ActionController::TestCase
get :exception_with_no_handler_for_wrapper
assert_response :unprocessable_entity
end
test "can rescue a ParseError" do
capture_log_output do
post :arbitrary_action, body: "{", as: :json
end
assert_response :bad_request
assert_equal "parse error", response.body
end
private
def capture_log_output
output = StringIO.new
request.set_header "action_dispatch.logger", ActiveSupport::Logger.new(output)
yield
output.string
end
end
class RescueTest < ActionDispatch::IntegrationTest