From f717a0d6ee2fd915c51593d030e7f1dcdb776c05 Mon Sep 17 00:00:00 2001 From: Jakub Jirutka Date: Sun, 25 Feb 2018 01:19:10 +0100 Subject: [PATCH] Fix multipart to set its header even when other headers are provided `@raw_request.initialize_http_header` resets the headers, so when options contained :headers, it always erased the Content-Type header set for multipart. Now the Content-Type header is always set to "multipart/form-data" when body is detected as multipart. This is IMHO not correct, but that's how the original implementation was designed... --- lib/httparty/request.rb | 18 +++++++++--------- spec/httparty/request_spec.rb | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/httparty/request.rb b/lib/httparty/request.rb index 0b4d2e4..e420f86 100644 --- a/lib/httparty/request.rb +++ b/lib/httparty/request.rb @@ -205,15 +205,6 @@ module HTTParty @raw_request = http_method.new(request_uri(uri)) @raw_request.body_stream = options[:body_stream] if options[:body_stream] - if options[:body] - body = Body.new(options[:body], query_string_normalizer: query_string_normalizer) - if body.multipart? - content_type = "multipart/form-data; boundary=#{body.boundary}" - @raw_request.initialize_http_header('Content-Type' => content_type) - end - @raw_request.body = body.call - end - if options[:headers].respond_to?(:to_hash) headers_hash = options[:headers].to_hash @@ -227,6 +218,15 @@ module HTTParty end end + if options[:body] + body = Body.new(options[:body], query_string_normalizer: query_string_normalizer) + if body.multipart? + content_type = "multipart/form-data; boundary=#{body.boundary}" + @raw_request['Content-Type'] = content_type + end + @raw_request.body = body.call + end + if options[:basic_auth] && send_authorization_header? @raw_request.basic_auth(username, password) @credentials_sent = true diff --git a/spec/httparty/request_spec.rb b/spec/httparty/request_spec.rb index 2e31d87..ca20a27 100644 --- a/spec/httparty/request_spec.rb +++ b/spec/httparty/request_spec.rb @@ -342,6 +342,27 @@ RSpec.describe HTTParty::Request do expect(CGI.unescape(body)).to eq("foo=bar&foo=baz&page=1") end end + + context "when body is multipart" do + it "sets header Content-Type: multipart/form-data; boundary=" do + @request.options[:body] = {file: File.open(File::NULL, 'r')} + @request.send(:setup_raw_request) + headers = @request.instance_variable_get(:@raw_request).each_header.to_a + headers = Hash[*headers.flatten] # Ruby 2.0 doesn't have Array#to_h + expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---}) + end + + context "and header Content-Type is provided" do + it "overwrites the header to: multipart/form-data; boundary=" do + @request.options[:body] = {file: File.open(File::NULL, 'r')} + @request.options[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'} + @request.send(:setup_raw_request) + headers = @request.instance_variable_get(:@raw_request).each_header.to_a + headers = Hash[*headers.flatten] # Ruby 2.0 doesn't have Array#to_h + expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---}) + end + end + end end describe 'http' do