diff --git a/sdks/ruby/lib/dropbox-sign/api_client.rb b/sdks/ruby/lib/dropbox-sign/api_client.rb index ad1d84275..bd7e7367e 100644 --- a/sdks/ruby/lib/dropbox-sign/api_client.rb +++ b/sdks/ruby/lib/dropbox-sign/api_client.rb @@ -132,6 +132,22 @@ def build_request(http_method, path, opts = {}) end end + # Workaround for the Typhoeus/libcurl multipart PUT bug. + # libcurl only builds a multipart body via CURLOPT_HTTPPOST/CURLOPT_MIMEPOST, + # which is engaged for POST requests. For PUT it falls back to CURLOPT_UPLOAD + # and silently drops form fields, so the request is sent without a + # `Content-Type: multipart/form-data; boundary=...` header or body. + # We send the request as POST so the multipart body is encoded correctly, + # then use CURLOPT_CUSTOMREQUEST (exposed by Ethon as :customrequest) to + # restore PUT as the on-the-wire HTTP verb. + # See: https://github.com/typhoeus/typhoeus/issues/389 + content_type_header = header_params['Content-Type'] || header_params['content-type'] + if http_method == :put && content_type_header.is_a?(String) && + content_type_header.start_with?('multipart/form-data') + req_opts[:method] = :post + req_opts[:customrequest] = 'PUT' + end + Typhoeus::Request.new(url, req_opts) end diff --git a/sdks/ruby/templates/api_client_typhoeus_partial.mustache b/sdks/ruby/templates/api_client_typhoeus_partial.mustache index f55f98043..116fd36d7 100644 --- a/sdks/ruby/templates/api_client_typhoeus_partial.mustache +++ b/sdks/ruby/templates/api_client_typhoeus_partial.mustache @@ -87,6 +87,22 @@ end end + # Workaround for the Typhoeus/libcurl multipart PUT bug. + # libcurl only builds a multipart body via CURLOPT_HTTPPOST/CURLOPT_MIMEPOST, + # which is engaged for POST requests. For PUT it falls back to CURLOPT_UPLOAD + # and silently drops form fields, so the request is sent without a + # `Content-Type: multipart/form-data; boundary=...` header or body. + # We send the request as POST so the multipart body is encoded correctly, + # then use CURLOPT_CUSTOMREQUEST (exposed by Ethon as :customrequest) to + # restore PUT as the on-the-wire HTTP verb. + # See: https://github.com/typhoeus/typhoeus/issues/389 + content_type_header = header_params['Content-Type'] || header_params['content-type'] + if http_method == :put && content_type_header.is_a?(String) && + content_type_header.start_with?('multipart/form-data') + req_opts[:method] = :post + req_opts[:customrequest] = 'PUT' + end + Typhoeus::Request.new(url, req_opts) end