Skip to content

Commit

Permalink
Correct handling of body object. (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Feb 7, 2024
1 parent 645d245 commit 6fb3b29
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 12 deletions.
2 changes: 2 additions & 0 deletions gems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@
group :test do
gem "bake-test"
gem "bake-test-external"

gem "faraday-multipart"
end
22 changes: 21 additions & 1 deletion lib/async/http/faraday/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@
module Async
module HTTP
module Faraday
class BodyWrapper < ::Protocol::HTTP::Body::Readable
def initialize(body, block_size: 4096)
@body = body
@block_size = block_size
end

def close(error = nil)
@body.close if @body.respond_to?(:close)
ensure
super
end

def read
@body.read(@block_size)
end
end

class Adapter < ::Faraday::Adapter
CONNECTION_EXCEPTIONS = [
Errno::EADDRNOTAVAIL,
Expand Down Expand Up @@ -99,7 +116,10 @@ def call(env)
end

if body = env.body
body = Body::Buffered.wrap(body)
# We need to wrap the body in a Readable object so that it can be read in chunks:
# Faraday's body only responds to `#read`.
# body = ::Protocol::HTTP::Body::Buffered.wrap(body)
body = BodyWrapper.new(body)
end

if headers = env.request_headers
Expand Down
35 changes: 24 additions & 11 deletions spec/async/http/faraday/adapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@

require 'async'

require 'faraday'
require 'faraday/multipart'

RSpec.describe Async::HTTP::Faraday::Adapter do
include_context Async::RSpec::Reactor

let(:endpoint) {
let(:endpoint) do
Async::HTTP::Endpoint.parse('http://127.0.0.1:9294')
}
end

def run_server(response = Protocol::HTTP::Response[204], response_delay: nil)
Sync do |task|
Expand Down Expand Up @@ -59,15 +62,14 @@ def get_response(url = endpoint.url, path = '/index', adapter_options: {})
expect(get_response.body).to eq 'Hello World'
end
end

it "client can get responce with respect to Content-Type encoding" do
run_server(Protocol::HTTP::Response[200, {'Content-Type' => 'text/html; charset=utf-8'}, ['こんにちは世界']]) do
body = get_response.body
expect(body.encoding).to eq Encoding::UTF_8
expect(body).to eq 'こんにちは世界'
end
end


it "client can get responce with respect to Content-Type encoding" do
run_server(Protocol::HTTP::Response[200, {'Content-Type' => 'text/html; charset=utf-8'}, ['こんにちは世界']]) do
body = get_response.body
expect(body.encoding).to eq Encoding::UTF_8
expect(body).to eq 'こんにちは世界'
end
end

it "works without top level reactor" do
response = get_response("https://www.google.com", "/search?q=ruby")
Expand Down Expand Up @@ -121,4 +123,15 @@ def get_response(url = endpoint.url, path = '/index', adapter_options: {})
it 'wraps underlying exceptions into Faraday analogs' do
expect { get_response(endpoint.url, '/index') }.to raise_error(Faraday::ConnectionFailed)
end

it 'can use multi-part post body' do
connection = Faraday.new do |builder|
builder.request :multipart
builder.adapter :async_http
end

connection.post("https://httpbin.org/post") do |request|
request.body = { "file" => Faraday::Multipart::FilePart.new(StringIO.new("file content"), "text/plain", "file.txt") }
end
end
end

0 comments on commit 6fb3b29

Please sign in to comment.