1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00

Add error handling for bad requests (invalid params)

Requests that raise an error when parameters are parsed will
now respond with a 400 status instead of 500.
This commit is contained in:
Jordan Owens 2016-01-19 19:50:41 -05:00
parent aa4ad35b7c
commit 8f8df53ff2
4 changed files with 54 additions and 5 deletions

View file

@ -73,6 +73,12 @@ module Sinatra
request_method == "UNLINK"
end
def params
super
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
raise BadRequest, "Invalid query parameters: #{e.message}"
end
private
class AcceptEntry
@ -225,6 +231,10 @@ module Sinatra
end
end
class BadRequest < TypeError #:nodoc:
def http_status; 400 end
end
class NotFound < NameError #:nodoc:
def http_status; 404 end
end
@ -593,6 +603,11 @@ module Sinatra
status.between? 500, 599
end
# whether or not the status is set to 400
def bad_request?
status == 400
end
# whether or not the status is set to 404
def not_found?
status == 404
@ -897,9 +912,7 @@ module Sinatra
@env = env
@request = Request.new(env)
@response = Response.new
@params = indifferent_params(@request.params)
template_cache.clear if settings.reload_templates
force_encoding(@params)
@response['Content-Type'] = nil
invoke { dispatch! }
@ -1086,6 +1099,9 @@ module Sinatra
# Dispatch a request with error handling.
def dispatch!
@params = indifferent_params(@request.params)
force_encoding(@params)
invoke do
static! if settings.static? && (request.get? || request.head?)
filter! :before
@ -1121,11 +1137,12 @@ module Sinatra
if server_error?
dump_errors! boom if settings.dump_errors?
raise boom if settings.show_exceptions? and settings.show_exceptions != :after_handler
end
if not_found?
elsif not_found?
headers['X-Cascade'] = 'pass' if settings.x_cascade?
body '<h1>Not Found</h1>'
elsif bad_request?
dump_errors! boom if settings.dump_errors?
halt status
end
res = error_block!(boom.class, boom) || error_block!(status, boom)

View file

@ -26,6 +26,23 @@ class HelpersTest < Minitest::Test
end
end
describe 'bad_request?' do
it 'is true for status == 400' do
status_app(400) { bad_request? }
assert_body 'true'
end
it 'is false for status gt 400' do
status_app(401) { bad_request? }
assert_body 'false'
end
it 'is false for status lt 400' do
status_app(399) { bad_request? }
assert_body 'false'
end
end
describe 'not_found?' do
it 'is true for status == 404' do
status_app(404) { not_found? }

View file

@ -50,6 +50,11 @@ class RequestTest < Minitest::Test
assert_equal({ 'compress' => '0.25' }, request.preferred_type.params)
end
it "raises Sinatra::BadRequest when params contain conflicting types" do
request = Sinatra::Request.new 'QUERY_STRING' => 'foo=&foo[]='
assert_raises(Sinatra::BadRequest) { request.params }
end
it "makes accept types behave like strings" do
request = Sinatra::Request.new('HTTP_ACCEPT' => 'image/jpeg; compress=0.25')
assert request.accept?('image/jpeg')

View file

@ -47,6 +47,16 @@ class RoutingTest < Minitest::Test
assert_equal '', response.body
end
it "400s when request params contain conflicting types" do
mock_app {
get('/foo') { }
}
request = Rack::MockRequest.new(@app)
response = request.request('GET', '/foo?bar=&bar[]=', {})
assert response.bad_request?
end
it "404s when no route satisfies the request" do
mock_app {
get('/foo') { }