8000 Fix connecting to IPv6 destination hosts · SimonFrings/reactphp-http-proxy@5675206 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5675206

Browse files
committed
Fix connecting to IPv6 destination hosts
1 parent 8cf95d8 commit 5675206

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

src/ProxyConnector.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ public function connect($uri)
107107
return Promise\reject(new InvalidArgumentException('Invalid target URI specified'));
108108
}
109109

110-
$host = trim($parts['host'], '[]');
111-
$port = $parts['port'];
110+
$target = $parts['host'] . ':' . $parts['port'];
112111

113112
// construct URI to HTTP CONNECT proxy server to connect to
114113
$proxyUri = $this->proxyUri;
@@ -126,11 +125,11 @@ public function connect($uri)
126125

127126
// append hostname from URI to query string unless explicitly given
128127
if (!isset($args['hostname'])) {
129-
$args['hostname'] = $parts['host'];
128+
$args['hostname'] = trim($parts['host'], '[]');
130129
}
131130

132131
// append query string
133-
$proxyUri .= '?' . http_build_query($args, '', '&');;
132+
$proxyUri .= '?' . http_build_query($args, '', '&');
134133

135134
// append fragment from URI if given
136135
if (isset($parts['fragment'])) {
@@ -139,7 +138,7 @@ public function connect($uri)
139138

140139
$auth = $this->proxyAuth;
141140

142-
return $this->connector->connect($proxyUri)->then(function (ConnectionInterface $stream) use ($host, $port, $auth) {
141+
return $this->connector->connect($proxyUri)->then(function (ConnectionInterface $stream) use ($target, $auth) {
143142
$deferred = new Deferred(function ($_, $reject) use ($stream) {
144143
$reject(new RuntimeException('Connection canceled while waiting for response from proxy (ECONNABORTED)', defined('SOCKET_ECONNABORTED') ? SOCKET_ECONNABORTED : 103));
145144
$stream->close();
@@ -199,7 +198,7 @@ public function connect($uri)
199198
$deferred->reject(new RuntimeException('Connection to proxy lost while waiting for response (ECONNRESET)', defined('SOCKET_ECONNRESET') ? SOCKET_ECONNRESET : 104));
200199
});
201200

202-
$stream->write("CONNECT " . $host . ":" . $port . " HTTP/1.1\r\nHost: " . $host . ":" . $port . "\r\n" . $auth . "\r\n");
201+
$stream->write("CONNECT " . $target . " HTTP/1.1\r\nHost: " . $target . "\r\n" . $auth . "\r\n");
203202

204203
return $deferred->promise()->then(function (ConnectionInterface $stream) use ($fn) {
205204
// Stop buffering when connection has been established.

tests/ProxyConnectorTest.php

Lines changed: 43 additions & 0 deletions
46F9
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,36 @@ public function testCreatesConnectionToHttpPortAndObeysExplicitHostname()
6969
$proxy->connect('google.com:80?hostname=www.google.com');
7070
}
7171

72+
public function testCreatesConnectionToIpv4Address()
73+
{
74+
$promise = new Promise(function () { });
75+
$this->connector->expects($this->once())->method('connect')->with('tcp://proxy.example.com:80?hostname=127.0.0.1')->willReturn($promise);
76+
77+
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
78+
79+
$proxy->connect('127.0.0.1:80');
80+
}
81+
82+
public function testCreatesConnectionToIpv6Address()
83+
{
84+
$promise = new Promise(function () { });
85+
$this->connector->expects($this->once())->method('connect')->with('tcp://proxy.example.com:80?hostname=%3A%3A1')->willReturn($promise);
86+
87+
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
88+
89+
$proxy->connect('[::1]:80');
90+
}
91+
92+
public function testCreatesConnectionToIpv4AddressOverIpv6Proxy()
93+
{
94+
$promise = new Promise(function () { });
95+
$this->connector->expects($this->once())->method('connect')->with('tcp://[::1]:80?hostname=127.0.0.1')->willReturn($promise);
96+
97+
$proxy = new ProxyConnector('[::1]:80', $this->connector);
98+
99+
$proxy->connect('127.0.0.1:80');
100+
}
101+
72102
public function testCreatesConnectionToHttpsPort()
73103
{
74104
$promise = new Promise(function () { });
@@ -116,6 +146,19 @@ public function testWillWriteToOpenConnection()
116146
$proxy->connect('google.com:80');
117147
}
118148

149+
public function testWillWriteIpv6HostToOpenConnection()
150+
{
151+
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
152+
$stream->expects($this->once())->method('write')->with("CONNECT [::1]:80 HTTP/1.1\r\nHost: [::1]:80\r\n\r\n");
153+
154+
$promise = \React\Promise\resolve($stream);
155+
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
156+
157+
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
158+
159+
$proxy->connect('[::1]:80');
160+
}
161+
119162
public function testWillProxyAuthorizationHeaderIfProxyUriContainsAuthentication()
120163
{
121164
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();

0 commit comments

Comments
 (0)
0