Skip to content

Commit

Permalink
Merge pull request #183 from clue-labs/socket
Browse files Browse the repository at this point in the history
Forward compatibility with Socket v1.0 and v0.8
  • Loading branch information
clue authored May 13, 2017
2 parents bb4b14a + ce9fb0b commit 563af6b
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 20 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"require": {
"php": ">=5.3.0",
"ringcentral/psr7": "^1.2",
"react/socket": "^0.7 || ^0.6 || ^0.5",
"react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5",
"react/stream": "^0.6 || ^0.5 || ^0.4.4",
"react/promise": "^2.0 || ^1.1",
"evenement/evenement": "^2.0 || ^1.0"
Expand All @@ -18,7 +18,7 @@
},
"require-dev": {
"phpunit/phpunit": "^4.8.10||^5.0",
"react/socket": "^0.7",
"react/socket": "^1.0 || ^0.8 || ^0.7",
"clue/block-react": "^1.1"
}
}
3 changes: 3 additions & 0 deletions src/RequestHeaderParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ private function parseRequest($data)
// set URI components from socket address if not already filled via Host header
if ($request->getUri()->getHost() === '') {
$parts = parse_url($this->localSocketUri);
if (!isset($parts['host'], $parts['port'])) {
$parts = array('host' => '127.0.0.1', 'port' => 80);
}

$request = $request->withUri(
$request->getUri()->withScheme('http')->withHost($parts['host'])->withPort($parts['port']),
Expand Down
22 changes: 18 additions & 4 deletions src/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,25 @@ public function __construct(SocketServerInterface $io, $callback)
/** @internal */
public function handleConnection(ConnectionInterface $conn)
{
$uriLocal = $conn->getLocalAddress();
if ($uriLocal !== null && strpos($uriLocal, '://') === false) {
// local URI known but does not contain a scheme. Should only happen for old Socket < 0.8
// try to detect transport encryption and assume default application scheme
$uriLocal = ($this->isConnectionEncrypted($conn) ? 'https://' : 'http://') . $uriLocal;
} elseif ($uriLocal !== null) {
// local URI known, so translate transport scheme to application scheme
$uriLocal = strtr($uriLocal, array('tcp://' => 'http://', 'tls://' => 'https://'));
}

$uriRemote = $conn->getRemoteAddress();
if ($uriRemote !== null && strpos($uriRemote, '://') === false) {
// local URI known but does not contain a scheme. Should only happen for old Socket < 0.8
// actual scheme is not evaluated but required for parsing URI
$uriRemote = 'unused://' . $uriRemote;
}

$that = $this;
$parser = new RequestHeaderParser(
($this->isConnectionEncrypted($conn) ? 'https://' : 'http://') . $conn->getLocalAddress(),
'tcp://' . $conn->getRemoteAddress()
);
$parser = new RequestHeaderParser($uriLocal, $uriRemote);

$listener = array($parser, 'feed');
$parser->on('headers', function (RequestInterface $request, $bodyBuffer) use ($conn, $listener, $parser, $that) {
Expand Down
37 changes: 23 additions & 14 deletions tests/FunctionalServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use React\Http\Response;
use React\Socket\SecureServer;

class FunctionServerTest extends TestCase
class FunctionalServerTest extends TestCase
{
public function testPlainHttpOnRandomPort()
{
Expand All @@ -26,15 +26,15 @@ public function testPlainHttpOnRandomPort()
});

$result = $connector->connect($socket->getAddress())->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\nHost: " . $conn->getRemoteAddress() . "\r\n\r\n");
$conn->write("GET / HTTP/1.0\r\nHost: " . noScheme($conn->getRemoteAddress()) . "\r\n\r\n");

return BufferedSink::createPromise($conn);
});

$response = Block\await($result, $loop, 1.0);

$this->assertContains("HTTP/1.0 200 OK", $response);
$this->assertContains('http://' . $socket->getAddress() . '/', $response);
$this->assertContains('http://' . noScheme($socket->getAddress()) . '/', $response);

$socket->close();
}
Expand All @@ -58,7 +58,7 @@ public function testPlainHttpOnRandomPortWithoutHostHeaderUsesSocketUri()
$response = Block\await($result, $loop, 1.0);

$this->assertContains("HTTP/1.0 200 OK", $response);
$this->assertContains('http://' . $socket->getAddress() . '/', $response);
$this->assertContains('http://' . noScheme($socket->getAddress()) . '/', $response);

$socket->close();
}
Expand Down Expand Up @@ -106,16 +106,16 @@ public function testSecureHttpsOnRandomPort()
return new Response(200, array(), (string)$request->getUri());
});

$result = $connector->connect('tls://' . $socket->getAddress())->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\nHost: " . $conn->getRemoteAddress() . "\r\n\r\n");
$result = $connector->connect('tls://' . noScheme($socket->getAddress()))->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\nHost: " . noScheme($conn->getRemoteAddress()) . "\r\n\r\n");

return BufferedSink::createPromise($conn);
});

$response = Block\await($result, $loop, 1.0);

$this->assertContains("HTTP/1.0 200 OK", $response);
$this->assertContains('https://' . $socket->getAddress() . '/', $response);
$this->assertContains('https://' . noScheme($socket->getAddress()) . '/', $response);

$socket->close();
}
Expand All @@ -139,7 +139,7 @@ public function testSecureHttpsOnRandomPortWithoutHostHeaderUsesSocketUri()
return new Response(200, array(), (string)$request->getUri());
});

$result = $connector->connect('tls://' . $socket->getAddress())->then(function (ConnectionInterface $conn) {
$result = $connector->connect('tls://' . noScheme($socket->getAddress()))->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\n\r\n");

return BufferedSink::createPromise($conn);
Expand All @@ -148,7 +148,7 @@ public function testSecureHttpsOnRandomPortWithoutHostHeaderUsesSocketUri()
$response = Block\await($result, $loop, 1.0);

$this->assertContains("HTTP/1.0 200 OK", $response);
$this->assertContains('https://' . $socket->getAddress() . '/', $response);
$this->assertContains('https://' . noScheme($socket->getAddress()) . '/', $response);

$socket->close();
}
Expand Down Expand Up @@ -232,7 +232,7 @@ public function testSecureHttpsOnStandardPortReturnsUriWithNoPort()
return new Response(200, array(), (string)$request->getUri());
});

$result = $connector->connect('tls://' . $socket->getAddress())->then(function (ConnectionInterface $conn) {
$result = $connector->connect('tls://' . noScheme($socket->getAddress()))->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\nHost: 127.0.0.1\r\n\r\n");

return BufferedSink::createPromise($conn);
Expand Down Expand Up @@ -269,7 +269,7 @@ public function testSecureHttpsOnStandardPortWithoutHostHeaderUsesSocketUri()
return new Response(200, array(), (string)$request->getUri());
});

$result = $connector->connect('tls://' . $socket->getAddress())->then(function (ConnectionInterface $conn) {
$result = $connector->connect('tls://' . noScheme($socket->getAddress()))->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\n\r\n");

return BufferedSink::createPromise($conn);
Expand Down Expand Up @@ -298,7 +298,7 @@ public function testPlainHttpOnHttpsStandardPortReturnsUriWithPort()
});

$result = $connector->connect($socket->getAddress())->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\nHost: " . $conn->getRemoteAddress() . "\r\n\r\n");
$conn->write("GET / HTTP/1.0\r\nHost: " . noScheme($conn->getRemoteAddress()) . "\r\n\r\n");

return BufferedSink::createPromise($conn);
});
Expand Down Expand Up @@ -334,8 +334,8 @@ public function testSecureHttpsOnHttpStandardPortReturnsUriWithPort()
return new Response(200, array(), (string)$request->getUri() . 'x' . $request->getHeaderLine('Host'));
});

$result = $connector->connect('tls://' . $socket->getAddress())->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\nHost: " . $conn->getRemoteAddress() . "\r\n\r\n");
$result = $connector->connect('tls://' . noScheme($socket->getAddress()))->then(function (ConnectionInterface $conn) {
$conn->write("GET / HTTP/1.0\r\nHost: " . noScheme($conn->getRemoteAddress()) . "\r\n\r\n");

return BufferedSink::createPromise($conn);
});
Expand All @@ -348,3 +348,12 @@ public function testSecureHttpsOnHttpStandardPortReturnsUriWithPort()
$socket->close();
}
}

function noScheme($uri)
{
$pos = strpos($uri, '://');
if ($pos !== false) {
$uri = substr($uri, $pos + 3);
}
return $uri;
}

0 comments on commit 563af6b

Please sign in to comment.