Skip to content

Commit 3f39f80

Browse files
committed
[HttpClient] Call dns properly with promises, use promises internally
1 parent a4ef120 commit 3f39f80

File tree

4 files changed

+79
-81
lines changed

4 files changed

+79
-81
lines changed

ConnectionManager.php

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
namespace React\HttpClient;
44

55
use React\EventLoop\LoopInterface;
6-
use React\Stream\Stream;
76
use React\Dns\Resolver\Resolver;
7+
use React\Stream\Stream;
8+
use React\Promise\Deferred;
9+
use React\Promise\FulfilledPromise;
10+
use React\Promise\RejectedPromise;
811

912
class ConnectionManager implements ConnectionManagerInterface
1013
{
@@ -17,73 +20,70 @@ public function __construct(LoopInterface $loop, Resolver $resolver)
1720
$this->resolver = $resolver;
1821
}
1922

20-
public function getConnection($callback, $host, $port)
23+
public function getConnection($host, $port)
2124
{
2225
$that = $this;
23-
$this->resolve(function ($address, $error = null) use ($that, $callback, $host, $port) {
24-
if ($error) {
25-
call_user_func($callback, null, new \RuntimeException(
26-
sprintf("failed to resolve %s", $host),
27-
0,
28-
$error
29-
));
30-
return;
31-
}
32-
$that->getConnectionForAddress($callback, $address, $port);
33-
}, $host);
26+
27+
return $this
28+
->resolveHostname($host)
29+
->then(function ($address) use ($port, $that) {
30+
return $that->getConnectionForAddress($address, $port);
31+
});
3432
}
3533

36-
public function getConnectionForAddress($callback, $address, $port)
34+
public function getConnectionForAddress($address, $port)
3735
{
3836
$url = $this->getSocketUrl($address, $port);
3937

4038
$socket = stream_socket_client($url, $errno, $errstr, ini_get("default_socket_timeout"), STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT);
4139

4240
if (!$socket) {
43-
call_user_func($callback, null, new \RuntimeException(
41+
return new RejectedPromise(new \RuntimeException(
4442
sprintf("connection to %s:%d failed: %s", $addresss, $port, $errstr),
4543
$errno
4644
));
47-
return;
4845
}
4946

5047
stream_set_blocking($socket, 0);
5148

5249
// wait for connection
5350

54-
$loop = $this->loop;
55-
$that = $this;
51+
return $this
52+
->waitForStreamOnce($socket)
53+
->then(array($this, 'handleConnectedSocket'));
54+
}
5655

57-
$this->loop->addWriteStream($socket, function () use ($that, $callback, $socket, $loop) {
56+
protected function waitForStreamOnce($stream)
57+
{
58+
$deferred = new Deferred();
5859

59-
$loop->removeWriteStream($socket);
60+
$loop = $this->loop;
6061

61-
$that->handleConnectedSocket($callback, $socket);
62+
$this->loop->addWriteStream($stream, function ($stream) use ($loop, $deferred) {
63+
$loop->removeWriteStream($stream);
64+
$deferred->resolve($stream);
6265
});
66+
67+
return $deferred->promise();
6368
}
6469

65-
public function handleConnectedSocket($callback, $socket)
70+
public function handleConnectedSocket($socket)
6671
{
67-
call_user_func($callback, new Stream($socket, $this->loop));
72+
return new Stream($socket, $this->loop);
6873
}
6974

7075
protected function getSocketUrl($host, $port)
7176
{
7277
return sprintf('tcp://%s:%s', $host, $port);
7378
}
7479

75-
protected function resolve($callback, $host)
80+
protected function resolveHostname($host)
7681
{
7782
if (false !== filter_var($host, FILTER_VALIDATE_IP)) {
78-
call_user_func($callback, $host);
79-
return;
83+
return new FulfilledPromise($host);
8084
}
8185

82-
$this->resolver->resolve($host, function ($address) use ($callback) {
83-
call_user_func($callback, $address);
84-
}, function ($error) use ($callback) {
85-
call_user_func($callback, null, $error);
86-
});
86+
return $this->resolver->resolve($host);
8787
}
8888
}
8989

ConnectionManagerInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
interface ConnectionManagerInterface
66
{
7-
public function getConnection($callback, $host, $port);
7+
public function getConnection($host, $port);
88
}

Request.php

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,32 +54,28 @@ public function writeHead()
5454
$streamRef = &$this->stream;
5555
$stateRef = &$this->state;
5656

57-
$this->connect(function ($stream, \Exception $error = null) use ($that, $request, &$streamRef, &$stateRef) {
58-
if (!$stream) {
59-
$that->closeError(new \RuntimeException(
60-
"Connection failed",
61-
0,
62-
$error
63-
));
64-
return;
65-
}
57+
$this
58+
->connect()
59+
->then(
60+
function ($stream) use ($that, $request, &$streamRef, &$stateRef) {
61+
$streamRef = $stream;
6662

67-
$streamRef = $stream;
63+
$stream->on('drain', array($that, 'handleDrain'));
64+
$stream->on('data', array($that, 'handleData'));
65+
$stream->on('end', array($that, 'handleEnd'));
66+
$stream->on('error', array($that, 'handleError'));
6867

69-
$stream->on('drain', array($that, 'handleDrain'));
70-
$stream->on('data', array($that, 'handleData'));
71-
$stream->on('end', array($that, 'handleEnd'));
72-
$stream->on('error', array($that, 'handleError'));
68+
$request->setProtocolVersion('1.0');
69+
$headers = (string) $request;
7370

74-
$request->setProtocolVersion('1.0');
75-
$headers = (string) $request;
71+
$stream->write($headers);
7672

77-
$stream->write($headers);
73+
$stateRef = Request::STATE_HEAD_WRITTEN;
7874

79-
$stateRef = Request::STATE_HEAD_WRITTEN;
80-
81-
$that->emit('headers-written', array($that));
82-
});
75+
$that->emit('headers-written', array($that));
76+
},
77+
array($this, 'handleError')
78+
);
8379
}
8480

8581
public function write($data)
@@ -213,16 +209,13 @@ protected function parseResponse($data)
213209
return array($response, $parsed['body']);
214210
}
215211

216-
protected function connect($callback)
212+
protected function connect()
217213
{
218214
$host = $this->request->getHost();
219215
$port = $this->request->getPort();
220-
$connectionManager = $this->connectionManager;
221-
$that = $this;
222216

223-
$connectionManager->getConnection(function ($stream, $error = null) use ($that, $callback) {
224-
call_user_func($callback, $stream, $error);
225-
}, $host, $port);
217+
return $this->connectionManager
218+
->getConnection($host, $port);
226219
}
227220

228221
public function setResponseFactory($factory)

SecureConnectionManager.php

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,44 @@
44

55
use React\EventLoop\LoopInterface;
66
use React\Stream\Stream;
7+
use React\Promise\Deferred;
8+
use React\Promise\ResolverInterface;
79

810
class SecureConnectionManager extends ConnectionManager
911
{
10-
public function handleConnectedSocket($callback, $socket)
12+
public function handleConnectedSocket($socket)
1113
{
12-
$loop = $this->loop;
14+
$that = $this;
1315

14-
$enableCrypto = function () use ($callback, $socket, $loop) {
16+
$deferred = new Deferred();
1517

16-
$result = stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
17-
18-
if (true === $result) {
19-
// crypto was successfully enabled
20-
$loop->removeWriteStream($socket);
21-
$loop->removeReadStream($socket);
22-
call_user_func($callback, new Stream($socket, $loop));
23-
24-
} else if (false === $result) {
25-
// an error occured
26-
$loop->removeWriteStream($socket);
27-
$loop->removeReadStream($socket);
28-
call_user_func($callback, null);
29-
30-
} else {
31-
// need more data, will retry
32-
}
18+
$enableCrypto = function () use ($that, $socket, $deferred) {
19+
$that->enableCrypto($socket, $deferred);
3320
};
3421

3522
$this->loop->addWriteStream($socket, $enableCrypto);
3623
$this->loop->addReadStream($socket, $enableCrypto);
37-
3824
$enableCrypto();
25+
26+
return $deferred->promise();
3927
}
40-
}
4128

29+
public function enableCrypto($socket, ResolverInterface $resolver)
30+
{
31+
$result = stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
32+
33+
if (true === $result) {
34+
$this->loop->removeWriteStream($socket);
35+
$this->loop->removeReadStream($socket);
36+
37+
$resolver->resolve(new Stream($socket, $this->loop));
38+
} else if (false === $result) {
39+
$this->loop->removeWriteStream($socket);
40+
$this->loop->removeReadStream($socket);
4241

42+
$resolver->reject();
43+
} else {
44+
// need more data, will retry
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)