summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2023-01-16 14:04:04 -0800
committerSamuel Williams <samuel.williams@oriontransfer.co.nz>2023-01-17 11:29:01 +1300
commit401ca8248e642a9b3b11895f2957d12d448c5d55 (patch)
tree66f11d318285b8e601a67fd2a67de131eef28751
parentaf9cbb88a3d873c6dabe08554cbb78b9eeb2b8b1 (diff)
downloadrack-401ca8248e642a9b3b11895f2957d12d448c5d55.tar.gz
`Rack::Request#POST` should consistently raise errors. (#2010)
Cache errors that occur when invoking `Rack::Request#POST` so they can be raised again later. * Don't throw exactly the same error - so we have the correct backtrace.
-rw-r--r--lib/rack/constants.rb1
-rw-r--r--lib/rack/request.rb47
-rw-r--r--test/spec_request.rb16
3 files changed, 45 insertions, 19 deletions
diff --git a/lib/rack/constants.rb b/lib/rack/constants.rb
index 6aa9281f..13365935 100644
--- a/lib/rack/constants.rb
+++ b/lib/rack/constants.rb
@@ -55,6 +55,7 @@ module Rack
RACK_REQUEST_FORM_INPUT = 'rack.request.form_input'
RACK_REQUEST_FORM_HASH = 'rack.request.form_hash'
RACK_REQUEST_FORM_VARS = 'rack.request.form_vars'
+ RACK_REQUEST_FORM_ERROR = 'rack.request.form_error'
RACK_REQUEST_COOKIE_HASH = 'rack.request.cookie_hash'
RACK_REQUEST_COOKIE_STRING = 'rack.request.cookie_string'
RACK_REQUEST_QUERY_HASH = 'rack.request.query_hash'
diff --git a/lib/rack/request.rb b/lib/rack/request.rb
index 6641b5fc..40922a21 100644
--- a/lib/rack/request.rb
+++ b/lib/rack/request.rb
@@ -496,26 +496,35 @@ module Rack
# This method support both application/x-www-form-urlencoded and
# multipart/form-data.
def POST
- if get_header(RACK_INPUT).nil?
- raise "Missing rack.input"
- elsif get_header(RACK_REQUEST_FORM_INPUT) == get_header(RACK_INPUT)
- get_header(RACK_REQUEST_FORM_HASH)
- elsif form_data? || parseable_data?
- unless set_header(RACK_REQUEST_FORM_HASH, parse_multipart)
- form_vars = get_header(RACK_INPUT).read
-
- # Fix for Safari Ajax postings that always append \0
- # form_vars.sub!(/\0\z/, '') # performance replacement:
- form_vars.slice!(-1) if form_vars.end_with?("\0")
-
- set_header RACK_REQUEST_FORM_VARS, form_vars
- set_header RACK_REQUEST_FORM_HASH, parse_query(form_vars, '&')
+ if error = get_header(RACK_REQUEST_FORM_ERROR)
+ raise error.class, error.message, cause: error.cause
+ end
+
+ begin
+ if get_header(RACK_INPUT).nil?
+ raise "Missing rack.input"
+ elsif get_header(RACK_REQUEST_FORM_INPUT) == get_header(RACK_INPUT)
+ get_header(RACK_REQUEST_FORM_HASH)
+ elsif form_data? || parseable_data?
+ unless set_header(RACK_REQUEST_FORM_HASH, parse_multipart)
+ form_vars = get_header(RACK_INPUT).read
+
+ # Fix for Safari Ajax postings that always append \0
+ # form_vars.sub!(/\0\z/, '') # performance replacement:
+ form_vars.slice!(-1) if form_vars.end_with?("\0")
+
+ set_header RACK_REQUEST_FORM_VARS, form_vars
+ set_header RACK_REQUEST_FORM_HASH, parse_query(form_vars, '&')
+ end
+ set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
+ get_header RACK_REQUEST_FORM_HASH
+ else
+ set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
+ set_header(RACK_REQUEST_FORM_HASH, {})
end
- set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
- get_header RACK_REQUEST_FORM_HASH
- else
- set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
- set_header(RACK_REQUEST_FORM_HASH, {})
+ rescue => error
+ set_header(RACK_REQUEST_FORM_ERROR, error)
+ raise
end
end
diff --git a/test/spec_request.rb b/test/spec_request.rb
index 750639de..9fed5029 100644
--- a/test/spec_request.rb
+++ b/test/spec_request.rb
@@ -1218,6 +1218,22 @@ class RackRequestTest < Minitest::Spec
req.media_type_params['weird'].must_equal 'lol"'
end
+ it "returns the same error for invalid post inputs" do
+ env = {
+ 'REQUEST_METHOD' => 'POST',
+ 'PATH_INFO' => '/foo',
+ 'rack.input' => StringIO.new('invalid=bar&invalid[foo]=bar'),
+ 'HTTP_CONTENT_TYPE' => "application/x-www-form-urlencoded",
+ }
+
+ 2.times do
+ # The actual exception type here is unimportant - just that it fails.
+ assert_raises(Rack::Utils::ParameterTypeError) do
+ Rack::Request.new(env).POST
+ end
+ end
+ end
+
it "parse with junk before boundary" do
# Adapted from RFC 1867.
input = <<EOF