Skip to content

Commit 6f23a0e

Browse files
committed
Forward compatibility with Socket v1.0 and v0.8
1 parent bb4b14a commit 6f23a0e

File tree

4 files changed

+46
-20
lines changed

4 files changed

+46
-20
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"require": {
77
"php": ">=5.3.0",
88
"ringcentral/psr7": "^1.2",
9-
"react/socket": "^0.7 || ^0.6 || ^0.5",
9+
"react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5",
1010
"react/stream": "^0.6 || ^0.5 || ^0.4.4",
1111
"react/promise": "^2.0 || ^1.1",
1212
"evenement/evenement": "^2.0 || ^1.0"
@@ -18,7 +18,7 @@
1818
},
1919
"require-dev": {
2020
"phpunit/phpunit": "^4.8.10||^5.0",
21-
"react/socket": "^0.7",
21+
"react/socket": "^1.0 || ^0.8 || ^0.7",
2222
"clue/block-react": "^1.1"
2323
}
2424
}

src/RequestHeaderParser.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ private function parseRequest($data)
181181
// set URI components from socket address if not already filled via Host header
182182
if ($request->getUri()->getHost() === '') {
183183
$parts = parse_url($this->localSocketUri);
184+
if (!isset($parts['host'], $parts['port'])) {
185+
$parts = array('host' => '127.0.0.1', 'port' => 80);
186+
}
184187

185188
$request = $request->withUri(
186189
$request->getUri()->withScheme('http')->withHost($parts['host'])->withPort($parts['port']),

src/Server.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,25 @@ public function __construct(SocketServerInterface $io, $callback)
111111
/** @internal */
112112
public function handleConnection(ConnectionInterface $conn)
113113
{
114+
$uriLocal = $conn->getLocalAddress();
115+
if ($uriLocal !== null && strpos($uriLocal, '://') === false) {
116+
// local URI known but does not contain a scheme. Should only happen for old Socket < 0.8
117+
// try to detect transport encryption and assume default application scheme
118+
$uriLocal = ($this->isConnectionEncrypted($conn) ? 'https://' : 'http://') . $uriLocal;
119+
} elseif ($uriLocal !== null) {
120+
// local URI known, so translate transport scheme to application scheme
121+
$uriLocal = strtr($uriLocal, array('tcp://' => 'http://', 'tls://' => 'https://'));
122+
}
123+
124+
$uriRemote = $conn->getRemoteAddress();
125+
if ($uriRemote !== null && strpos($uriRemote, '://') === false) {
126+
// local URI known but does not contain a scheme. Should only happen for old Socket < 0.8
127+
// actual scheme is not evaluated but required for parsing URI
128+
$uriRemote = 'unused://' . $uriRemote;
129+
}
130+
114131
$that = $this;
115-
$parser = new RequestHeaderParser(
116-
($this->isConnectionEncrypted($conn) ? 'https://' : 'http://') . $conn->getLocalAddress(),
117-
'tcp://' . $conn->getRemoteAddress()
118-
);
132+
$parser = new RequestHeaderParser($uriLocal, $uriRemote);
119133

120134
$listener = array($parser, 'feed');
121135
$parser->on('headers', function (RequestInterface $request, $bodyBuffer) use ($conn, $listener, $parser, $that) {

tests/FunctionalServerTest.php

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use React\Http\Response;
1414
use React\Socket\SecureServer;
1515

16-
class FunctionServerTest extends TestCase
16+
class FunctionalServerTest extends TestCase
1717
{
1818
public function testPlainHttpOnRandomPort()
1919
{
@@ -26,15 +26,15 @@ public function testPlainHttpOnRandomPort()
2626
});
2727

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

3131
return BufferedSink::createPromise($conn);
3232
});
3333

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

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

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

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

6363
$socket->close();
6464
}
@@ -106,16 +106,16 @@ public function testSecureHttpsOnRandomPort()
106106
return new Response(200, array(), (string)$request->getUri());
107107
});
108108

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

112112
return BufferedSink::createPromise($conn);
113113
});
114114

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

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

120120
$socket->close();
121121
}
@@ -139,7 +139,7 @@ public function testSecureHttpsOnRandomPortWithoutHostHeaderUsesSocketUri()
139139
return new Response(200, array(), (string)$request->getUri());
140140
});
141141

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

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

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

153153
$socket->close();
154154
}
@@ -232,7 +232,7 @@ public function testSecureHttpsOnStandardPortReturnsUriWithNoPort()
232232
return new Response(200, array(), (string)$request->getUri());
233233
});
234234

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

238238
return BufferedSink::createPromise($conn);
@@ -269,7 +269,7 @@ public function testSecureHttpsOnStandardPortWithoutHostHeaderUsesSocketUri()
269269
return new Response(200, array(), (string)$request->getUri());
270270
});
271271

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

275275
return BufferedSink::createPromise($conn);
@@ -298,7 +298,7 @@ public function testPlainHttpOnHttpsStandardPortReturnsUriWithPort()
298298
});
299299

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

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

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

340340
return BufferedSink::createPromise($conn);
341341
});
@@ -348,3 +348,12 @@ public function testSecureHttpsOnHttpStandardPortReturnsUriWithPort()
348348
$socket->close();
349349
}
350350
}
351+
352+
function noScheme($uri)
353+
{
354+
$pos = strpos($uri, '://');
355+
if ($pos !== false) {
356+
$uri = substr($uri, $pos + 3);
357+
}
358+
return $uri;
359+
}

0 commit comments

Comments
 (0)