Basic GET request errors with "Protocol::HTTP1::InvalidRequest" and "Protocol::HTTP2::StreamError: Stream closed!"
Closed this issue · 6 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
- with webmock I get a
- 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 aboutClosing resource while still in use!
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.
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)
What do you think we should do here to solve the problem?
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)
We now normalize the trailing slash in request path, so that it behaves like other adapters.