Bug #12642


Net::HTTP populates host header incorrectly when using an IPv6 Address

Added by dcorbin (David Corbin) over 6 years ago. Updated over 5 years ago.

Target version:


When sending a request, the client code adds a "Host" header. It does the by taking the given address, appending a colon, and then appending the port. This creates a fragment of a URL such as "". However, when instead of "", the address is an IPv6 address is given (such as 8383:3223::1333:DE12), simply appending a colon is not adequate. It yields 8383:3223::1333:DE12:80, which is hard to parse mess.

RFC3986 stipulates that the host should be surrounded by square brackets, which would have the Host header as: [8383:3223::1333:DE12]:80.


ipv6_test.rb (1.17 KB) ipv6_test.rb test script andy (Andy Brody), 03/14/2017 11:04 PM

Updated by andy (Andy Brody) almost 6 years ago

  • File ipv6_test.rb added

Updated by andy (Andy Brody) almost 6 years ago

Missing brackets from Host header for IPv6 addresses

This is a regression from Ruby 2.1. The bug appears to have been introduced in ruby 2.2.0 by this commit:

The change was added in response to this bug:

Attached is a test script demonstrating the bug "ipv6_test.rb".

Correct behavior (present in 2.0 from 2.0.0-p643 onward and in 2.1 from 2.1.6 onward) for sending a request to http://[::1]:8080

Host: [::1]:8080

Incorrect behavior (present in 2.2.0 through trunk)

Host: ::1:8080

See also

I've added tests for rest-client that show the affected Ruby versions. Net::HTTP support for IPv6 URIs was broken in 2.0 before 2.0.0-p643 and 2.1 before 2.1.6, so there is a narrow window of versions that work.

Full test output is here:

Broken handling of explicit IPv6 Host header

There is a separate bug that makes it impossible to explicitly set an IPv6 host header in affected ruby versions. Because Net::HTTP slices the end of the provided Host header after the first :, an IPv6 Host header will be rendered invalid.

If you attempt to set req['Host'] = '[::1]:8080', it will be rendered as [ due to

$ ruby ipv6_test.rb --set-host
/versions/2.3.1/lib/ruby/2.3.0/uri/generic.rb:595:in `check_host': bad component(expected host component): [ (URI::InvalidComponentError)
	from /versions/2.3.1/lib/ruby/2.3.0/uri/generic.rb:636:in `host='
	from /versions/2.3.1/lib/ruby/2.3.0/net/http/generic_request.rb:151:in `update_uri'
	from /versions/2.3.1/lib/ruby/2.3.0/net/http.rb:1493:in `begin_transport'
	from /versions/2.3.1/lib/ruby/2.3.0/net/http.rb:1433:in `transport_request'
	from /versions/2.3.1/lib/ruby/2.3.0/net/http.rb:1407:in `request'
	from ipv6_test.rb:42:in `block in <main>'
	from /versions/2.3.1/lib/ruby/2.3.0/net/http.rb:853:in `start'
Actions #3

Updated by andy (Andy Brody) almost 6 years ago

  • File deleted (ipv6_test.rb)

Updated by naruse (Yui NARUSE) almost 6 years ago

  • Assignee set to naruse (Yui NARUSE)
Actions #5

Updated by shyouhei (Shyouhei Urabe) over 5 years ago

  • Status changed from Open to Assigned

Updated by anuraguniyal (anurag uniyal) over 5 years ago

Is there a workaround for this? How should we connect to ipv6 servers?

Updated by anuraguniyal (anurag uniyal) over 5 years ago

Below monkey patching code works for me. Is there a better way?

module MonkeyPatch
  module Net
    module HTTP

module MonkeyPatch::Net::HTTP
  # workaround for
  # Ruby does not pass Host header with brackets if host is ipv6 address
  def addr_port
    addr = address()
    # if it is ipv6 add brackets around it
    if addr =~ Resolv::IPv6::Regex
      addr = "[#{addr}]"
    if use_ssl?
      addr + (port == Net::HTTP.https_default_port ? '' : ":#{port()}")
      addr + (port == Net::HTTP.http_default_port ? '' : ":#{port()}")

Actions #8

Updated by naruse (Yui NARUSE) over 5 years ago

  • Status changed from Assigned to Closed

Applied in changeset trunk|r60455.

Host header should add branckets to IPv6 address [Bug #12642]


Also available in: Atom PDF