Skip to content

Commit

Permalink
Use EACCES error code if proxy uses 407 (Proxy Authentication Required)
Browse files Browse the repository at this point in the history
  • Loading branch information
clue committed Aug 28, 2017
1 parent 5db04ad commit 7258a76
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 5 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ $proxy = new ProxyConnector(
connection attempt.
If the authentication details are missing or not accepted by the remote HTTP
proxy server, it is expected to reject each connection attempt with a
`407` (Proxy Authentication Required) response status code.
`407` (Proxy Authentication Required) response status code and an exception
error code of `SOCKET_EACCES` (13).

#### Advanced secure proxy connections

Expand Down
11 changes: 7 additions & 4 deletions src/ProxyConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,14 @@ public function connect($uri)
return;
}

// status must be 2xx
if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
if ($response->getStatusCode() === 407) {
// map status code 407 (Proxy Authentication Required) to EACCES
$deferred->reject(new RuntimeException('Proxy denied connection due to invalid authentication ' . $response->getStatusCode() . ' (' . $response->getReasonPhrase() . ') (EACCES)', defined('SOCKET_EACCES') ? SOCKET_EACCES : 13));
return $stream->close();
} elseif ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
// map non-2xx status code to ECONNREFUSED
$deferred->reject(new RuntimeException('Proxy refused connection with HTTP error code ' . $response->getStatusCode() . ' (' . $response->getReasonPhrase() . ') (ECONNREFUSED)', defined('SOCKET_ECONNREFUSED') ? SOCKET_ECONNREFUSED : 111));
$stream->close();
return;
return $stream->close();
}

// all okay, resolve with stream instance
Expand Down
17 changes: 17 additions & 0 deletions tests/ProxyConnectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,23 @@ public function testRejectsAndClosesIfStreamWritesTooMuchData()
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EMSGSIZE));
}

public function testRejectsAndClosesIfStreamReturnsProyAuthenticationRequired()
{
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();

$promise = \React\Promise\resolve($stream);
$this->connector->expects($this->once())->method('connect')->willReturn($promise);

$proxy = new ProxyConnector('proxy.example.com', $this->connector);

$promise = $proxy->connect('google.com:80');

$stream->expects($this->once())->method('close');
$stream->emit('data', array("HTTP/1.1 407 Proxy Authentication Required\r\n\r\n"));

$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EACCES));
}

public function testRejectsAndClosesIfStreamReturnsNonSuccess()
{
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
Expand Down

0 comments on commit 7258a76

Please sign in to comment.