[Ruby 1.9 - Feature #5180][Open] net/http の接続時に用いる IP アドレスの指定

Issue #5180 has been reported by Yui NARUSE.


Feature #5180: net/http の接続時に用いる IP アドレスの指定
http://redmine.ruby-lang.org/issues/5180

Author: Yui NARUSE
Status: Open
Priority: Normal
Assignee:
Category: lib
Target version:

通常 net/http を使う時は、Net::HTTP.start(“ruby-lang.org”) などとホスト名を使います。
で、Socket がホスト名から IP アドレスを引いて、コネクションが張られます。
普通の人はこれで足りるわけですが、ふつうな人はしばしば DNS で引けない IP アドレスに接続したくなります。
例えば、ホスト名は “ruby-lang.org” としたいが、IP アドレスは 127.0.0.1 とか。

以下のパッチをあてると、
Net::HTTP.start(“ruby-lang.org”, ipaddr: ‘127.0.0.1’)
などとできるようになります。

diff --git a/lib/net/http.rb b/lib/net/http.rb
index 7b9ec4f…6d034e0 100644
— a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -524,7 +524,7 @@ module Net #:nodoc:
# opt :: optional hash
#
# opt sets following values by its accessor.

  • The keys are ca_file, ca_path, cert, cert_store, ciphers,

  • The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers,

    close_on_empty_response, key, open_timeout, read_timeout,

ssl_timeout,
# ssl_version, use_ssl, verify_callback, verify_depth and
verify_mode.
# If you set :use_ssl as true, you can use https and default value
of
@@ -542,6 +542,7 @@ module Net #:nodoc:
port, p_addr, p_port, p_user, p_pass = *arg
port = https_default_port if !port && opt && opt[:use_ssl]
http = new(address, port, p_addr, p_port, p_user, p_pass)

  •  http.ipaddr = opt[:ipaddr] if opt[:ipaddr]
    
     if opt
       if opt[:use_ssl]
    

@@ -575,6 +576,7 @@ module Net #:nodoc:
def initialize(address, port = nil)
@address = address
@port = (port || HTTP.default_port)

  •  @ipaddr = nil
     @curr_http_version = HTTPVersion
     @no_keepalive_server = false
     @close_on_empty_response = false
    

@@ -620,6 +622,17 @@ module Net #:nodoc:
# The port number to connect to.
attr_reader :port

  • The IP address to connect to/used to connect to

  • def ipaddr
  •  started? ?  @socket.io.peeraddr[3] : @ipaddr
    
  • end
  • Set the IP address to connect to

  • def ipaddr=(addr)
  •  raise IOError, "ipaddr value changed, but session already 
    

started" if started?

  •  @ipaddr = addr
    
  • end
  • Number of seconds to wait for the connection to open. Any number

    may be used, including Floats for fractional seconds. If the HTTP

    object cannot open a connection in this many seconds, it raises a

@@ -945,7 +958,7 @@ module Net #:nodoc:
# without proxy

 def conn_address
  •  address()
    
  •  @ipaddr || address()
    

    end

    def conn_port

(08/10/2011 11:46 AM), Yui NARUSE wrote:

例えば、ホスト名は “ruby-lang.org” としたいが、IP アドレスは 127.0.0.1 とか。

/etc/hostsを書け、ではだめですか。名前解決のレイヤーの要件をHTTPで解決するのは筋が悪いでしょう。

2011$BG/(B8$B7n(B10$BF|(B15:05 Yui NARUSE [email protected]:

$BJL$N%f!<%9%1!<%9$H$7$F!“F1$8%[%9%HL>!J$H$$$&$+%I%a%$%sL>!K$r;}$DJ#?t$N%5!<%P72$KBP$7$F!”(B

$B$=$l$>$l$KF0:n3NG’$GDL?.$7$?$$;v$,$"$C$?$s$G$9$,!"$3$N>[email protected]$H0lDj$N%[%9%HL>$rAw$j$D$D(B
$B!"(B

IP $B%"%I%l%9$OLVMe$7$J$$$H$$$1$J$$$N$G!"(B/etc/hosts
[email protected]$H%5!<%P!<[email protected]$1=q$-49$($F;n$9$N$r(B
$B7+$jJV$5$J$$$H$$$1$J$$$N$G$D$i$$$G$9!#(B

resolv-replace $B$_$?$$$K(B TCPSocket.open
$B$r$9$j$+$($k$N$O$$$+$,$G$9$+$M!#(B

$B$3$l$O(B lexcal $B$8$c$J$/$F(B dynamic $B$KJQ$([email protected]$J$!(B

($B$D$^$j(B local rebinding)

Issue #5180 has been updated by Yui NARUSE.

Shyouhei U. wrote:

(08/10/2011 11:46 AM), Yui NARUSE wrote:

例えば、ホスト名は “ruby-lang.org” としたいが、IP アドレスは 127.0.0.1 とか。

/etc/hostsを書け、ではだめですか。名前解決のレイヤーの要件をHTTPで解決するのは筋が悪いでしょう。

127.0.0.1 の例だとそうなんですね。

別のユースケースとして、同じホスト名(というかドメイン名)を持つ複数のサーバ群に対して、
それぞれに動作確認で通信したい事があったんですが、この場合だと一定のホスト名を送りつつ 、
IP アドレスは網羅しないといけないので、/etc/hosts だとサーバーの数だけ書き換えて試すのを
繰り返さないといけないのでつらいです。

Feature #5180: net/http の接続時に用いる IP アドレスの指定
http://redmine.ruby-lang.org/issues/5180

Author: Yui NARUSE
Status: Open
Priority: Normal
Assignee:
Category: lib
Target version:

通常 net/http を使う時は、Net::HTTP.start(“ruby-lang.org”) などとホスト名を使います。
で、Socket がホスト名から IP アドレスを引いて、コネクションが張られます。
普通の人はこれで足りるわけですが、ふつうな人はしばしば DNS で引けない IP アドレスに接続したくなります。
例えば、ホスト名は “ruby-lang.org” としたいが、IP アドレスは 127.0.0.1 とか。

以下のパッチをあてると、
Net::HTTP.start(“ruby-lang.org”, ipaddr: ‘127.0.0.1’)
などとできるようになります。

diff --git a/lib/net/http.rb b/lib/net/http.rb
index 7b9ec4f…6d034e0 100644
— a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -524,7 +524,7 @@ module Net #:nodoc:
# opt :: optional hash
#
# opt sets following values by its accessor.

  • The keys are ca_file, ca_path, cert, cert_store, ciphers,

  • The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers,

    close_on_empty_response, key, open_timeout, read_timeout,

ssl_timeout,
# ssl_version, use_ssl, verify_callback, verify_depth and
verify_mode.
# If you set :use_ssl as true, you can use https and default value
of
@@ -542,6 +542,7 @@ module Net #:nodoc:
port, p_addr, p_port, p_user, p_pass = *arg
port = https_default_port if !port && opt && opt[:use_ssl]
http = new(address, port, p_addr, p_port, p_user, p_pass)

  •  http.ipaddr = opt[:ipaddr] if opt[:ipaddr]
    
     if opt
       if opt[:use_ssl]
    

@@ -575,6 +576,7 @@ module Net #:nodoc:
def initialize(address, port = nil)
@address = address
@port = (port || HTTP.default_port)

  •  @ipaddr = nil
     @curr_http_version = HTTPVersion
     @no_keepalive_server = false
     @close_on_empty_response = false
    

@@ -620,6 +622,17 @@ module Net #:nodoc:
# The port number to connect to.
attr_reader :port

  • The IP address to connect to/used to connect to

  • def ipaddr
  •  started? ?  @socket.io.peeraddr[3] : @ipaddr
    
  • end
  • Set the IP address to connect to

  • def ipaddr=(addr)
  •  raise IOError, "ipaddr value changed, but session already 
    

started" if started?

  •  @ipaddr = addr
    
  • end
  • Number of seconds to wait for the connection to open. Any number

    may be used, including Floats for fractional seconds. If the HTTP

    object cannot open a connection in this many seconds, it raises a

@@ -945,7 +958,7 @@ module Net #:nodoc:
# without proxy

 def conn_address
  •  address()
    
  •  @ipaddr || address()
    

    end

    def conn_port

2011$BG/(B8$B7n(B10$BF|(B15:20 Tanaka A. [email protected]:

2011$BG/(B8$B7n(B10$BF|(B15:05 Yui NARUSE [email protected]:

$BJL$N%f!<%9%1!<%9$H$7$F!“F1$8%[%9%HL>!J$H$$$&$+%I%a%$%sL>!K$r;}$DJ#?t$N%5!<%P72$KBP$7$F!”(B

$B$=$l$>$l$KF0:n3NG’$GDL?.$7$?$$;v$,$"$C$?$s$G$9$,!"$3$N>[email protected]$H0lDj$N%[%9%HL>$rAw$j$D$D(B
$B!"(B

IP $B%"%I%l%9$OLVMe$7$J$$$H$$$1$J$$$N$G!"(B/etc/hosts
[email protected]$H%5!<%P!<[email protected]$1=q$-49$($F;n$9$N$r(B

$B7+$jJV$5$J$$$H$$$1$J$$$N$G$D$i$$$G$9!#(B

resolv-replace $B$_$?$$$K(B TCPSocket.open $B$r$9$j$+$($k$N$O$$$+$,$G$9$+$M!#(B

$B$3$l$O(B lexcal $B$8$c$J$/$F(B dynamic $B$KJQ$([email protected]$J$!(B ($B$D$^$j(B

local rebinding)

TCPSocket.open
$B$NCf$J$I$G$d$k$H$$$&J}8~<+BN$O$"[email protected]$H;W$C$F$$$k$s$G$9$,!"(B
$B$G$O$=$3$G;H$&(B IP$B%"%I%l%9$r$I$3$+$i<h$C$F$/$k$+$H$J$k$H!"(B
$B%0%m!<%P%kJQ?t$r;H$&$H$+$7$J$$$H>e<j$/$$$+$J$$$s$8$c$J$$$+$H(B

[email protected]$H$3$s$J46$8$K$J$j$^$9!#(B
$B$b$&$A$g$C$H;H$$$E$i$/$F$b$$$$$H$O;W$$$^$9$,!"$=$&$9$k$H(B start
$B$,;H$($J$/$J$C$F(B
$B0l5$$KJ#;(2=$9$k$N$,G:$_$I$3$m(B
require ‘net/http’
addrs = %w/192.168.0.1 192.168.0.2 192.168.0.3/
addrs.each do |addr|
Net::HTTP.start(‘example.org’, use_ssl: true, ipaddr: addr){|h| p
h.get(’/’)}
end

2011$BG/(B8$B7n(B10$BF|(B18:21 tadanori kojima
[email protected]:

$B$H$$$&$N$,(BHTTP$BE*$J$U$D$&$NBP=h$J5$$,$7$^$9(B
$B4pK\E*$J(B HTTP $B$KBP$9$kM}6~$H$7$F$OF10U$9$k$H$3$m$J$s$G$9$,!"(B
https [email protected]$H(B connection
$BD%$k;[email protected]$G%[%9%HL>$,I,MW$J$?$a!"[email protected]$H$^$:$$$s$G$9!#(B

$B%[%9%H$,(Bv4/v6$B$NN>%"%I%l%9$r;}$D>l9g$J$I$K([email protected]\B3$7$?$$!"(B
$B$H$J$k$H$-$bF1$8$h$&$J46$8$G$7$g$&$+(B

$B$=$&$G$9$M!#(B

2011$BG/(B8$B7n(B10$BF|(B17:20 NARUSE, Yui [email protected]:

TCPSocket.open $B$NCf$J$I$G$d$k$H$$$&J}8~<+BN$O$"[email protected]$H;W$C$F$$$k$s$G$9$,!"(B
$B$G$O$=$3$G;H$&(B IP$B%"%I%l%9$r$I$3$+$i<h$C$F$/$k$+$H$J$k$H!"(B
$B%0%m!<%P%kJQ?t$r;H$&$H$+$7$J$$$H>e<j$/$$$+$J$$$s$8$c$J$$$+$H(B

$B%0%m!<%P%kJQ?t$,7y$J$i%9%l%C%IJQ?t$H$+!#(B

[email protected]$H$3$s$J46$8$K$J$j$^$9!#(B

net/http $B$KBP=h$rF~$l$k$[$I$NOC$J$N$+$J$!!#(B

load balancer$BMxMQ;~$N(Breal
[email protected]\B3$J$I$N%f!<%9%1!<%9$OM}2r$G$-$^$9$,(B

Net::HTTP.start(“127.0.0.1”) {|h|
print h.request_get( ‘/index.html’ , {“host”=>“ruby-lang.org”}).body
}

$B"((Bstart$B$O(BIP$B;XDj!"%j%/%(%9%H;~$N(Bhost$B%X%C%@$K%[%9%HL>(B

$B$H$$$&$N$,(BHTTP$BE*$J$U$D$&$NBP=h$J5$$,$7$^$9(B

$B%[%9%H$,(Bv4/v6$B$NN>%"%I%l%9$r;}$D>l9g$J$I$K([email protected]\B3$7$?$$!"(B
$B$H$J$k$H$-$bF1$8$h$&$J46$8$G$7$g$&$+(B

On Wed, 10 Aug 2011 15:05:24 +0900

On Wed, 10 Aug 2011 18:33:08 +0900
“NARUSE, Yui” [email protected] wrote:

$B$H$$$&$N$,(BHTTP$BE*$J$U$D$&$NBP=h$J5$$,$7$^$9(B

$B4pK\E*$J(B HTTP $B$KBP$9$kM}6~$H$7$F$OF10U$9$k$H$3$m$J$s$G$9$,!"(B
https [email protected]$H(B connection
$BD%$k;[email protected]$G%[%9%HL>$,I,MW$J$?$a!"[email protected]$H$^$:$$$s$G$9!#(B

$B0UL#$,$o$+$j$^$7$?(B

$B$G$b(Bssl$B$C$F(Bcommon name$B$N8!>Z$^$G$d$C$F$?$C$1!)(B
$B$H!"(Bnet/http.rb$B$N%=!<%9$r$_$k$H(Bconnect$BFb$K(B

$B!]!&!]!&!]!&!]!&!]!&!](B
s.connect
if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
s.post_connection_check(@address)
end
$B!]!&!]!&!]!&!]!&!]!&!](B

$B$H$"$k$N$G!"([email protected]$H!J<j85$N%^%7%s$,(Bcent5$B$J$N$G!#!#!#!K(B
$B!]!&!]!&!]!&!]!&!]!&!](B
diff -u net/http.rb.orig net/http.rb
— net/http.rb.orig 2011-08-11 11:09:21.000000000 +0900
+++ net/http.rb 2011-08-11 11:39:08.000000000 +0900
@@ -470,6 +470,7 @@
@debug_output = nil
@use_ssl = false
@ssl_context = nil

  •  @common_name = nil
    

    end

    def inspect
    @@ -526,6 +527,8 @@
    false # redefined in net/https
    end

  • attr_accessor :common_name

  • Opens TCP connection and HTTP session.

    When this method is called with block, gives a HTTP object

@@ -585,7 +588,7 @@
end
s.connect
if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE

  •      s.post_connection_check(@address)
    
  •      s.post_connection_check( @common_name || @address)
       end
     end
     on_connect
    

$B!]!&!]!&!]!&!]!&!]!&!](B
$B$G!"(B
$B!]!&!]!&!]!&!]!&!]!&!](B
require ‘net/http’
addrs = %w/192.168.0.1 192.168.0.2 192.168.0.3/
addrs.each do |addr|
Net::HTTP.start(addr, use_ssl: true, common_name: ‘example.org’){|h| p
h.get(’/’)}
end
$B!]!&!]!&!]!&!]!&!]!&!](B
$B$H(Bcommon name$B$r;XDj$9$k$[$&$,9%$_$G$9(B:-)

$B$$$b$H$NLdBj$O(B
[email protected]\B3%5!<%P$N;XDj!J(BIP/Hostname)$B!"(B
$B!!(BHTTP$B$N(BHost$B%X%C%@!J(BIP/Hostname$B!"(BVirtualHost$B$J$I$GMxMQ!K(B
$B!!(BSSL$B$N(BCN$B8!>Z!J(BIP/Hostname$B$H$OJL$K(BCNAME$B$b$"[email protected]$k(B)
$B$H!"%l%$%d$r0U<1$7$?%Q%1%C%H$NAH$_N)$FJ}$,I,MW$J$3$H$G$7$g$&$+(B
$B$9$C$-$j$7$?2r7hJ}K!$OIb$+$P$J$$$G$9$M!#!#!#(B

On Thu, 11 Aug 2011 15:30:06 +0900
Kazuhiro NISHIYAMA [email protected] wrote:

$B$9$C$-$j$7$?2r7hJ}K!$OIb$+$P$J$$$G$9$M!#!#!#(B

$B%[%9%HL>$O(B [ruby-dev:43164] $B$N(B SNI $B$N$h$&$JItJ,$G$b;H$C$F$$$k$N$G(B
$B85$NDs0F$G$O(B IP $B%"%I%l%9$NJ}$rJLES;XDj$K$J$C$F$$$k$N$G$O$J$$$+$H(B
$B;W$$$^$7$?!#(B

$B$=$&$G$9$M(B
$B<+J,$O%M%C%H%o!<%/20$J$N$G%l%$%d$NDc$$$[$&[email protected]$_>e$2$F$$$/$N$,(B
[email protected]$K9g$C$F$$$k$N$G$9$,!">e0L$+$i2<$j$F$$$/J}$,DL>o$N$d$jJ}$G$9$M(B

$B85!9$O<+J,$b(Bhttps://www.asahi.com/$B$N$h$&$J%[%9%HL>$H(BCN$B$,0[$J$k(B
$B%5%$%H$N8!>Z$G$I$&$7$?$b$s$+G:[email protected]$3$H$,$"$j$^$7$?(B

$B$G$b!"(Bnet/http$B$K<j$rF~$l$k$[$I$U$D$&$+!)$H$$$&5?Ld$K0lI<$G$9(B

Issue #5180 has been updated by Kazuhiro NISHIYAMA.

匿名ユーザ wrote:

おおもとの問題は
接続サーバの指定(IP/Hostname)、
HTTPのHostヘッダ(IP/Hostname、VirtualHostなどで利用)
SSLのCN検証(IP/Hostnameとは別にCNAMEもあり得る)
と、レイヤを意識したパケットの組み立て方が必要なことでしょうか
すっきりした解決方法は浮かばないですね。。。

ホスト名は [ruby-dev:43164] の SNI のような部分でも使っているので
元の提案では IP アドレスの方を別途指定になっているのではないかと
思いました。

Feature #5180: net/http の接続時に用いる IP アドレスの指定
http://redmine.ruby-lang.org/issues/5180

Author: Yui NARUSE
Status: Open
Priority: Normal
Assignee:
Category: lib
Target version:

通常 net/http を使う時は、Net::HTTP.start(“ruby-lang.org”) などとホスト名を使います。
で、Socket がホスト名から IP アドレスを引いて、コネクションが張られます。
普通の人はこれで足りるわけですが、ふつうな人はしばしば DNS で引けない IP アドレスに接続したくなります。
例えば、ホスト名は “ruby-lang.org” としたいが、IP アドレスは 127.0.0.1 とか。

以下のパッチをあてると、
Net::HTTP.start(“ruby-lang.org”, ipaddr: ‘127.0.0.1’)
などとできるようになります。

diff --git a/lib/net/http.rb b/lib/net/http.rb
index 7b9ec4f…6d034e0 100644
— a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -524,7 +524,7 @@ module Net #:nodoc:
# opt :: optional hash
#
# opt sets following values by its accessor.

  • The keys are ca_file, ca_path, cert, cert_store, ciphers,

  • The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers,

    close_on_empty_response, key, open_timeout, read_timeout,

ssl_timeout,
# ssl_version, use_ssl, verify_callback, verify_depth and
verify_mode.
# If you set :use_ssl as true, you can use https and default value
of
@@ -542,6 +542,7 @@ module Net #:nodoc:
port, p_addr, p_port, p_user, p_pass = *arg
port = https_default_port if !port && opt && opt[:use_ssl]
http = new(address, port, p_addr, p_port, p_user, p_pass)

  •  http.ipaddr = opt[:ipaddr] if opt[:ipaddr]
    
     if opt
       if opt[:use_ssl]
    

@@ -575,6 +576,7 @@ module Net #:nodoc:
def initialize(address, port = nil)
@address = address
@port = (port || HTTP.default_port)

  •  @ipaddr = nil
     @curr_http_version = HTTPVersion
     @no_keepalive_server = false
     @close_on_empty_response = false
    

@@ -620,6 +622,17 @@ module Net #:nodoc:
# The port number to connect to.
attr_reader :port

  • The IP address to connect to/used to connect to

  • def ipaddr
  •  started? ?  @socket.io.peeraddr[3] : @ipaddr
    
  • end
  • Set the IP address to connect to

  • def ipaddr=(addr)
  •  raise IOError, "ipaddr value changed, but session already 
    

started" if started?

  •  @ipaddr = addr
    
  • end
  • Number of seconds to wait for the connection to open. Any number

    may be used, including Floats for fractional seconds. If the HTTP

    object cannot open a connection in this many seconds, it raises a

@@ -945,7 +958,7 @@ module Net #:nodoc:
# without proxy

 def conn_address
  •  address()
    
  •  @ipaddr || address()
    

    end

    def conn_port

(2011/08/11 17:48), tadanori kojima wrote:

$B%[%9%HL>$O(B [ruby-dev:43164] $B$N(B SNI $B$N$h$&$JItJ,$G$b;H$C$F$$$k$N$G(B
$B85$NDs0F$G$O(B IP $B%"%I%l%9$NJ}$rJLES;XDj$K$J$C$F$$$k$N$G$O$J$$$+$H(B
$B;W$$$^$7$?!#(B

$B$=$&$G$9$M(B
$B<+J,$O%M%C%H%o!<%/20$J$N$G%l%$%d$NDc$$$[$&[email protected]$_>e$2$F$$$/$N$,(B
[email protected]$K9g$C$F$$$k$N$G$9$,!">e0L$+$i2<$j$F$$$/J}$,DL>o$N$d$jJ}$G$9$M(B

$B$^$!!"$o$?$7$,$d$j$?$$$N$O(B http(s) $B$J$N$G!#(B
$B$J$*!"(BHTTP $B$N(B Host $B$H(B SSL $B$N(B CN
$B$,0c$&$H$$$&%1!<%9$O$o$?$7$K$O;W$$$D$-$^$;$s$G$7$?!#(B

$B85!9$O<+J,$b(Bhttps://www.asahi.com/$B$N$h$&$J%[%9%HL>$H(BCN$B$,0[$J$k(B
$B%5%$%H$N8!>Z$G$I$&$7$?$b$s$+G:[email protected]$3$H$,$"$j$^$7$?(B

$B$G$b!"(Bnet/http$B$K<j$rF~$l$k$[$I$U$D$&$+!)$H$$$&5?Ld$K0lI<$G$9(B

$B7k9=(B hosts $B%U%!%$%k=q$-49$($C$F$d$k$H;W$&$s$G$9$1$l$I$M!#(B

(2011/08/10 18:54), Tanaka A. wrote:

2011$BG/(B8$B7n(B10$BF|(B17:20 NARUSE, Yui [email protected]:

TCPSocket.open $B$NCf$J$I$G$d$k$H$$$&J}8~<+BN$O$"[email protected]$H;W$C$F$$$k$s$G$9$,!"(B
$B$G$O$=$3$G;H$&(B IP$B%"%I%l%9$r$I$3$+$i<h$C$F$/$k$+$H$J$k$H!"(B
$B%0%m!<%P%kJQ?t$r;H$&$H$+$7$J$$$H>e<j$/$$$+$J$$$s$8$c$J$$$+$H(B

$B%0%m!<%P%kJQ?t$,7y$J$i%9%l%C%IJQ?t$H$+!#(B

require ‘net/http’
addrs = %w/192.168.0.1 192.168.0.2 192.168.0.3/
def TCPSocket.open(host, serv, *rest)
TCPSocket.new(Thread.current[:ipaddr], serv, *rest)
end
addrs.map do |addr|
Thread.new do
Thread.current[:ipaddr] = addr
Net::HTTP.start(‘exapmle.org’, use_ssl: true) do |h|
r = h.head(’/’)
p [addr, h.instance_variable_get(:@socket).io.peeraddr[3], r]
end
end
end.each(&:join)
class << TCPSocket
remove_method :open
end

$B$3$s$J46$8$G$9$+$M!"$&!<$s!"$3$3$^$GBg$2$5$K$7$J$$$H$$$1$J$$$N$+$J$!!#(B

[email protected]$H$3$s$J46$8$K$J$j$^$9!#(B

net/http $B$KBP=h$rF~$l$k$[$I$NOC$J$N$+$J$!!#(B

$B$b$H$b$H(B conn_address $B$O(B Proxy
$BBP1~$N$?$a$KCj>]2=$5$l$F$$$k$N$G!"(B
$B$=$3$r$b$&$A$g$C$H$$$8$k$N$O$=$3$^$GFMHt$JOC$G$b$J$$$H;W$&$s$G$9$1$I$M!#(B

Issue #5180 has been updated by mame (Yusuke E.).

Status changed from Open to Assigned
Assignee set to naruse (Yui NARUSE)

成瀬さん

微妙に反対意見が出てますが、net/http のメンテナの裁量で
好きにやっていい範囲だと思います。
しかし現在 net/http にはメンテナがいません。

成瀬さんがメンテナになりませんか?
おまけで、net/http 関係の issue が憑いてきます。
メンテナになるのってまつもとさんの了解が必要でしたっけ。

成瀬さんがメンテナやりたくないなら reject の方向で。
その場合は Eric H. あたりに声かけてみますか。


Yusuke E. [email protected]

Feature #5180: net/http の接続時に用いる IP アドレスの指定
https://bugs.ruby-lang.org/issues/5180#change-25204

Author: naruse (Yui NARUSE)
Status: Assigned
Priority: Normal
Assignee: naruse (Yui NARUSE)
Category: lib
Target version:

通常 net/http を使う時は、Net::HTTP.start(“ruby-lang.org”) などとホスト名を使います。
で、Socket がホスト名から IP アドレスを引いて、コネクションが張られます。
普通の人はこれで足りるわけですが、ふつうな人はしばしば DNS で引けない IP アドレスに接続したくなります。
例えば、ホスト名は “ruby-lang.org” としたいが、IP アドレスは 127.0.0.1 とか。

以下のパッチをあてると、
Net::HTTP.start(“ruby-lang.org”, ipaddr: ‘127.0.0.1’)
などとできるようになります。

diff --git a/lib/net/http.rb b/lib/net/http.rb
index 7b9ec4f…6d034e0 100644
— a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -524,7 +524,7 @@ module Net #:nodoc:
# opt :: optional hash
#
# opt sets following values by its accessor.

  • The keys are ca_file, ca_path, cert, cert_store, ciphers,

  • The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers,

    close_on_empty_response, key, open_timeout, read_timeout,

ssl_timeout,
# ssl_version, use_ssl, verify_callback, verify_depth and
verify_mode.
# If you set :use_ssl as true, you can use https and default value
of
@@ -542,6 +542,7 @@ module Net #:nodoc:
port, p_addr, p_port, p_user, p_pass = *arg
port = https_default_port if !port && opt && opt[:use_ssl]
http = new(address, port, p_addr, p_port, p_user, p_pass)

  •  http.ipaddr = opt[:ipaddr] if opt[:ipaddr]
    
     if opt
       if opt[:use_ssl]
    

@@ -575,6 +576,7 @@ module Net #:nodoc:
def initialize(address, port = nil)
@address = address
@port = (port || HTTP.default_port)

  •  @ipaddr = nil
     @curr_http_version = HTTPVersion
     @no_keepalive_server = false
     @close_on_empty_response = false
    

@@ -620,6 +622,17 @@ module Net #:nodoc:
# The port number to connect to.
attr_reader :port

  • The IP address to connect to/used to connect to

  • def ipaddr
  •  started? ?  @socket.io.peeraddr[3] : @ipaddr
    
  • end
  • Set the IP address to connect to

  • def ipaddr=(addr)
  •  raise IOError, "ipaddr value changed, but session already 
    

started" if started?

  •  @ipaddr = addr
    
  • end
  • Number of seconds to wait for the connection to open. Any number

    may be used, including Floats for fractional seconds. If the HTTP

    object cannot open a connection in this many seconds, it raises a

@@ -945,7 +958,7 @@ module Net #:nodoc:
# without proxy

 def conn_address
  •  address()
    
  •  @ipaddr || address()
    

    end

    def conn_port

Issue #5180 has been updated by naruse (Yui NARUSE).

Status changed from Assigned to Rejected

これは reject します。

さておき、メンテナにはなりますかね。
まつもとさんの承認は必要だったような。

Feature #5180: net/http の接続時に用いる IP アドレスの指定
https://bugs.ruby-lang.org/issues/5180#change-25246

Author: naruse (Yui NARUSE)
Status: Rejected
Priority: Normal
Assignee: naruse (Yui NARUSE)
Category: lib
Target version:

通常 net/http を使う時は、Net::HTTP.start(“ruby-lang.org”) などとホスト名を使います。
で、Socket がホスト名から IP アドレスを引いて、コネクションが張られます。
普通の人はこれで足りるわけですが、ふつうな人はしばしば DNS で引けない IP アドレスに接続したくなります。
例えば、ホスト名は “ruby-lang.org” としたいが、IP アドレスは 127.0.0.1 とか。

以下のパッチをあてると、
Net::HTTP.start(“ruby-lang.org”, ipaddr: ‘127.0.0.1’)
などとできるようになります。

diff --git a/lib/net/http.rb b/lib/net/http.rb
index 7b9ec4f…6d034e0 100644
— a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -524,7 +524,7 @@ module Net #:nodoc:
# opt :: optional hash
#
# opt sets following values by its accessor.

  • The keys are ca_file, ca_path, cert, cert_store, ciphers,

  • The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers,

    close_on_empty_response, key, open_timeout, read_timeout,

ssl_timeout,
# ssl_version, use_ssl, verify_callback, verify_depth and
verify_mode.
# If you set :use_ssl as true, you can use https and default value
of
@@ -542,6 +542,7 @@ module Net #:nodoc:
port, p_addr, p_port, p_user, p_pass = *arg
port = https_default_port if !port && opt && opt[:use_ssl]
http = new(address, port, p_addr, p_port, p_user, p_pass)

  •  http.ipaddr = opt[:ipaddr] if opt[:ipaddr]
    
     if opt
       if opt[:use_ssl]
    

@@ -575,6 +576,7 @@ module Net #:nodoc:
def initialize(address, port = nil)
@address = address
@port = (port || HTTP.default_port)

  •  @ipaddr = nil
     @curr_http_version = HTTPVersion
     @no_keepalive_server = false
     @close_on_empty_response = false
    

@@ -620,6 +622,17 @@ module Net #:nodoc:
# The port number to connect to.
attr_reader :port

  • The IP address to connect to/used to connect to

  • def ipaddr
  •  started? ?  @socket.io.peeraddr[3] : @ipaddr
    
  • end
  • Set the IP address to connect to

  • def ipaddr=(addr)
  •  raise IOError, "ipaddr value changed, but session already 
    

started" if started?

  •  @ipaddr = addr
    
  • end
  • Number of seconds to wait for the connection to open. Any number

    may be used, including Floats for fractional seconds. If the HTTP

    object cannot open a connection in this many seconds, it raises a

@@ -945,7 +958,7 @@ module Net #:nodoc:
# without proxy

 def conn_address
  •  address()
    
  •  @ipaddr || address()
    

    end

    def conn_port