Skip to content

Commit

Permalink
Allow JSON and IO in the same payload
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyisr committed Aug 30, 2019
1 parent f4ae96e commit 904693a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
17 changes: 16 additions & 1 deletion lib/faraday/request/multipart.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def has_multipart?(obj) # rubocop:disable Naming/PredicateName
def create_multipart(env, params)
boundary = env.request.boundary
parts = process_params(params) do |key, value|
Faraday::Parts::Part.new(boundary, key, value)
part(boundary, key, value)
end
parts << Faraday::Parts::EpiloguePart.new(boundary)

Expand All @@ -61,6 +61,21 @@ def create_multipart(env, params)
body
end

def part(boundary, key, value)
if json?(value)
header = { 'Content-Type' => 'application/json' }
Faraday::Parts::Part.new(boundary, key, value, header)
else
Faraday::Parts::Part.new(boundary, key, value)
end
end

def json?(value)
JSON.parse(value)
rescue JSON::ParserError => e
false
end

# @return [String]
def unique_boundary
"#{DEFAULT_BOUNDARY_PREFIX}-#{SecureRandom.hex}"
Expand Down
39 changes: 39 additions & 0 deletions spec/faraday/request/multipart_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,45 @@
end
end

context 'when providing json and IO content in the same payload' do
let(:io_content) { StringIO.new('io-content') }
let(:json_content) do
{
b: 1,
c: 2
}.to_json
end

let(:payload) do
{
json_content: json_content,
io_content: Faraday::UploadIO.new(io_content, 'application/pdf')
}
end

it_behaves_like 'a multipart request'

it 'forms a multipart request' do
response = conn.post('/echo', payload)

boundary = parse_multipart_boundary(response.headers['Content-Type'])
result = parse_multipart(boundary, response.body)
expect(result[:errors]).to be_empty

part_json, body_json = result.part('json_content')
expect(part_json).to_not be_nil
expect(part_json.mime).to eq('application/json')
expect(part_json.filename).to be_nil
expect(body_json).to eq(json_content)

part_io, body_io = result.part('io_content')
expect(part_io).to_not be_nil
expect(part_io.mime).to eq('application/pdf')
expect(part_io.filename).to eq('local.path')
expect(body_io).to eq(io_content.string)
end
end

context 'when multipart objects in array param' do
let(:payload) do
{
Expand Down

0 comments on commit 904693a

Please sign in to comment.