async-http-faraday icon indicating copy to clipboard operation
async-http-faraday copied to clipboard

Basic GET request errors with "Protocol::HTTP1::InvalidRequest" and "Protocol::HTTP2::StreamError: Stream closed!"

Open ric2b opened this issue 7 months ago • 4 comments

I've been trying to use async-http-faraday and I'm struggling to get it to work, even with the simplest request I can think of: a GET request to example.com.

I made a dedicated reproduction repo here, the rspec test file is here.

You can clone the repo and run the following to see the test results:

bundle install
bundle exec rspec

In summary, it shows that:

  • Faraday with the default Net::HTTP adapter works fine with webmock or with real requests
  • Faraday with the async-http adapter fails both with webmock or with real requests
    • with webmock I get a Protocol::HTTP1::InvalidRequest error
    • with a real request I get a Protocol::HTTP2::StreamError: Stream closed! error
  • Using async-http by itself (without Faraday) it works both with a real request or with webmock, although with the real request I get a warning about Closing resource while still in use!

ric2b avatar Nov 21 '23 15:11 ric2b

Nevermind, I completely missed that you're supposed to pass the url or domain to Faraday#new, not to Faraday::Connection#get.

Somehow that works for the default adapter but not for the async-http adapter.

ric2b avatar Nov 21 '23 17:11 ric2b

After looking at my original application code I noticed that I was not using Faraday::Connection#get but Faraday::Connection#run_request, which takes a url as the second parameter, not a path. So it seems like async-http-faraday is not handling that use case correctly while Faraday's default adapter does (the default adapter also seems to deal well with the usage of get(url), although that does seem to be out of spec)

ric2b avatar Nov 21 '23 18:11 ric2b

What do you think we should do here to solve the problem?

ioquatix avatar Nov 21 '23 19:11 ioquatix

@ioquatix

I'm not completely sure yet but I think the issue is that the async-http adapter has no default path, a url like https://example.com leads to it sending "GET HTTP/1.1" (bad request) while https://example.com/ (difference is the trailing slash) sends a valid "GET / HTTP/1.1" request as expected.

For example:

connection = Faraday.new { |faraday| faraday.adapter :async_http }

# BAD
connection.get('https://example.com')
connection.run_request(:get, 'https://example.com', nil, nil)

# GOOD
connection.get('https://example.com/') # Note the trailing slash
connection.run_request(:get, 'https://example.com/', nil, nil)

ric2b avatar Nov 21 '23 21:11 ric2b