Closed jeraki closed 1 year ago
For starters:
1: from /redacted/vendor/bundle/ruby/2.6.0/gems/http-3.3.0/lib/http/timeout/null.rb:21:in `initialize'
HTTP::ConnectionError (failed to connect: getaddrinfo: Name or service not known)
The path shows http-3.3.0
, or v3.3.0. The latest release is 5.1.0.
Can you upgrade to the latest release and see if the problem persists?
I can verify that problem persists with http (5.1.0)
Yes, I mentioned this in my original post:
I realize I'm using old versions of both HTTP libraries as well as Rails (working with a large corporate codebase that's very outdated), but I've also tried this with http.rb v5 in a Pry session outside of the context of this project, and the same error occurs.
I apologize if that wasn't more clear.
The backtrace of the error when using v5.1.0 would be helpful.
FWIW it's probably erroring out here:
https://github.com/httprb/http/blob/f4fb336/lib/http/timeout/null.rb#L21
...in which case it would be helpful to instrument it with what's being passed as host
, and figure out what it should be instead, as the ultimate error is:
getaddrinfo: Name or service not known
I checked out the Git repo and tried to make the request from bundle console
to get a stack trace with the latest version:
irb(main):002:0> HTTP.get("http://2606:2800:220:1:248:1893:25c8:1946/foo?bar=baz")
Traceback (most recent call last):
16: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/cli.rb:31:in `dispatch'
15: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
14: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
13: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
12: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/cli.rb:509:in `console'
11: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/cli/console.rb:19:in `run'
10: from (irb):2
9: from /redacted/co/http/lib/http/chainable.rb:20:in `get'
8: from /redacted/co/http/lib/http/chainable.rb:75:in `request'
7: from /redacted/co/http/lib/http/client.rb:31:in `request'
6: from /redacted/co/http/lib/http/client.rb:70:in `perform'
5: from /redacted/co/http/lib/http/client.rb:70:in `new'
4: from /redacted/co/http/lib/http/connection.rb:42:in `initialize'
3: from /redacted/co/http/lib/http/timeout/null.rb:21:in `connect'
2: from /redacted/co/http/lib/http/timeout/null.rb:21:in `open'
1: from /redacted/co/http/lib/http/timeout/null.rb:21:in `initialize'
HTTP::ConnectionError (failed to connect: getaddrinfo: nodename nor servname provided, or not known)
irb(main):003:0>
irb(main):004:0> HTTP::VERSION
=> "5.1.0"
That's with Ruby 2.6.7 (the main application I work on still uses Ruby 2.6). I can try it with a newer version of Ruby if you think that might matter.
I tried modifying the connect
method in lib/http/timeout/null.rb
to this:
def connect(socket_class, host, port, nodelay = false)
p({
socket_class: socket_class,
host: host,
port: port,
nodelay: nodelay,
})
@socket = socket_class.open(host, port)
@socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
end
And then when making the request in bundle console
I see this just before the exception and stack trace:
{:socket_class=>TCPSocket, :host=>"2606:2800:220:1:248:1893:25c8", :port=>1946, :nodelay=>false}
Looks like it's seeing the last section of the address as the port.
Forgot to mention, here's the debug output if I put brackets around the IP address. It correctly identifies the host and port, but still results in the same exception:
irb(main):002:0> HTTP.get("http://[2606:2800:220:1:248:1893:25c8:1946]/foo?bar=baz")
{:socket_class=>TCPSocket, :host=>"[2606:2800:220:1:248:1893:25c8:1946]", :port=>80, :nodelay=>false}
Traceback (most recent call last):
16: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
15: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
14: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
13: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/cli.rb:509:in `console'
12: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/cli/console.rb:19:in `run'
11: from (irb):2
10: from (irb):2:in `rescue in irb_binding'
9: from /redacted/co/http/lib/http/chainable.rb:20:in `get'
8: from /redacted/co/http/lib/http/chainable.rb:75:in `request'
7: from /redacted/co/http/lib/http/client.rb:31:in `request'
6: from /redacted/co/http/lib/http/client.rb:70:in `perform'
5: from /redacted/co/http/lib/http/client.rb:70:in `new'
4: from /redacted/co/http/lib/http/connection.rb:42:in `initialize'
3: from /redacted/co/http/lib/http/timeout/null.rb:27:in `connect'
2: from /redacted/co/http/lib/http/timeout/null.rb:27:in `open'
1: from /redacted/co/http/lib/http/timeout/null.rb:27:in `initialize'
HTTP::ConnectionError (failed to connect: getaddrinfo: nodename nor servname provided, or not known)
I've confirmed in this case that URI#host
returns [2606:2800:220:1:248:1893:25c8:1946]
>> URI.parse("http://[2606:2800:220:1:248:1893:25c8:1946]/foo?bar=baz").host
=> "[2606:2800:220:1:248:1893:25c8:1946]"
So I'm guessing the solution is we need to strip the outer brackets in this case, if the inner address is a valid IPv6 address?
I tried changing the connect
method to strip the brackets (naively, there's probably a safer way) and that gets further but raises a different exception.
Connect:
def connect(socket_class, host, port, nodelay = false)
host = host.gsub(/\[|\]/, "")
@socket = socket_class.open(host, port)
@socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
end
Usage:
irb(main):001:0> HTTP.get("http://[2606:2800:220:1:248:1893:25c8:1946]/foo?bar=baz")
Traceback (most recent call last):
16: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/cli.rb:31:in `dispatch'
15: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
14: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
13: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
12: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/cli.rb:509:in `console'
11: from /redacted/.rbenv/versions/2.6.7/lib/ruby/gems/2.6.0/gems/bundler-2.2.33/lib/bundler/cli/console.rb:19:in `run'
10: from (irb):1
9: from /redacted/co/http/lib/http/chainable.rb:20:in `get'
8: from /redacted/co/http/lib/http/chainable.rb:75:in `request'
7: from /redacted/co/http/lib/http/client.rb:31:in `request'
6: from /redacted/co/http/lib/http/client.rb:70:in `perform'
5: from /redacted/co/http/lib/http/client.rb:70:in `new'
4: from /redacted/co/http/lib/http/connection.rb:42:in `initialize'
3: from /redacted/co/http/lib/http/timeout/null.rb:22:in `connect'
2: from /redacted/co/http/lib/http/timeout/null.rb:22:in `open'
1: from /redacted/co/http/lib/http/timeout/null.rb:22:in `initialize'
HTTP::ConnectionError (failed to connect: No route to host - connect(2) for "2606:2800:220:1:248:1893:25c8:1946" port 80)
This might be an issue with IPv6 support on my local network, though. I notice that I get the same error with curl too:
$ curl -i -v "http://[2606:2800:220:1:248:1893:25c8:1946]/foo?bar=baz"
* Trying 2606:2800:220:1:248:1893:25c8:1946:80...
* Immediate connect fail for 2606:2800:220:1:248:1893:25c8:1946: No route to host
* Closing connection 0
curl: (7) Couldn't connect to server
Stripping the brackets is probably the right solution, although you'd want a regex that matches the outer brackets with an inner capture group for valid IPv6 addresses, which if it matches returns the inner capture group.
If you can test that solution where you have IPv6 connectivity, that'd be great.
Perhaps we could test against ::1
when available?
I tried the above change to connect
by monkey patching the class in a Rails console on the server I usually work from and I was able to successfully make a request to an internal IPv6 address that was previously causing the reported error. So it does look like stripping the brackets is the fix!
Hi @jeraki @tarcieri is there any update on this?
@harshit-splunk I didn't have time to work on my PR for a few weeks, but I just pushed a commit to move it forward. You can follow #731 for updates.
I'm trying to use http.rb to make GET requests to IPv6 addresses and always get the following error:
I've tried with and without brackets around the IP address and the results are the same. (I'd expect the version without brackets to fail, so that by itself isn't a problem. More detail on why I'm even trying a bracket-less version below.)
Interestingly, making a request to the exact same URL with httparty succeeds when using the bracketed form.
Here is a demonstration of what I see using the IPv6 address for example.com (2606:2800:220:1:248:1893:25c8:1946):
http.rb without brackets:
http.rb with brackets:
httparty without brackets:
httparty with brackets:
I realize I'm using old versions of both HTTP libraries as well as Rails (working with a large corporate codebase that's very outdated), but I've also tried this with http.rb v5 in a Pry session outside of the context of this project, and the same error occurs.
Normally I would just use httparty, because it works, but unfortunately I can't because of a bad interaction between httparty and the newrelic_rpm gem. Apparently
Net::HTTP
needs brackets removed from IPv6 addresses, so httparty has some code that intentionally removes the brackets before handing off the request toNet::HTTP
. At this point, New Relic instrumentation hooks into the request, attempts to re-parse the URL using the addressable gem, and raises an exception because it requires brackets around IPv6 addresses. None of this is http.rb's fault, I'm just mentioning it for the context as to why I'm trying use http.rb in the first place. I wanted to try something that doesn't useNet::HTTP
under the hood so that there's no conflict in support for brackets around IPv6 addresses. I see that both http.rb and newrelic_rpm use the addressable gem for URLs, so they should be compatible.Any idea why I'm getting this error from http.rb? I wasn't able to find documentation or issues that specifically mention IPv6 to see examples of how it's supposed to work or how to troubleshoot.
Thank you for your time.