Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct handling of body object. #33

Merged
merged 1 commit into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading