excon/excon — pull request #449 by jrafanie (2014-12-05 22:36:44+00:00)
Title: Unwrap ipv6 addresses for use with sockets

Literal IPv6 addresses, such as ::1, have a few rules in regards to their use:
* They must be wrapped in [], such as [::1] when used in URL/URIs and in the Host Request header field.
See: https://bugzilla.mozilla.org/show_bug.cgi?id=45891
TL;DR:
RFC 2617 says Host = host : port
RFC 2732 says, host must be wrapped in [], so, we need **Host = [::1]:9292**

* They must be unwrapped, "::1", when passed to sockets.
See: https://github.com/ruby/ruby/blob/e70210cad637c5be31709f65c0eb9603f8ec18a1/lib/uri/generic.rb#L234

#### To illustrate the problem that this pull request fixes:
```ruby
irb(main):001:0> require 'excon'
=> true
irb(main):002:0> Excon.new("http://[::1]:9292").request
Excon::Errors::SocketError: getaddrinfo: nodename nor servname provided, or not known (SocketError)
...
```

I get a getaddrinfo error **because Excon is sending [::1]** directly to the socket layer.

#### Using this PR's fixed excon:

```ruby
$ bundle console
Resolving dependencies...
irb(main):001:0> require 'excon'
=> false

irb(main):002:0> Excon.new("http://[::1]:9292").request
Excon::Errors::SocketError: Connection refused - connect(2) (Errno::ECONNREFUSED)
...
```
**Note 1**: Instead of getaddrinfo error, I get connection refused because I have nothing listening.

**Note 2**: I don't like borrowing from ruby's URI class, I'd rather let URI handle this...

**Note 3**: It's unfortunate I have to unwrap each time we pass to the socket but I couldn't find an easy way to handle the request host header separately from the socket host value. The same data/datum is used for both. In other libraries, you can keep things as URI objects and call hostname for unwrapped (`::1`) and host for wrapped (`[::1]`). As mentioned above in note 2, this is desirable but unfortunately, excon would have to change in many places to keep the host/port/scheme/path, etc. in URI format and extract out the parts you need when needed. If we did do this though, we could then call URI#hostname where I'm currently unwrapping the [] for use in the socket code.

See also:
https://github.com/nahi/httpclient/pull/176
https://github.com/rest-client/rest-client/pull/332
https://github.com/rest-client/rest-client/pull/333