aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/test/dispatch/request/multipart_params_parsing_test.rb')
-rw-r--r--actionpack/test/dispatch/request/multipart_params_parsing_test.rb202
1 files changed, 202 insertions, 0 deletions
diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
new file mode 100644
index 0000000000..da8233c074
--- /dev/null
+++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb
@@ -0,0 +1,202 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+class MultipartParamsParsingTest < ActionDispatch::IntegrationTest
+ class TestController < ActionController::Base
+ class << self
+ attr_accessor :last_request_parameters, :last_parameters
+ end
+
+ def parse
+ self.class.last_request_parameters = begin
+ request.request_parameters
+ rescue EOFError
+ {}
+ end
+ self.class.last_parameters = request.parameters
+ head :ok
+ end
+
+ def read
+ render plain: "File: #{params[:uploaded_data].read}"
+ end
+ end
+
+ FIXTURE_PATH = File.expand_path("../../fixtures/multipart", __dir__)
+
+ def teardown
+ TestController.last_request_parameters = nil
+ end
+
+ test "parses single parameter" do
+ assert_equal({ "foo" => "bar" }, parse_multipart("single_parameter"))
+ end
+
+ test "parses bracketed parameters" do
+ assert_equal({ "foo" => { "baz" => "bar" } }, parse_multipart("bracketed_param"))
+ end
+
+ test "parse single utf8 parameter" do
+ assert_equal({ "Iñtërnâtiônàlizætiøn_name" => "Iñtërnâtiônàlizætiøn_value" },
+ parse_multipart("single_utf8_param"), "request.request_parameters")
+ assert_equal(
+ "Iñtërnâtiônàlizætiøn_value",
+ TestController.last_parameters["Iñtërnâtiônàlizætiøn_name"], "request.parameters")
+ end
+
+ test "parse bracketed utf8 parameter" do
+ assert_equal({ "Iñtërnâtiônàlizætiøn_name" => {
+ "Iñtërnâtiônàlizætiøn_nested_name" => "Iñtërnâtiônàlizætiøn_value" } },
+ parse_multipart("bracketed_utf8_param"), "request.request_parameters")
+ assert_equal(
+ { "Iñtërnâtiônàlizætiøn_nested_name" => "Iñtërnâtiônàlizætiøn_value" },
+ TestController.last_parameters["Iñtërnâtiônàlizætiøn_name"], "request.parameters")
+ end
+
+ test "parses text file" do
+ params = parse_multipart("text_file")
+ assert_equal %w(file foo), params.keys.sort
+ assert_equal "bar", params["foo"]
+
+ file = params["file"]
+ assert_equal "file.txt", file.original_filename
+ assert_equal "text/plain", file.content_type
+ assert_equal "contents", file.read
+ end
+
+ test "parses utf8 filename with percent character" do
+ params = parse_multipart("utf8_filename")
+ assert_equal %w(file foo), params.keys.sort
+ assert_equal "bar", params["foo"]
+
+ file = params["file"]
+ assert_equal "ファイル%名.txt", file.original_filename
+ assert_equal "text/plain", file.content_type
+ assert_equal "contents", file.read
+ end
+
+ test "parses boundary problem file" do
+ params = parse_multipart("boundary_problem_file")
+ assert_equal %w(file foo), params.keys.sort
+
+ file = params["file"]
+ foo = params["foo"]
+
+ assert_equal "file.txt", file.original_filename
+ assert_equal "text/plain", file.content_type
+
+ assert_equal "bar", foo
+ end
+
+ test "parses large text file" do
+ params = parse_multipart("large_text_file")
+ assert_equal %w(file foo), params.keys.sort
+ assert_equal "bar", params["foo"]
+
+ file = params["file"]
+
+ assert_equal "file.txt", file.original_filename
+ assert_equal "text/plain", file.content_type
+ assert_equal(("a" * 20480), file.read)
+ end
+
+ test "parses binary file" do
+ params = parse_multipart("binary_file")
+ assert_equal %w(file flowers foo), params.keys.sort
+ assert_equal "bar", params["foo"]
+
+ file = params["file"]
+ assert_equal "file.csv", file.original_filename
+ assert_nil file.content_type
+ assert_equal "contents", file.read
+
+ file = params["flowers"]
+ assert_equal "flowers.jpg", file.original_filename
+ assert_equal "image/jpeg", file.content_type
+ assert_equal 19512, file.size
+ end
+
+ test "parses mixed files" do
+ params = parse_multipart("mixed_files")
+ assert_equal %w(files foo), params.keys.sort
+ assert_equal "bar", params["foo"]
+
+ # Rack doesn't handle multipart/mixed for us.
+ files = params["files"]
+ assert_equal 19756, files.bytesize
+ end
+
+ test "does not create tempfile if no file has been selected" do
+ params = parse_multipart("none")
+ assert_equal %w(submit-name), params.keys.sort
+ assert_equal "Larry", params["submit-name"]
+ assert_nil params["files"]
+ end
+
+ test "parses empty upload file" do
+ params = parse_multipart("empty")
+ assert_equal %w(files submit-name), params.keys.sort
+ assert_equal "Larry", params["submit-name"]
+ assert params["files"]
+ assert_equal "", params["files"].read
+ end
+
+ test "uploads and reads binary file" do
+ with_test_routing do
+ fixture = FIXTURE_PATH + "/ruby_on_rails.jpg"
+ params = { uploaded_data: fixture_file_upload(fixture, "image/jpg") }
+ post "/read", params: params
+ end
+ end
+
+ test "uploads and reads file" do
+ with_test_routing do
+ post "/read", params: { uploaded_data: fixture_file_upload(FIXTURE_PATH + "/hello.txt", "text/plain") }
+ assert_equal "File: Hello", response.body
+ end
+ end
+
+ # This can happen in Internet Explorer when redirecting after multipart form submit.
+ test "does not raise EOFError on GET request with multipart content-type" do
+ with_routing do |set|
+ set.draw do
+ ActiveSupport::Deprecation.silence do
+ get ":action", controller: "multipart_params_parsing_test/test"
+ end
+ end
+ headers = { "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x" }
+ get "/parse", headers: headers
+ assert_response :ok
+ end
+ end
+
+ private
+ def fixture(name)
+ File.open(File.join(FIXTURE_PATH, name), "rb") do |file|
+ { "rack.input" => file.read,
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
+ "CONTENT_LENGTH" => file.stat.size.to_s }
+ end
+ end
+
+ def parse_multipart(name)
+ with_test_routing do
+ headers = fixture(name)
+ post "/parse", params: headers.delete("rack.input"), headers: headers
+ assert_response :ok
+ TestController.last_request_parameters
+ end
+ end
+
+ def with_test_routing
+ with_routing do |set|
+ set.draw do
+ ActiveSupport::Deprecation.silence do
+ post ":action", controller: "multipart_params_parsing_test/test"
+ end
+ end
+ yield
+ end
+ end
+end