From a95077fd790e32ff576041dba0cb5dedcafc507b Mon Sep 17 00:00:00 2001 From: Tim Craft Date: Mon, 1 Apr 2024 11:11:03 +0100 Subject: [PATCH] Support parsing multiple files for one form field --- lib/rack/query_parser.rb | 6 ++++++ test/multipart/multiple_files | 16 ++++++++++++++++ test/spec_multipart.rb | 12 ++++++++++++ test/spec_utils.rb | 2 +- 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test/multipart/multiple_files diff --git a/lib/rack/query_parser.rb b/lib/rack/query_parser.rb index 28cbce18f..fff499da8 100644 --- a/lib/rack/query_parser.rb +++ b/lib/rack/query_parser.rb @@ -132,6 +132,12 @@ def normalize_params(params, name, v, _depth=nil) if after == '' if k == '[]' && depth != 0 return [v] + elsif !params[k].nil? && !v.nil? && depth == 0 + if params[k].is_a?(Array) + params[k] << v + else + params[k] = [params[k], v] + end else params[k] = v end diff --git a/test/multipart/multiple_files b/test/multipart/multiple_files new file mode 100644 index 000000000..299a08ad0 --- /dev/null +++ b/test/multipart/multiple_files @@ -0,0 +1,16 @@ +--AaB03x +content-disposition: form-data; name="files"; filename="file1.txt" +content-type: text/plain + +foo +--AaB03x +content-disposition: form-data; name="files"; filename="file2.txt" +content-type: text/plain + +bar +--AaB03x +content-disposition: form-data; name="files"; filename="file3.txt" +content-type: text/plain + +quux +--AaB03x-- diff --git a/test/spec_multipart.rb b/test/spec_multipart.rb index 53d8b4d66..34a2bf45b 100644 --- a/test/spec_multipart.rb +++ b/test/spec_multipart.rb @@ -518,6 +518,18 @@ def initialize(*) params["files"].size.must_equal 252 end + it "parses multiple files with same name" do + env = Rack::MockRequest.env_for("/", multipart_fixture(:multiple_files)) + params = Rack::Multipart.parse_multipart(env) + params["files"].must_be_instance_of Array + params["files"][0][:filename].must_equal "file1.txt" + params["files"][0][:tempfile].read.must_equal "foo" + params["files"][1][:filename].must_equal "file2.txt" + params["files"][1][:tempfile].read.must_equal "bar" + params["files"][2][:filename].must_equal "file3.txt" + params["files"][2][:tempfile].read.must_equal "quux" + end + it "parses IE multipart upload and cleans up the filename" do env = Rack::MockRequest.env_for("/", multipart_fixture(:ie)) params = Rack::Multipart.parse_multipart(env) diff --git a/test/spec_utils.rb b/test/spec_utils.rb index 4111bdb84..37d9ec460 100644 --- a/test/spec_utils.rb +++ b/test/spec_utils.rb @@ -150,7 +150,7 @@ def assert_nested_query(exp, act) must_equal "foo" => "\"bar\"" Rack::Utils.parse_nested_query("foo=bar&foo=quux"). - must_equal "foo" => "quux" + must_equal "foo" => ["bar", "quux"] Rack::Utils.parse_nested_query("foo&foo="). must_equal "foo" => "" Rack::Utils.parse_nested_query("foo=1&bar=2").