summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-11 18:37:18 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-11 18:37:18 +0000
commit468985371143fc0f1f86c60897fa64c22321c8fc (patch)
tree0442c3fd2e17fa510ad6ea948221224dbf1069fe
parentdea582458af3ac34fcaad7fd8de46560c012fb3b (diff)
* lib/net/http.rb (Net::HTTP#connect): use local_host and local_port
if specified. patched by Ricardo Amorim [Feature #6617] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36367 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--NEWS9
-rw-r--r--lib/net/http.rb10
-rw-r--r--test/net/http/test_http.rb42
4 files changed, 65 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 0905fc6f31..28a192f970 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Jul 12 01:49:07 2012 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/net/http.rb (Net::HTTP#connect): use local_host and local_port
+ if specified. patched by Ricardo Amorim [Feature #6617]
+
Wed Jul 11 17:36:39 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/extmk.rb: append ENCOBJS to DLDOBJS but not EXTSOLIBS which is
diff --git a/NEWS b/NEWS
index 7c356b9352..dbf0c292b8 100644
--- a/NEWS
+++ b/NEWS
@@ -83,6 +83,15 @@ with all sufficient information, see the ChangeLog file.
* incompatible changes:
* Fiber#resume cannot resume a fiber which invokes "Fiber#transfer".
+* net/http
+ * new methods:
+ * Net::HTTP#local_host
+ * Net::HTTP#local_host=
+ * Net::HTTP#local_port
+ * Net::HTTP#local_port=
+ * extended method:
+ * Net::HTTP#connect uses local_host and local_port if specified.
+
* net/imap
* new methods:
* Net::IMAP.default_port
diff --git a/lib/net/http.rb b/lib/net/http.rb
index 9521f6c20a..7efea79cdd 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -587,6 +587,8 @@ module Net #:nodoc:
def initialize(address, port = nil)
@address = address
@port = (port || HTTP.default_port)
+ @local_host = nil
+ @local_port = nil
@curr_http_version = HTTPVersion
@keep_alive_timeout = 2
@last_communicated = nil
@@ -631,6 +633,12 @@ module Net #:nodoc:
# The port number to connect to.
attr_reader :port
+ # The local host used to estabilish the connection.
+ attr_accessor :local_host
+
+ # The local port used to estabilish the connection.
+ attr_accessor :local_port
+
# 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
@@ -799,7 +807,7 @@ module Net #:nodoc:
def connect
D "opening connection to #{conn_address()}..."
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
- TCPSocket.open(conn_address(), conn_port())
+ TCPSocket.open(conn_address(), conn_port(), @local_host, @local_port)
}
D "opened"
if use_ssl?
diff --git a/test/net/http/test_http.rb b/test/net/http/test_http.rb
index 8b3928bfd1..0f57e0ce2f 100644
--- a/test/net/http/test_http.rb
+++ b/test/net/http/test_http.rb
@@ -616,3 +616,45 @@ class TestNetHTTPKeepAlive < Test::Unit::TestCase
}
end
end
+
+class TestNetHTTPLocalBind < Test::Unit::TestCase
+ CONFIG = {
+ 'host' => '127.0.0.1',
+ 'port' => 10081,
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ }
+
+ include TestNetHTTPUtils
+
+ def test_bind_to_local_host
+ @server.mount_proc('/show_ip') { |req, res| res.body = req.remote_ip }
+
+ http = Net::HTTP.new(config('host'), config('port'))
+ http.local_host = _select_local_ip_address
+ assert_not_nil(http.local_host)
+ assert_nil(http.local_port)
+
+ res = http.get('/show_ip')
+ assert_equal(http.local_host, res.body)
+ end
+
+ def test_bind_to_local_port
+ @server.mount_proc('/show_port') { |req, res| res.body = req.peeraddr[1].to_s }
+
+ http = Net::HTTP.new(config('host'), config('port'))
+ http.local_host = _select_local_ip_address
+ http.local_port = [*10000..20000].shuffle.first.to_s
+ assert_not_nil(http.local_host)
+ assert_not_nil(http.local_port)
+
+ res = http.get('/show_port')
+ assert_equal(http.local_port, res.body)
+ end
+
+ def _select_local_ip_address
+ Socket.ip_address_list.find { |addr|
+ not addr.ipv4_loopback? and not addr.ipv4_multicast?
+ }.ip_address
+ end
+end