diff --git a/README.md b/README.md index 6f34664..15b1039 100644 --- a/README.md +++ b/README.md @@ -10,24 +10,23 @@ An asynchronous WebSocket client in PHP #### Usage Pawl as a standalone app: Connect to an echo server, send a message, display output, close connection: + ```php then(function($conn) { - $conn->on('message', function($msg) use ($conn) { - echo "Received: {$msg}\n"; - $conn->close(); - }); +require __DIR__ . '/vendor/autoload.php'; - $conn->send('Hello World!'); - }, function ($e) { - echo "Could not connect: {$e->getMessage()}\n"; +\Ratchet\Client\connect('wss://echo.websocket.org:443')->then(function($conn) { + $conn->on('message', function($msg) use ($conn) { + echo "Received: {$msg}\n"; + $conn->close(); }); -``` ---- + $conn->send('Hello World!'); +}, function ($e) { + echo "Could not connect: {$e->getMessage()}\n"; +}); +``` #### Classes @@ -57,31 +56,29 @@ A more in-depth example using explicit interfaces: Requesting sub-protocols, and ```php '8.8.8.8', - 'timeout' => 10 - ]); - $connector = new \Ratchet\Client\Connector($loop, $reactConnector); - - $connector('ws://127.0.0.1:9000', ['protocol1', 'subprotocol2'], ['Origin' => 'http://localhost']) - ->then(function(\Ratchet\Client\WebSocket $conn) { - $conn->on('message', function(\Ratchet\RFC6455\Messaging\MessageInterface $msg) use ($conn) { - echo "Received: {$msg}\n"; - $conn->close(); - }); - - $conn->on('close', function($code = null, $reason = null) { - echo "Connection closed ({$code} - {$reason})\n"; - }); - - $conn->send('Hello World!'); - }, function(\Exception $e) use ($loop) { - echo "Could not connect: {$e->getMessage()}\n"; - $loop->stop(); +require __DIR__ . '/vendor/autoload.php'; + +$reactConnector = new \React\Socket\Connector([ + 'dns' => '8.8.8.8', + 'timeout' => 10 +]); +$loop = \React\EventLoop\Loop::get(); +$connector = new \Ratchet\Client\Connector($loop, $reactConnector); + +$connector('ws://127.0.0.1:9000', ['protocol1', 'subprotocol2'], ['Origin' => 'http://localhost']) +->then(function(\Ratchet\Client\WebSocket $conn) { + $conn->on('message', function(\Ratchet\RFC6455\Messaging\MessageInterface $msg) use ($conn) { + echo "Received: {$msg}\n"; + $conn->close(); + }); + + $conn->on('close', function($code = null, $reason = null) { + echo "Connection closed ({$code} - {$reason})\n"; }); - $loop->run(); + $conn->send('Hello World!'); +}, function(\Exception $e) use ($loop) { + echo "Could not connect: {$e->getMessage()}\n"; + $loop->stop(); +}); ``` diff --git a/composer.json b/composer.json index e488fa6..331fc49 100644 --- a/composer.json +++ b/composer.json @@ -11,9 +11,9 @@ } , "require": { "php": ">=5.4" - , "react/socket": "^1.0 || ^0.8 || ^0.7" , "evenement/evenement": "^3.0 || ^2.0" , "ratchet/rfc6455": "^0.3" + , "react/socket": "^1.9" } , "require-dev": { "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8" diff --git a/src/Connector.php b/src/Connector.php index 8b30e66..8fd0519 100644 --- a/src/Connector.php +++ b/src/Connector.php @@ -1,6 +1,7 @@ _loop = $loop ?: Loop::get(); + if (null === $connector) { - $connector = new \React\Socket\Connector($loop, [ + $connector = new \React\Socket\Connector([ 'timeout' => 20 - ]); + ], $this->_loop); } - $this->_loop = $loop; $this->_connector = $connector; $this->_negotiator = new ClientNegotiator; } diff --git a/src/functions.php b/src/functions.php index 064c983..373afe4 100644 --- a/src/functions.php +++ b/src/functions.php @@ -1,8 +1,6 @@ */ function connect($url, array $subProtocols = [], $headers = [], LoopInterface $loop = null) { - $loop = $loop ?: ReactFactory::create(); - $connector = new Connector($loop); $connection = $connector($url, $subProtocols, $headers); - $runHasBeenCalled = false; - - $loop->addTimer(Timer::MIN_INTERVAL, function () use (&$runHasBeenCalled) { - $runHasBeenCalled = true; - }); - - register_shutdown_function(function() use ($loop, &$runHasBeenCalled) { - if (!$runHasBeenCalled) { - $loop->run(); - } - }); - return $connection; } diff --git a/tests/autobahn/runner.php b/tests/autobahn/runner.php index 897a670..f4f9cb4 100644 --- a/tests/autobahn/runner.php +++ b/tests/autobahn/runner.php @@ -6,10 +6,8 @@ define('AGENT', 'Pawl/0.3'); - $loop = React\EventLoop\Factory::create(); - - $connFactory = function() use ($loop) { - $connector = new Ratchet\Client\Connector($loop); + $connFactory = function() { + $connector = new Ratchet\Client\Connector(); return function($url) use ($connector) { return $connector('ws://127.0.0.1:9001' . $url); @@ -29,14 +27,14 @@ return $futureNum->promise(); }, function($e) { echo "Could not connect to test server: {$e->getMessage()}\n"; - })->then(function($numOfCases) use ($connector, $loop) { + })->then(function($numOfCases) use ($connector) { echo "Running {$numOfCases} test cases\n\n"; $allCases = new Deferred; $i = 0; - $runNextCase = function() use (&$runNextCase, &$i, $numOfCases, $allCases, $connector, $loop) { + $runNextCase = function() use (&$runNextCase, &$i, $numOfCases, $allCases, $connector) { $i++; if ($i > (int)$numOfCases->getPayload()) { @@ -59,11 +57,11 @@ $runNextCase(); return $allCases->promise(); - })->then(function() use ($connector, $loop) { - $connector('/updateReports?agent=' . AGENT)->then(function(WebSocket $conn) use ($loop) { + })->then(function() use ($connector) { + $connector('/updateReports?agent=' . AGENT)->then(function(WebSocket $conn) { echo "\nDone!\n"; - $conn->on('close', [$loop, 'stop']); + $conn->on('close', function () { + \React\EventLoop\Loop::stop(); + }); }); }); - - $loop->run(); diff --git a/tests/unit/ConnectorTest.php b/tests/unit/ConnectorTest.php index a32a051..c560691 100644 --- a/tests/unit/ConnectorTest.php +++ b/tests/unit/ConnectorTest.php @@ -2,12 +2,23 @@ use PHPUnit\Framework\TestCase; use Ratchet\Client\Connector; -use React\EventLoop\Factory; +use React\EventLoop\Loop; use React\Promise\RejectedPromise; use React\Promise\Promise; class ConnectorTest extends TestCase { + public function testConstructWithoutLoopAssignsLoopAutomatically() + { + $factory = new Connector(); + + $ref = new \ReflectionProperty($factory, '_loop'); + $ref->setAccessible(true); + $loop = $ref->getValue($factory); + + $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + } + public function uriDataProvider() { return [ ['ws://127.0.0.1', 'tcp://127.0.0.1:80'], @@ -21,7 +32,7 @@ public function uriDataProvider() { * @dataProvider uriDataProvider */ public function testSecureConnectionUsesTlsScheme($uri, $expectedConnectorUri) { - $loop = Factory::create(); + $loop = Loop::get(); $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); diff --git a/tests/unit/RequestUriTest.php b/tests/unit/RequestUriTest.php index 0b30240..9b78553 100644 --- a/tests/unit/RequestUriTest.php +++ b/tests/unit/RequestUriTest.php @@ -29,9 +29,7 @@ function uriDataProvider() { * @dataProvider uriDataProvider */ function testGeneratedRequestUri($uri, $expectedRequestUri) { - $loop = Factory::create(); - - $connector = new Connector($loop); + $connector = new Connector(); $generateRequest = self::getPrivateClassMethod('\Ratchet\Client\Connector', 'generateRequest'); $request = $generateRequest->invokeArgs($connector, [$uri, [], []]);