ostinelli / net-http2

NetHttp2 is an HTTP/2 client for Ruby.
MIT License
141 stars 31 forks source link

Using HTTPS results in error #54

Open vanso-hubsi opened 2 months ago

vanso-hubsi commented 2 months ago

Hi! I'm having weird basic issues using this library. When I do the same simple test as in the example it works:

>> require 'net-http2'
=> true
>> client = NetHttp2::Client.new("http://nghttp2.org")
=> #<NetHttp2::Client:0x0000000107398020 @uri=#<URI::HTTP http://nghttp2.org>, @connect_timeout=60, @ssl_context=#<OpenSSL::SSL::SSLContext:0x000000011f216248 @npn_protocols=["h2"], @npn_select_cb=#<Proc:0x000000011f215ff0@[…]/net-http2-0.18.5/lib/net-http2/client.rb:190 (lambda)>>, @is_ssl=false, @mutex=#<Thread::Mutex:0x000000011f215f00>, @h2=nil, @socket=nil, @socket_thread=nil, @first_data_sent=false, @streams={}>
>> response = client.call(:get, '/')
=> #<NetHttp2::Response:0x000000011f2bd548 @headers={":status"=>"200", "date"=>"Mon, 23 Sep 2024 09:13:12 GMT", "content-type"=>"text/html", "last-modified"=>"Tue, 27 Aug 2024 09:49:44 GMT", […]

Doing same with HTTPS results in an error, though:

>> require 'net-http2'
=> true
>> client = NetHttp2::Client.new("https://nghttp2.org")
=> #<NetHttp2::Client:0x0000000141d86048 @uri=#<URI::HTTPS https://nghttp2.org>, @connect_timeout=60, @ssl_context=#<OpenSSL::SSL::SSLContext:0x0000000141d855f8 @npn_protocols=["h2"], @npn_select_cb=#<Proc:0x0000000141d85198@[…]/net-http2-0.18.5/lib/net-http2/client.rb:190 (lambda)>>, @is_ssl=true, @mutex=#<Thread::Mutex:0x0000000141d84f40>, @h2=nil, @socket=nil, @socket_thread=nil, @first_data_sent=false, @streams={}>
>> response = client.call(:get, '/')
#<Thread:0x0000000141dbd160@[…]/net-http2-0.18.5/lib/net-http2/client.rb:112 run> terminated with exception (report_on_exception is true):
[…]/net-http2-0.18.5/lib/net-http2/client.rb:134:in `callback_or_raise': Socket was remotely closed (SocketError)
        from […]/net-http2-0.18.5/lib/net-http2/client.rb:119:in `rescue in block (2 levels) in ensure_open'
        from […]/net-http2-0.18.5/lib/net-http2/client.rb:113:in `block (2 levels) in ensure_open'
[…]/openssl/buffering.rb:182:in `sysread_nonblock': end of file reached (EOFError)
        from […]/openssl/buffering.rb:182:in `read_nonblock'
        from […]/net-http2-0.18.5/lib/net-http2/client.rb:145:in `block in socket_loop'
        from […]/net-http2-0.18.5/lib/net-http2/client.rb:142:in `loop'
        from […]/net-http2-0.18.5/lib/net-http2/client.rb:142:in `socket_loop'
        from […]/net-http2-0.18.5/lib/net-http2/client.rb:114:in `block (2 levels) in ensure_open'
Traceback (most recent call last):
        3: from […]/net-http2-0.18.5/lib/net-http2/client.rb:113:in `block (2 levels) in ensure_open'
        2: from […]/net-http2-0.18.5/lib/net-http2/client.rb:119:in `rescue in block (2 levels) in ensure_open'
        1: from […]/net-http2-0.18.5/lib/net-http2/client.rb:134:in `callback_or_raise'
SocketError (Socket was remotely closed)

Same happens for other servers (e.g. https://www.google.com, https://www.amazon.com), while they work fine using "curl --http2 -H 'User-Agent:' -H 'Accept:'" (-H options to remove default headers curl generates to ensure similarity).

I found that the servers actually respond with data, so I injected some debugging into the module at lib/net-http2/client.rb:146:

    def socket_loop
      […]
          data_received = @socket.read_nonblock(1024)
          puts data_received

which reveals that the servers seem to respond in HTTP/1 for some reason:

>> require 'net-http2'
=> true
>> client = NetHttp2::Client.new("https://nghttp2.org")
=> #<NetHttp2::Client:0x0000000151272d90 @uri=#<URI::HTTPS https://nghttp2.org>, @connect_timeout=60, @ssl_context=#<OpenSSL::SSL::SSLContext:0x0000000151272908 @npn_protocols=["h2"], @npn_select_cb=#<Proc:0x0000000151272638@[…]/net-http2-0.18.5/lib/net-http2/client.rb:191 (lambda)>>, @is_ssl=true, @mutex=#<Thread::Mutex:0x0000000151272548>, @h2=nil, @socket=nil, @socket_thread=nil, @first_data_sent=false, @streams={}>
>> response = client.call(:get, '/')
HTTP/1.1 400 Bad Request
Server: nghttpx
Content-Length: 129
Date: Mon, 23 Sep 2024 09:38:43 GMT
Content-Type: text/html; charset=UTF-8
Connection: close

<!DOCTYPE html><html lang="en"><title>400 Bad Request</title><body><h1>400 Bad Request</h1><footer>nghttpx</footer></body></html>
#<Thread:0x0000000151279618@[…]/net-http2-0.18.5/lib/net-http2/client.rb:112 run> terminated with exception (report_on_exception is true):
[…]

I've tried this getting same results on two different MacOS systems using the latest version and different rubies: net-http2 (0.18.5) http-2 (0.12.0) ruby 3.3.5 / 2.6.8

I wonder what the issue could be here, as it looks the module is generally broken - which I can't imagine to be the case. 😄

Thank you!