├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── src ├── Console │ └── Commands │ │ └── RatchetServerCommand.php ├── Examples │ └── Pusher.php ├── Providers │ └── LaravelRatchetServiceProvider.php ├── RatchetWampServer.php ├── RatchetWsServer.php ├── config │ └── ratchet.php └── lang │ └── en │ └── messages.php └── tests ├── index.js └── pubsub.html /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | node_modules/ 3 | 4 | # Laravel 4 specific 5 | bootstrap/compiled.php 6 | app/storage/ 7 | 8 | # Laravel 5 & Lumen specific 9 | bootstrap/cache/ 10 | storage/ 11 | .env.*.php 12 | .env.php 13 | .env 14 | .env.example -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Askedio 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Ratchet Server 2 | 3 | This package enables you to create and run a fully functioning WebSocket server in your Laravel app. It can optionally receive messages broadcast over ZeroMQ. 4 | 5 | ## Requirements 6 | 7 | - PHP 7.1+ 8 | - Laravel 5.5+ 9 | - ZeroMQ 10 | - ext-zmq for PHP 11 | 12 | ## Installation 13 | 14 | ```bash 15 | $ composer require askedio/laravel-ratchet 16 | ``` 17 | 18 | The service provider is loaded automatically in Laravel 5.5 using Package Autodiscovery. 19 | 20 | Publish the vendor files so you can configure your server defaults. 21 | 22 | ```bash 23 | $ php artisan vendor:publish --provider="Askedio\LaravelRatchet\Providers\LaravelRatchetServiceProvider" 24 | ``` 25 | 26 | ## Starting the Server 27 | 28 | After completing installation, the quickest way to start a standard WebSocket server is simply by running: 29 | 30 | ```bash 31 | $ php artisan ratchet:serve --driver=WsServer 32 | ``` 33 | 34 | This will run a simple example server based on `src/Examples/Pusher.php`. 35 | 36 | It's possible to create a WampServer or an IoServer also. Use the `--help` switch on the command to find out more. 37 | 38 | You should create your own server class inside your `app` folder by extending one of the core Ratchet server classes: [RatchetWsServer.php](https://github.com/Askedio/laravel-ratchet/blob/master/src/RatchetWsServer.php) or [RatchetWampServer.php](https://github.com/Askedio/laravel-ratchet/blob/master/src/RatchetWampServer.php). 39 | 40 | Then update your `config/ratchet.php` file to point to your server `class`. 41 | 42 | ## Use with Laravel Broadcasting 43 | 44 | To use broadcasting in your Laravel app with the server you create, you will need a ZeroMQ broadcast driver for Laravel (e.g. [this one](https://github.com/pelim/laravel-zmq)). 45 | 46 | You will also need to tell your Ratchet server to bind to a ZeroMQ socket. You can do this simply by passing the `-z` option, i.e.: 47 | 48 | ```bash 49 | $ php artisan ratchet:serve --driver=WsServer -z 50 | ``` 51 | 52 | This will connect to the socket you define in your `config/ratchet.php` settings and listen for messages from ZeroMQ. 53 | 54 | To handle messages published via ZeroMQ, simply add a `public function onEntry($messages)` method to your server class. This will allow you to receive messages inside your Ratchet server instance and determine how to route them. 55 | 56 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "askedio/laravel-ratchet", 3 | "description": "A Ratchet Server built for Laravel", 4 | "keywords": ["laravel"], 5 | "license": "MIT", 6 | "type": "library", 7 | "require": { 8 | "php": ">=7.2.0", 9 | "ext-zmq": "*", 10 | "cboden/ratchet": "^0.4", 11 | "graham-campbell/throttle": "^7.4", 12 | "illuminate/console": "^6.0", 13 | "illuminate/support": "^6.0", 14 | "react/zmq": "0.2.*|0.3.*|0.4.*" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "Askedio\\LaravelRatchet\\": "src/" 19 | } 20 | }, 21 | "extra": { 22 | "laravel": { 23 | "providers": [ 24 | "Askedio\\LaravelRatchet\\Providers\\LaravelRatchetServiceProvider" 25 | ] 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "ec4e3bee67df5cae24dda4a2ad9492ef", 8 | "packages": [ 9 | { 10 | "name": "cboden/ratchet", 11 | "version": "v0.4.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/ratchetphp/Ratchet.git", 15 | "reference": "0d31f3a8ad4795fd48397712709e55cd07f51360" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/ratchetphp/Ratchet/zipball/0d31f3a8ad4795fd48397712709e55cd07f51360", 20 | "reference": "0d31f3a8ad4795fd48397712709e55cd07f51360", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "guzzlehttp/psr7": "^1.0", 25 | "php": ">=5.4.2", 26 | "ratchet/rfc6455": "^0.2", 27 | "react/socket": "^1.0 || ^0.8 || ^0.7 || ^0.6 || ^0.5", 28 | "symfony/http-foundation": "^2.6|^3.0|^4.0", 29 | "symfony/routing": "^2.6|^3.0|^4.0" 30 | }, 31 | "require-dev": { 32 | "phpunit/phpunit": "~4.8" 33 | }, 34 | "type": "library", 35 | "autoload": { 36 | "psr-4": { 37 | "Ratchet\\": "src/Ratchet" 38 | } 39 | }, 40 | "notification-url": "https://packagist.org/downloads/", 41 | "license": [ 42 | "MIT" 43 | ], 44 | "authors": [ 45 | { 46 | "name": "Chris Boden", 47 | "email": "cboden@gmail.com", 48 | "role": "Developer" 49 | } 50 | ], 51 | "description": "PHP WebSocket library", 52 | "homepage": "http://socketo.me", 53 | "keywords": [ 54 | "Ratchet", 55 | "WebSockets", 56 | "server", 57 | "sockets", 58 | "websocket" 59 | ], 60 | "time": "2017-12-12T00:49:31+00:00" 61 | }, 62 | { 63 | "name": "doctrine/inflector", 64 | "version": "v1.3.0", 65 | "source": { 66 | "type": "git", 67 | "url": "https://github.com/doctrine/inflector.git", 68 | "reference": "5527a48b7313d15261292c149e55e26eae771b0a" 69 | }, 70 | "dist": { 71 | "type": "zip", 72 | "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", 73 | "reference": "5527a48b7313d15261292c149e55e26eae771b0a", 74 | "shasum": "" 75 | }, 76 | "require": { 77 | "php": "^7.1" 78 | }, 79 | "require-dev": { 80 | "phpunit/phpunit": "^6.2" 81 | }, 82 | "type": "library", 83 | "extra": { 84 | "branch-alias": { 85 | "dev-master": "1.3.x-dev" 86 | } 87 | }, 88 | "autoload": { 89 | "psr-4": { 90 | "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" 91 | } 92 | }, 93 | "notification-url": "https://packagist.org/downloads/", 94 | "license": [ 95 | "MIT" 96 | ], 97 | "authors": [ 98 | { 99 | "name": "Roman Borschel", 100 | "email": "roman@code-factory.org" 101 | }, 102 | { 103 | "name": "Benjamin Eberlei", 104 | "email": "kontakt@beberlei.de" 105 | }, 106 | { 107 | "name": "Guilherme Blanco", 108 | "email": "guilhermeblanco@gmail.com" 109 | }, 110 | { 111 | "name": "Jonathan Wage", 112 | "email": "jonwage@gmail.com" 113 | }, 114 | { 115 | "name": "Johannes Schmitt", 116 | "email": "schmittjoh@gmail.com" 117 | } 118 | ], 119 | "description": "Common String Manipulations with regard to casing and singular/plural rules.", 120 | "homepage": "http://www.doctrine-project.org", 121 | "keywords": [ 122 | "inflection", 123 | "pluralize", 124 | "singularize", 125 | "string" 126 | ], 127 | "time": "2018-01-09T20:05:19+00:00" 128 | }, 129 | { 130 | "name": "evenement/evenement", 131 | "version": "v2.1.0", 132 | "source": { 133 | "type": "git", 134 | "url": "https://github.com/igorw/evenement.git", 135 | "reference": "6ba9a777870ab49f417e703229d53931ed40fd7a" 136 | }, 137 | "dist": { 138 | "type": "zip", 139 | "url": "https://api.github.com/repos/igorw/evenement/zipball/6ba9a777870ab49f417e703229d53931ed40fd7a", 140 | "reference": "6ba9a777870ab49f417e703229d53931ed40fd7a", 141 | "shasum": "" 142 | }, 143 | "require": { 144 | "php": ">=5.4.0" 145 | }, 146 | "require-dev": { 147 | "phpunit/phpunit": "^6.0||^5.7||^4.8.35" 148 | }, 149 | "type": "library", 150 | "extra": { 151 | "branch-alias": { 152 | "dev-master": "2.0-dev" 153 | } 154 | }, 155 | "autoload": { 156 | "psr-0": { 157 | "Evenement": "src" 158 | } 159 | }, 160 | "notification-url": "https://packagist.org/downloads/", 161 | "license": [ 162 | "MIT" 163 | ], 164 | "authors": [ 165 | { 166 | "name": "Igor Wiedler", 167 | "email": "igor@wiedler.ch" 168 | } 169 | ], 170 | "description": "Événement is a very simple event dispatching library for PHP", 171 | "keywords": [ 172 | "event-dispatcher", 173 | "event-emitter" 174 | ], 175 | "time": "2017-07-17T17:39:19+00:00" 176 | }, 177 | { 178 | "name": "graham-campbell/throttle", 179 | "version": "v7.1.0", 180 | "source": { 181 | "type": "git", 182 | "url": "https://github.com/GrahamCampbell/Laravel-Throttle.git", 183 | "reference": "76b06d5c967fac1e9893cccd923e310961bae7b2" 184 | }, 185 | "dist": { 186 | "type": "zip", 187 | "url": "https://api.github.com/repos/GrahamCampbell/Laravel-Throttle/zipball/76b06d5c967fac1e9893cccd923e310961bae7b2", 188 | "reference": "76b06d5c967fac1e9893cccd923e310961bae7b2", 189 | "shasum": "" 190 | }, 191 | "require": { 192 | "illuminate/cache": "5.5.*|5.6.*|5.7.*", 193 | "illuminate/contracts": "5.5.*|5.6.*|5.7.*", 194 | "illuminate/http": "5.5.*|5.6.*|5.7.*", 195 | "illuminate/support": "5.5.*|5.6.*|5.7.*", 196 | "php": "^7.1.3" 197 | }, 198 | "require-dev": { 199 | "graham-campbell/analyzer": "^2.1", 200 | "graham-campbell/testbench": "^5.1", 201 | "mockery/mockery": "^1.0", 202 | "phpunit/phpunit": "^6.5|^7.0" 203 | }, 204 | "type": "library", 205 | "extra": { 206 | "branch-alias": { 207 | "dev-master": "7.1-dev" 208 | }, 209 | "laravel": { 210 | "providers": [ 211 | "GrahamCampbell\\Throttle\\ThrottleServiceProvider" 212 | ] 213 | } 214 | }, 215 | "autoload": { 216 | "psr-4": { 217 | "GrahamCampbell\\Throttle\\": "src/" 218 | } 219 | }, 220 | "notification-url": "https://packagist.org/downloads/", 221 | "license": [ 222 | "MIT" 223 | ], 224 | "authors": [ 225 | { 226 | "name": "Graham Campbell", 227 | "email": "graham@alt-three.com" 228 | } 229 | ], 230 | "description": "Throttle Is A Rate Limiter For Laravel 5", 231 | "keywords": [ 232 | "Graham Campbell", 233 | "GrahamCampbell", 234 | "Laravel Throttle", 235 | "Laravel-Throttle", 236 | "framework", 237 | "laravel", 238 | "rate limit", 239 | "throttle", 240 | "throttling" 241 | ], 242 | "time": "2018-08-23T12:18:33+00:00" 243 | }, 244 | { 245 | "name": "guzzlehttp/psr7", 246 | "version": "1.4.2", 247 | "source": { 248 | "type": "git", 249 | "url": "https://github.com/guzzle/psr7.git", 250 | "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" 251 | }, 252 | "dist": { 253 | "type": "zip", 254 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", 255 | "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", 256 | "shasum": "" 257 | }, 258 | "require": { 259 | "php": ">=5.4.0", 260 | "psr/http-message": "~1.0" 261 | }, 262 | "provide": { 263 | "psr/http-message-implementation": "1.0" 264 | }, 265 | "require-dev": { 266 | "phpunit/phpunit": "~4.0" 267 | }, 268 | "type": "library", 269 | "extra": { 270 | "branch-alias": { 271 | "dev-master": "1.4-dev" 272 | } 273 | }, 274 | "autoload": { 275 | "psr-4": { 276 | "GuzzleHttp\\Psr7\\": "src/" 277 | }, 278 | "files": [ 279 | "src/functions_include.php" 280 | ] 281 | }, 282 | "notification-url": "https://packagist.org/downloads/", 283 | "license": [ 284 | "MIT" 285 | ], 286 | "authors": [ 287 | { 288 | "name": "Michael Dowling", 289 | "email": "mtdowling@gmail.com", 290 | "homepage": "https://github.com/mtdowling" 291 | }, 292 | { 293 | "name": "Tobias Schultze", 294 | "homepage": "https://github.com/Tobion" 295 | } 296 | ], 297 | "description": "PSR-7 message implementation that also provides common utility methods", 298 | "keywords": [ 299 | "http", 300 | "message", 301 | "request", 302 | "response", 303 | "stream", 304 | "uri", 305 | "url" 306 | ], 307 | "time": "2017-03-20T17:10:46+00:00" 308 | }, 309 | { 310 | "name": "illuminate/cache", 311 | "version": "v5.7.1", 312 | "source": { 313 | "type": "git", 314 | "url": "https://github.com/illuminate/cache.git", 315 | "reference": "0d416c93433e1473b96bffe0acb25271b876eb5e" 316 | }, 317 | "dist": { 318 | "type": "zip", 319 | "url": "https://api.github.com/repos/illuminate/cache/zipball/0d416c93433e1473b96bffe0acb25271b876eb5e", 320 | "reference": "0d416c93433e1473b96bffe0acb25271b876eb5e", 321 | "shasum": "" 322 | }, 323 | "require": { 324 | "illuminate/contracts": "5.7.*", 325 | "illuminate/support": "5.7.*", 326 | "php": "^7.1.3" 327 | }, 328 | "suggest": { 329 | "illuminate/database": "Required to use the database cache driver (5.7.*).", 330 | "illuminate/filesystem": "Required to use the file cache driver (5.7.*).", 331 | "illuminate/redis": "Required to use the redis cache driver (5.7.*)." 332 | }, 333 | "type": "library", 334 | "extra": { 335 | "branch-alias": { 336 | "dev-master": "5.7-dev" 337 | } 338 | }, 339 | "autoload": { 340 | "psr-4": { 341 | "Illuminate\\Cache\\": "" 342 | } 343 | }, 344 | "notification-url": "https://packagist.org/downloads/", 345 | "license": [ 346 | "MIT" 347 | ], 348 | "authors": [ 349 | { 350 | "name": "Taylor Otwell", 351 | "email": "taylor@laravel.com" 352 | } 353 | ], 354 | "description": "The Illuminate Cache package.", 355 | "homepage": "https://laravel.com", 356 | "time": "2018-08-26T13:50:36+00:00" 357 | }, 358 | { 359 | "name": "illuminate/console", 360 | "version": "v5.7.1", 361 | "source": { 362 | "type": "git", 363 | "url": "https://github.com/illuminate/console.git", 364 | "reference": "aeac0d059af9b3dc856831d4b82e6539a3454b32" 365 | }, 366 | "dist": { 367 | "type": "zip", 368 | "url": "https://api.github.com/repos/illuminate/console/zipball/aeac0d059af9b3dc856831d4b82e6539a3454b32", 369 | "reference": "aeac0d059af9b3dc856831d4b82e6539a3454b32", 370 | "shasum": "" 371 | }, 372 | "require": { 373 | "illuminate/contracts": "5.7.*", 374 | "illuminate/support": "5.7.*", 375 | "php": "^7.1.3", 376 | "symfony/console": "^4.1" 377 | }, 378 | "suggest": { 379 | "dragonmantank/cron-expression": "Required to use scheduling component (^2.0).", 380 | "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^6.0).", 381 | "symfony/process": "Required to use scheduling component (^4.1)." 382 | }, 383 | "type": "library", 384 | "extra": { 385 | "branch-alias": { 386 | "dev-master": "5.7-dev" 387 | } 388 | }, 389 | "autoload": { 390 | "psr-4": { 391 | "Illuminate\\Console\\": "" 392 | } 393 | }, 394 | "notification-url": "https://packagist.org/downloads/", 395 | "license": [ 396 | "MIT" 397 | ], 398 | "authors": [ 399 | { 400 | "name": "Taylor Otwell", 401 | "email": "taylor@laravel.com" 402 | } 403 | ], 404 | "description": "The Illuminate Console package.", 405 | "homepage": "https://laravel.com", 406 | "time": "2018-09-04T13:13:04+00:00" 407 | }, 408 | { 409 | "name": "illuminate/contracts", 410 | "version": "v5.7.1", 411 | "source": { 412 | "type": "git", 413 | "url": "https://github.com/illuminate/contracts.git", 414 | "reference": "31112aa75ef2aadb9f4e6662d6b88ecde7a3e847" 415 | }, 416 | "dist": { 417 | "type": "zip", 418 | "url": "https://api.github.com/repos/illuminate/contracts/zipball/31112aa75ef2aadb9f4e6662d6b88ecde7a3e847", 419 | "reference": "31112aa75ef2aadb9f4e6662d6b88ecde7a3e847", 420 | "shasum": "" 421 | }, 422 | "require": { 423 | "php": "^7.1.3", 424 | "psr/container": "^1.0", 425 | "psr/simple-cache": "^1.0" 426 | }, 427 | "type": "library", 428 | "extra": { 429 | "branch-alias": { 430 | "dev-master": "5.7-dev" 431 | } 432 | }, 433 | "autoload": { 434 | "psr-4": { 435 | "Illuminate\\Contracts\\": "" 436 | } 437 | }, 438 | "notification-url": "https://packagist.org/downloads/", 439 | "license": [ 440 | "MIT" 441 | ], 442 | "authors": [ 443 | { 444 | "name": "Taylor Otwell", 445 | "email": "taylor@laravel.com" 446 | } 447 | ], 448 | "description": "The Illuminate Contracts package.", 449 | "homepage": "https://laravel.com", 450 | "time": "2018-08-31T18:58:53+00:00" 451 | }, 452 | { 453 | "name": "illuminate/filesystem", 454 | "version": "v5.7.1", 455 | "source": { 456 | "type": "git", 457 | "url": "https://github.com/illuminate/filesystem.git", 458 | "reference": "2251e31e382ddcbbcb34fddc43e7cc0afa530be8" 459 | }, 460 | "dist": { 461 | "type": "zip", 462 | "url": "https://api.github.com/repos/illuminate/filesystem/zipball/2251e31e382ddcbbcb34fddc43e7cc0afa530be8", 463 | "reference": "2251e31e382ddcbbcb34fddc43e7cc0afa530be8", 464 | "shasum": "" 465 | }, 466 | "require": { 467 | "illuminate/contracts": "5.7.*", 468 | "illuminate/support": "5.7.*", 469 | "php": "^7.1.3", 470 | "symfony/finder": "^4.1" 471 | }, 472 | "suggest": { 473 | "league/flysystem": "Required to use the Flysystem local and FTP drivers (^1.0).", 474 | "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", 475 | "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", 476 | "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (^1.0).", 477 | "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0)." 478 | }, 479 | "type": "library", 480 | "extra": { 481 | "branch-alias": { 482 | "dev-master": "5.7-dev" 483 | } 484 | }, 485 | "autoload": { 486 | "psr-4": { 487 | "Illuminate\\Filesystem\\": "" 488 | } 489 | }, 490 | "notification-url": "https://packagist.org/downloads/", 491 | "license": [ 492 | "MIT" 493 | ], 494 | "authors": [ 495 | { 496 | "name": "Taylor Otwell", 497 | "email": "taylor@laravel.com" 498 | } 499 | ], 500 | "description": "The Illuminate Filesystem package.", 501 | "homepage": "https://laravel.com", 502 | "time": "2018-08-14T19:42:44+00:00" 503 | }, 504 | { 505 | "name": "illuminate/http", 506 | "version": "v5.7.1", 507 | "source": { 508 | "type": "git", 509 | "url": "https://github.com/illuminate/http.git", 510 | "reference": "5bcf3e2d547a07bf98e0e71fa919fdaf513eee36" 511 | }, 512 | "dist": { 513 | "type": "zip", 514 | "url": "https://api.github.com/repos/illuminate/http/zipball/5bcf3e2d547a07bf98e0e71fa919fdaf513eee36", 515 | "reference": "5bcf3e2d547a07bf98e0e71fa919fdaf513eee36", 516 | "shasum": "" 517 | }, 518 | "require": { 519 | "illuminate/session": "5.7.*", 520 | "illuminate/support": "5.7.*", 521 | "php": "^7.1.3", 522 | "symfony/http-foundation": "^4.1", 523 | "symfony/http-kernel": "^4.1" 524 | }, 525 | "type": "library", 526 | "extra": { 527 | "branch-alias": { 528 | "dev-master": "5.7-dev" 529 | } 530 | }, 531 | "autoload": { 532 | "psr-4": { 533 | "Illuminate\\Http\\": "" 534 | } 535 | }, 536 | "notification-url": "https://packagist.org/downloads/", 537 | "license": [ 538 | "MIT" 539 | ], 540 | "authors": [ 541 | { 542 | "name": "Taylor Otwell", 543 | "email": "taylor@laravel.com" 544 | } 545 | ], 546 | "description": "The Illuminate Http package.", 547 | "homepage": "https://laravel.com", 548 | "time": "2018-08-28T08:47:30+00:00" 549 | }, 550 | { 551 | "name": "illuminate/session", 552 | "version": "v5.7.1", 553 | "source": { 554 | "type": "git", 555 | "url": "https://github.com/illuminate/session.git", 556 | "reference": "712f834c8b85a4f58ab40f56a359ac3e7e24c11a" 557 | }, 558 | "dist": { 559 | "type": "zip", 560 | "url": "https://api.github.com/repos/illuminate/session/zipball/712f834c8b85a4f58ab40f56a359ac3e7e24c11a", 561 | "reference": "712f834c8b85a4f58ab40f56a359ac3e7e24c11a", 562 | "shasum": "" 563 | }, 564 | "require": { 565 | "illuminate/contracts": "5.7.*", 566 | "illuminate/filesystem": "5.7.*", 567 | "illuminate/support": "5.7.*", 568 | "php": "^7.1.3", 569 | "symfony/finder": "^4.1", 570 | "symfony/http-foundation": "^4.1" 571 | }, 572 | "suggest": { 573 | "illuminate/console": "Required to use the session:table command (5.7.*)." 574 | }, 575 | "type": "library", 576 | "extra": { 577 | "branch-alias": { 578 | "dev-master": "5.7-dev" 579 | } 580 | }, 581 | "autoload": { 582 | "psr-4": { 583 | "Illuminate\\Session\\": "" 584 | } 585 | }, 586 | "notification-url": "https://packagist.org/downloads/", 587 | "license": [ 588 | "MIT" 589 | ], 590 | "authors": [ 591 | { 592 | "name": "Taylor Otwell", 593 | "email": "taylor@laravel.com" 594 | } 595 | ], 596 | "description": "The Illuminate Session package.", 597 | "homepage": "https://laravel.com", 598 | "time": "2018-07-30T13:42:51+00:00" 599 | }, 600 | { 601 | "name": "illuminate/support", 602 | "version": "v5.7.1", 603 | "source": { 604 | "type": "git", 605 | "url": "https://github.com/illuminate/support.git", 606 | "reference": "800277753547b925c9442cc4f937e3daea39c1c5" 607 | }, 608 | "dist": { 609 | "type": "zip", 610 | "url": "https://api.github.com/repos/illuminate/support/zipball/800277753547b925c9442cc4f937e3daea39c1c5", 611 | "reference": "800277753547b925c9442cc4f937e3daea39c1c5", 612 | "shasum": "" 613 | }, 614 | "require": { 615 | "doctrine/inflector": "^1.1", 616 | "ext-mbstring": "*", 617 | "illuminate/contracts": "5.7.*", 618 | "nesbot/carbon": "^1.24.1", 619 | "php": "^7.1.3" 620 | }, 621 | "conflict": { 622 | "tightenco/collect": "<5.5.33" 623 | }, 624 | "suggest": { 625 | "illuminate/filesystem": "Required to use the composer class (5.7.*).", 626 | "ramsey/uuid": "Required to use Str::uuid() (^3.7).", 627 | "symfony/process": "Required to use the composer class (^4.1).", 628 | "symfony/var-dumper": "Required to use the dd function (^4.1)." 629 | }, 630 | "type": "library", 631 | "extra": { 632 | "branch-alias": { 633 | "dev-master": "5.7-dev" 634 | } 635 | }, 636 | "autoload": { 637 | "psr-4": { 638 | "Illuminate\\Support\\": "" 639 | }, 640 | "files": [ 641 | "helpers.php" 642 | ] 643 | }, 644 | "notification-url": "https://packagist.org/downloads/", 645 | "license": [ 646 | "MIT" 647 | ], 648 | "authors": [ 649 | { 650 | "name": "Taylor Otwell", 651 | "email": "taylor@laravel.com" 652 | } 653 | ], 654 | "description": "The Illuminate Support package.", 655 | "homepage": "https://laravel.com", 656 | "time": "2018-08-29T10:50:44+00:00" 657 | }, 658 | { 659 | "name": "nesbot/carbon", 660 | "version": "1.33.0", 661 | "source": { 662 | "type": "git", 663 | "url": "https://github.com/briannesbitt/Carbon.git", 664 | "reference": "55667c1007a99e82030874b1bb14d24d07108413" 665 | }, 666 | "dist": { 667 | "type": "zip", 668 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/55667c1007a99e82030874b1bb14d24d07108413", 669 | "reference": "55667c1007a99e82030874b1bb14d24d07108413", 670 | "shasum": "" 671 | }, 672 | "require": { 673 | "php": ">=5.3.9", 674 | "symfony/translation": "~2.6 || ~3.0 || ~4.0" 675 | }, 676 | "require-dev": { 677 | "friendsofphp/php-cs-fixer": "~2", 678 | "phpunit/phpunit": "^4.8.35 || ^5.7" 679 | }, 680 | "type": "library", 681 | "extra": { 682 | "laravel": { 683 | "providers": [ 684 | "Carbon\\Laravel\\ServiceProvider" 685 | ] 686 | } 687 | }, 688 | "autoload": { 689 | "psr-4": { 690 | "": "src/" 691 | } 692 | }, 693 | "notification-url": "https://packagist.org/downloads/", 694 | "license": [ 695 | "MIT" 696 | ], 697 | "authors": [ 698 | { 699 | "name": "Brian Nesbitt", 700 | "email": "brian@nesbot.com", 701 | "homepage": "http://nesbot.com" 702 | } 703 | ], 704 | "description": "A simple API extension for DateTime.", 705 | "homepage": "http://carbon.nesbot.com", 706 | "keywords": [ 707 | "date", 708 | "datetime", 709 | "time" 710 | ], 711 | "time": "2018-08-07T08:39:47+00:00" 712 | }, 713 | { 714 | "name": "psr/container", 715 | "version": "1.0.0", 716 | "source": { 717 | "type": "git", 718 | "url": "https://github.com/php-fig/container.git", 719 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" 720 | }, 721 | "dist": { 722 | "type": "zip", 723 | "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", 724 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", 725 | "shasum": "" 726 | }, 727 | "require": { 728 | "php": ">=5.3.0" 729 | }, 730 | "type": "library", 731 | "extra": { 732 | "branch-alias": { 733 | "dev-master": "1.0.x-dev" 734 | } 735 | }, 736 | "autoload": { 737 | "psr-4": { 738 | "Psr\\Container\\": "src/" 739 | } 740 | }, 741 | "notification-url": "https://packagist.org/downloads/", 742 | "license": [ 743 | "MIT" 744 | ], 745 | "authors": [ 746 | { 747 | "name": "PHP-FIG", 748 | "homepage": "http://www.php-fig.org/" 749 | } 750 | ], 751 | "description": "Common Container Interface (PHP FIG PSR-11)", 752 | "homepage": "https://github.com/php-fig/container", 753 | "keywords": [ 754 | "PSR-11", 755 | "container", 756 | "container-interface", 757 | "container-interop", 758 | "psr" 759 | ], 760 | "time": "2017-02-14T16:28:37+00:00" 761 | }, 762 | { 763 | "name": "psr/http-message", 764 | "version": "1.0.1", 765 | "source": { 766 | "type": "git", 767 | "url": "https://github.com/php-fig/http-message.git", 768 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 769 | }, 770 | "dist": { 771 | "type": "zip", 772 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 773 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 774 | "shasum": "" 775 | }, 776 | "require": { 777 | "php": ">=5.3.0" 778 | }, 779 | "type": "library", 780 | "extra": { 781 | "branch-alias": { 782 | "dev-master": "1.0.x-dev" 783 | } 784 | }, 785 | "autoload": { 786 | "psr-4": { 787 | "Psr\\Http\\Message\\": "src/" 788 | } 789 | }, 790 | "notification-url": "https://packagist.org/downloads/", 791 | "license": [ 792 | "MIT" 793 | ], 794 | "authors": [ 795 | { 796 | "name": "PHP-FIG", 797 | "homepage": "http://www.php-fig.org/" 798 | } 799 | ], 800 | "description": "Common interface for HTTP messages", 801 | "homepage": "https://github.com/php-fig/http-message", 802 | "keywords": [ 803 | "http", 804 | "http-message", 805 | "psr", 806 | "psr-7", 807 | "request", 808 | "response" 809 | ], 810 | "time": "2016-08-06T14:39:51+00:00" 811 | }, 812 | { 813 | "name": "psr/log", 814 | "version": "1.0.2", 815 | "source": { 816 | "type": "git", 817 | "url": "https://github.com/php-fig/log.git", 818 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 819 | }, 820 | "dist": { 821 | "type": "zip", 822 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 823 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 824 | "shasum": "" 825 | }, 826 | "require": { 827 | "php": ">=5.3.0" 828 | }, 829 | "type": "library", 830 | "extra": { 831 | "branch-alias": { 832 | "dev-master": "1.0.x-dev" 833 | } 834 | }, 835 | "autoload": { 836 | "psr-4": { 837 | "Psr\\Log\\": "Psr/Log/" 838 | } 839 | }, 840 | "notification-url": "https://packagist.org/downloads/", 841 | "license": [ 842 | "MIT" 843 | ], 844 | "authors": [ 845 | { 846 | "name": "PHP-FIG", 847 | "homepage": "http://www.php-fig.org/" 848 | } 849 | ], 850 | "description": "Common interface for logging libraries", 851 | "homepage": "https://github.com/php-fig/log", 852 | "keywords": [ 853 | "log", 854 | "psr", 855 | "psr-3" 856 | ], 857 | "time": "2016-10-10T12:19:37+00:00" 858 | }, 859 | { 860 | "name": "psr/simple-cache", 861 | "version": "1.0.1", 862 | "source": { 863 | "type": "git", 864 | "url": "https://github.com/php-fig/simple-cache.git", 865 | "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" 866 | }, 867 | "dist": { 868 | "type": "zip", 869 | "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", 870 | "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", 871 | "shasum": "" 872 | }, 873 | "require": { 874 | "php": ">=5.3.0" 875 | }, 876 | "type": "library", 877 | "extra": { 878 | "branch-alias": { 879 | "dev-master": "1.0.x-dev" 880 | } 881 | }, 882 | "autoload": { 883 | "psr-4": { 884 | "Psr\\SimpleCache\\": "src/" 885 | } 886 | }, 887 | "notification-url": "https://packagist.org/downloads/", 888 | "license": [ 889 | "MIT" 890 | ], 891 | "authors": [ 892 | { 893 | "name": "PHP-FIG", 894 | "homepage": "http://www.php-fig.org/" 895 | } 896 | ], 897 | "description": "Common interfaces for simple caching", 898 | "keywords": [ 899 | "cache", 900 | "caching", 901 | "psr", 902 | "psr-16", 903 | "simple-cache" 904 | ], 905 | "time": "2017-10-23T01:57:42+00:00" 906 | }, 907 | { 908 | "name": "ratchet/rfc6455", 909 | "version": "0.2.4", 910 | "source": { 911 | "type": "git", 912 | "url": "https://github.com/ratchetphp/RFC6455.git", 913 | "reference": "1612f528c3496ad06e910d0f8b6f16ab97696706" 914 | }, 915 | "dist": { 916 | "type": "zip", 917 | "url": "https://api.github.com/repos/ratchetphp/RFC6455/zipball/1612f528c3496ad06e910d0f8b6f16ab97696706", 918 | "reference": "1612f528c3496ad06e910d0f8b6f16ab97696706", 919 | "shasum": "" 920 | }, 921 | "require": { 922 | "guzzlehttp/psr7": "^1.0", 923 | "php": ">=5.4.2" 924 | }, 925 | "require-dev": { 926 | "phpunit/phpunit": "4.8.*", 927 | "react/http": "^0.4.1", 928 | "react/socket-client": "^0.4.3" 929 | }, 930 | "type": "library", 931 | "autoload": { 932 | "psr-4": { 933 | "Ratchet\\RFC6455\\": "src" 934 | } 935 | }, 936 | "notification-url": "https://packagist.org/downloads/", 937 | "license": [ 938 | "MIT" 939 | ], 940 | "authors": [ 941 | { 942 | "name": "Chris Boden", 943 | "email": "cboden@gmail.com", 944 | "role": "Developer" 945 | } 946 | ], 947 | "description": "RFC6455 WebSocket protocol handler", 948 | "homepage": "http://socketo.me", 949 | "keywords": [ 950 | "WebSockets", 951 | "rfc6455", 952 | "websocket" 953 | ], 954 | "time": "2018-05-02T14:52:00+00:00" 955 | }, 956 | { 957 | "name": "react/cache", 958 | "version": "v0.5.0", 959 | "source": { 960 | "type": "git", 961 | "url": "https://github.com/reactphp/cache.git", 962 | "reference": "7d7da7fb7574d471904ba357b39bbf110ccdbf66" 963 | }, 964 | "dist": { 965 | "type": "zip", 966 | "url": "https://api.github.com/repos/reactphp/cache/zipball/7d7da7fb7574d471904ba357b39bbf110ccdbf66", 967 | "reference": "7d7da7fb7574d471904ba357b39bbf110ccdbf66", 968 | "shasum": "" 969 | }, 970 | "require": { 971 | "php": ">=5.3.0", 972 | "react/promise": "~2.0|~1.1" 973 | }, 974 | "require-dev": { 975 | "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35" 976 | }, 977 | "type": "library", 978 | "autoload": { 979 | "psr-4": { 980 | "React\\Cache\\": "src/" 981 | } 982 | }, 983 | "notification-url": "https://packagist.org/downloads/", 984 | "license": [ 985 | "MIT" 986 | ], 987 | "description": "Async, Promise-based cache interface for ReactPHP", 988 | "keywords": [ 989 | "cache", 990 | "caching", 991 | "promise", 992 | "reactphp" 993 | ], 994 | "time": "2018-06-25T12:52:40+00:00" 995 | }, 996 | { 997 | "name": "react/dns", 998 | "version": "v0.4.15", 999 | "source": { 1000 | "type": "git", 1001 | "url": "https://github.com/reactphp/dns.git", 1002 | "reference": "319e110a436d26a2fa137cfa3ef2063951715794" 1003 | }, 1004 | "dist": { 1005 | "type": "zip", 1006 | "url": "https://api.github.com/repos/reactphp/dns/zipball/319e110a436d26a2fa137cfa3ef2063951715794", 1007 | "reference": "319e110a436d26a2fa137cfa3ef2063951715794", 1008 | "shasum": "" 1009 | }, 1010 | "require": { 1011 | "php": ">=5.3.0", 1012 | "react/cache": "^0.5 || ^0.4 || ^0.3", 1013 | "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5", 1014 | "react/promise": "^2.1 || ^1.2.1", 1015 | "react/promise-timer": "^1.2", 1016 | "react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4.5" 1017 | }, 1018 | "require-dev": { 1019 | "clue/block-react": "^1.2", 1020 | "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35" 1021 | }, 1022 | "type": "library", 1023 | "autoload": { 1024 | "psr-4": { 1025 | "React\\Dns\\": "src" 1026 | } 1027 | }, 1028 | "notification-url": "https://packagist.org/downloads/", 1029 | "license": [ 1030 | "MIT" 1031 | ], 1032 | "description": "Async DNS resolver for ReactPHP", 1033 | "keywords": [ 1034 | "async", 1035 | "dns", 1036 | "dns-resolver", 1037 | "reactphp" 1038 | ], 1039 | "time": "2018-07-02T12:17:56+00:00" 1040 | }, 1041 | { 1042 | "name": "react/event-loop", 1043 | "version": "v0.4.3", 1044 | "source": { 1045 | "type": "git", 1046 | "url": "https://github.com/reactphp/event-loop.git", 1047 | "reference": "8bde03488ee897dc6bb3d91e4e17c353f9c5252f" 1048 | }, 1049 | "dist": { 1050 | "type": "zip", 1051 | "url": "https://api.github.com/repos/reactphp/event-loop/zipball/8bde03488ee897dc6bb3d91e4e17c353f9c5252f", 1052 | "reference": "8bde03488ee897dc6bb3d91e4e17c353f9c5252f", 1053 | "shasum": "" 1054 | }, 1055 | "require": { 1056 | "php": ">=5.4.0" 1057 | }, 1058 | "require-dev": { 1059 | "phpunit/phpunit": "~4.8" 1060 | }, 1061 | "suggest": { 1062 | "ext-event": "~1.0", 1063 | "ext-libev": "*", 1064 | "ext-libevent": ">=0.1.0" 1065 | }, 1066 | "type": "library", 1067 | "autoload": { 1068 | "psr-4": { 1069 | "React\\EventLoop\\": "src" 1070 | } 1071 | }, 1072 | "notification-url": "https://packagist.org/downloads/", 1073 | "license": [ 1074 | "MIT" 1075 | ], 1076 | "description": "Event loop abstraction layer that libraries can use for evented I/O.", 1077 | "keywords": [ 1078 | "asynchronous", 1079 | "event-loop" 1080 | ], 1081 | "time": "2017-04-27T10:56:23+00:00" 1082 | }, 1083 | { 1084 | "name": "react/promise", 1085 | "version": "v2.7.0", 1086 | "source": { 1087 | "type": "git", 1088 | "url": "https://github.com/reactphp/promise.git", 1089 | "reference": "f4edc2581617431aea50430749db55cc3fc031b3" 1090 | }, 1091 | "dist": { 1092 | "type": "zip", 1093 | "url": "https://api.github.com/repos/reactphp/promise/zipball/f4edc2581617431aea50430749db55cc3fc031b3", 1094 | "reference": "f4edc2581617431aea50430749db55cc3fc031b3", 1095 | "shasum": "" 1096 | }, 1097 | "require": { 1098 | "php": ">=5.4.0" 1099 | }, 1100 | "require-dev": { 1101 | "phpunit/phpunit": "~4.8" 1102 | }, 1103 | "type": "library", 1104 | "autoload": { 1105 | "psr-4": { 1106 | "React\\Promise\\": "src/" 1107 | }, 1108 | "files": [ 1109 | "src/functions_include.php" 1110 | ] 1111 | }, 1112 | "notification-url": "https://packagist.org/downloads/", 1113 | "license": [ 1114 | "MIT" 1115 | ], 1116 | "authors": [ 1117 | { 1118 | "name": "Jan Sorgalla", 1119 | "email": "jsorgalla@gmail.com" 1120 | } 1121 | ], 1122 | "description": "A lightweight implementation of CommonJS Promises/A for PHP", 1123 | "keywords": [ 1124 | "promise", 1125 | "promises" 1126 | ], 1127 | "time": "2018-06-13T15:59:06+00:00" 1128 | }, 1129 | { 1130 | "name": "react/promise-timer", 1131 | "version": "v1.5.0", 1132 | "source": { 1133 | "type": "git", 1134 | "url": "https://github.com/reactphp/promise-timer.git", 1135 | "reference": "a11206938ca2394dc7bb368f5da25cd4533fa603" 1136 | }, 1137 | "dist": { 1138 | "type": "zip", 1139 | "url": "https://api.github.com/repos/reactphp/promise-timer/zipball/a11206938ca2394dc7bb368f5da25cd4533fa603", 1140 | "reference": "a11206938ca2394dc7bb368f5da25cd4533fa603", 1141 | "shasum": "" 1142 | }, 1143 | "require": { 1144 | "php": ">=5.3", 1145 | "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5", 1146 | "react/promise": "^2.7.0 || ^1.2.1" 1147 | }, 1148 | "require-dev": { 1149 | "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35" 1150 | }, 1151 | "type": "library", 1152 | "autoload": { 1153 | "psr-4": { 1154 | "React\\Promise\\Timer\\": "src/" 1155 | }, 1156 | "files": [ 1157 | "src/functions.php" 1158 | ] 1159 | }, 1160 | "notification-url": "https://packagist.org/downloads/", 1161 | "license": [ 1162 | "MIT" 1163 | ], 1164 | "authors": [ 1165 | { 1166 | "name": "Christian Lück", 1167 | "email": "christian@lueck.tv" 1168 | } 1169 | ], 1170 | "description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.", 1171 | "homepage": "https://github.com/reactphp/promise-timer", 1172 | "keywords": [ 1173 | "async", 1174 | "event-loop", 1175 | "promise", 1176 | "reactphp", 1177 | "timeout", 1178 | "timer" 1179 | ], 1180 | "time": "2018-06-13T16:45:37+00:00" 1181 | }, 1182 | { 1183 | "name": "react/socket", 1184 | "version": "v1.0.0", 1185 | "source": { 1186 | "type": "git", 1187 | "url": "https://github.com/reactphp/socket.git", 1188 | "reference": "476e2644a634c6301b8111e6d22a61679e6e6bd0" 1189 | }, 1190 | "dist": { 1191 | "type": "zip", 1192 | "url": "https://api.github.com/repos/reactphp/socket/zipball/476e2644a634c6301b8111e6d22a61679e6e6bd0", 1193 | "reference": "476e2644a634c6301b8111e6d22a61679e6e6bd0", 1194 | "shasum": "" 1195 | }, 1196 | "require": { 1197 | "evenement/evenement": "^3.0 || ^2.0 || ^1.0", 1198 | "php": ">=5.3.0", 1199 | "react/dns": "^0.4.13", 1200 | "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5", 1201 | "react/promise": "^2.6.0 || ^1.2.1", 1202 | "react/promise-timer": "^1.4.0", 1203 | "react/stream": "^1.0 || ^0.7.1" 1204 | }, 1205 | "require-dev": { 1206 | "clue/block-react": "^1.2", 1207 | "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35" 1208 | }, 1209 | "type": "library", 1210 | "autoload": { 1211 | "psr-4": { 1212 | "React\\Socket\\": "src" 1213 | } 1214 | }, 1215 | "notification-url": "https://packagist.org/downloads/", 1216 | "license": [ 1217 | "MIT" 1218 | ], 1219 | "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", 1220 | "keywords": [ 1221 | "Connection", 1222 | "Socket", 1223 | "async", 1224 | "reactphp", 1225 | "stream" 1226 | ], 1227 | "time": "2018-07-11T14:38:22+00:00" 1228 | }, 1229 | { 1230 | "name": "react/stream", 1231 | "version": "v1.0.0", 1232 | "source": { 1233 | "type": "git", 1234 | "url": "https://github.com/reactphp/stream.git", 1235 | "reference": "fdd0140f42805d65bf9687636503db0b326d2244" 1236 | }, 1237 | "dist": { 1238 | "type": "zip", 1239 | "url": "https://api.github.com/repos/reactphp/stream/zipball/fdd0140f42805d65bf9687636503db0b326d2244", 1240 | "reference": "fdd0140f42805d65bf9687636503db0b326d2244", 1241 | "shasum": "" 1242 | }, 1243 | "require": { 1244 | "evenement/evenement": "^3.0 || ^2.0 || ^1.0", 1245 | "php": ">=5.3.8", 1246 | "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5" 1247 | }, 1248 | "require-dev": { 1249 | "clue/stream-filter": "~1.2", 1250 | "phpunit/phpunit": "^6.4 || ^5.7 || ^4.8.35" 1251 | }, 1252 | "type": "library", 1253 | "autoload": { 1254 | "psr-4": { 1255 | "React\\Stream\\": "src" 1256 | } 1257 | }, 1258 | "notification-url": "https://packagist.org/downloads/", 1259 | "license": [ 1260 | "MIT" 1261 | ], 1262 | "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", 1263 | "keywords": [ 1264 | "event-driven", 1265 | "io", 1266 | "non-blocking", 1267 | "pipe", 1268 | "reactphp", 1269 | "readable", 1270 | "stream", 1271 | "writable" 1272 | ], 1273 | "time": "2018-07-11T14:38:16+00:00" 1274 | }, 1275 | { 1276 | "name": "react/zmq", 1277 | "version": "v0.3.0", 1278 | "source": { 1279 | "type": "git", 1280 | "url": "https://github.com/reactphp/zmq.git", 1281 | "reference": "2865e3b23000751ed443d3f108da2735abf80716" 1282 | }, 1283 | "dist": { 1284 | "type": "zip", 1285 | "url": "https://api.github.com/repos/reactphp/zmq/zipball/2865e3b23000751ed443d3f108da2735abf80716", 1286 | "reference": "2865e3b23000751ed443d3f108da2735abf80716", 1287 | "shasum": "" 1288 | }, 1289 | "require": { 1290 | "evenement/evenement": "~2.0", 1291 | "ext-zmq": "*", 1292 | "php": ">=5.4.0", 1293 | "react/event-loop": "0.4.*" 1294 | }, 1295 | "require-dev": { 1296 | "ext-pcntl": "*" 1297 | }, 1298 | "type": "library", 1299 | "extra": { 1300 | "branch-alias": { 1301 | "dev-master": "0.4-dev" 1302 | } 1303 | }, 1304 | "autoload": { 1305 | "psr-0": { 1306 | "React\\ZMQ": "src" 1307 | } 1308 | }, 1309 | "notification-url": "https://packagist.org/downloads/", 1310 | "license": [ 1311 | "MIT" 1312 | ], 1313 | "description": "ZeroMQ bindings for React.", 1314 | "keywords": [ 1315 | "zeromq", 1316 | "zmq" 1317 | ], 1318 | "time": "2014-05-25T17:54:51+00:00" 1319 | }, 1320 | { 1321 | "name": "symfony/console", 1322 | "version": "v4.1.4", 1323 | "source": { 1324 | "type": "git", 1325 | "url": "https://github.com/symfony/console.git", 1326 | "reference": "ca80b8ced97cf07390078b29773dc384c39eee1f" 1327 | }, 1328 | "dist": { 1329 | "type": "zip", 1330 | "url": "https://api.github.com/repos/symfony/console/zipball/ca80b8ced97cf07390078b29773dc384c39eee1f", 1331 | "reference": "ca80b8ced97cf07390078b29773dc384c39eee1f", 1332 | "shasum": "" 1333 | }, 1334 | "require": { 1335 | "php": "^7.1.3", 1336 | "symfony/polyfill-mbstring": "~1.0" 1337 | }, 1338 | "conflict": { 1339 | "symfony/dependency-injection": "<3.4", 1340 | "symfony/process": "<3.3" 1341 | }, 1342 | "require-dev": { 1343 | "psr/log": "~1.0", 1344 | "symfony/config": "~3.4|~4.0", 1345 | "symfony/dependency-injection": "~3.4|~4.0", 1346 | "symfony/event-dispatcher": "~3.4|~4.0", 1347 | "symfony/lock": "~3.4|~4.0", 1348 | "symfony/process": "~3.4|~4.0" 1349 | }, 1350 | "suggest": { 1351 | "psr/log-implementation": "For using the console logger", 1352 | "symfony/event-dispatcher": "", 1353 | "symfony/lock": "", 1354 | "symfony/process": "" 1355 | }, 1356 | "type": "library", 1357 | "extra": { 1358 | "branch-alias": { 1359 | "dev-master": "4.1-dev" 1360 | } 1361 | }, 1362 | "autoload": { 1363 | "psr-4": { 1364 | "Symfony\\Component\\Console\\": "" 1365 | }, 1366 | "exclude-from-classmap": [ 1367 | "/Tests/" 1368 | ] 1369 | }, 1370 | "notification-url": "https://packagist.org/downloads/", 1371 | "license": [ 1372 | "MIT" 1373 | ], 1374 | "authors": [ 1375 | { 1376 | "name": "Fabien Potencier", 1377 | "email": "fabien@symfony.com" 1378 | }, 1379 | { 1380 | "name": "Symfony Community", 1381 | "homepage": "https://symfony.com/contributors" 1382 | } 1383 | ], 1384 | "description": "Symfony Console Component", 1385 | "homepage": "https://symfony.com", 1386 | "time": "2018-07-26T11:24:31+00:00" 1387 | }, 1388 | { 1389 | "name": "symfony/debug", 1390 | "version": "v4.1.4", 1391 | "source": { 1392 | "type": "git", 1393 | "url": "https://github.com/symfony/debug.git", 1394 | "reference": "47ead688f1f2877f3f14219670f52e4722ee7052" 1395 | }, 1396 | "dist": { 1397 | "type": "zip", 1398 | "url": "https://api.github.com/repos/symfony/debug/zipball/47ead688f1f2877f3f14219670f52e4722ee7052", 1399 | "reference": "47ead688f1f2877f3f14219670f52e4722ee7052", 1400 | "shasum": "" 1401 | }, 1402 | "require": { 1403 | "php": "^7.1.3", 1404 | "psr/log": "~1.0" 1405 | }, 1406 | "conflict": { 1407 | "symfony/http-kernel": "<3.4" 1408 | }, 1409 | "require-dev": { 1410 | "symfony/http-kernel": "~3.4|~4.0" 1411 | }, 1412 | "type": "library", 1413 | "extra": { 1414 | "branch-alias": { 1415 | "dev-master": "4.1-dev" 1416 | } 1417 | }, 1418 | "autoload": { 1419 | "psr-4": { 1420 | "Symfony\\Component\\Debug\\": "" 1421 | }, 1422 | "exclude-from-classmap": [ 1423 | "/Tests/" 1424 | ] 1425 | }, 1426 | "notification-url": "https://packagist.org/downloads/", 1427 | "license": [ 1428 | "MIT" 1429 | ], 1430 | "authors": [ 1431 | { 1432 | "name": "Fabien Potencier", 1433 | "email": "fabien@symfony.com" 1434 | }, 1435 | { 1436 | "name": "Symfony Community", 1437 | "homepage": "https://symfony.com/contributors" 1438 | } 1439 | ], 1440 | "description": "Symfony Debug Component", 1441 | "homepage": "https://symfony.com", 1442 | "time": "2018-08-03T11:13:38+00:00" 1443 | }, 1444 | { 1445 | "name": "symfony/event-dispatcher", 1446 | "version": "v4.1.4", 1447 | "source": { 1448 | "type": "git", 1449 | "url": "https://github.com/symfony/event-dispatcher.git", 1450 | "reference": "bfb30c2ad377615a463ebbc875eba64a99f6aa3e" 1451 | }, 1452 | "dist": { 1453 | "type": "zip", 1454 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bfb30c2ad377615a463ebbc875eba64a99f6aa3e", 1455 | "reference": "bfb30c2ad377615a463ebbc875eba64a99f6aa3e", 1456 | "shasum": "" 1457 | }, 1458 | "require": { 1459 | "php": "^7.1.3" 1460 | }, 1461 | "conflict": { 1462 | "symfony/dependency-injection": "<3.4" 1463 | }, 1464 | "require-dev": { 1465 | "psr/log": "~1.0", 1466 | "symfony/config": "~3.4|~4.0", 1467 | "symfony/dependency-injection": "~3.4|~4.0", 1468 | "symfony/expression-language": "~3.4|~4.0", 1469 | "symfony/stopwatch": "~3.4|~4.0" 1470 | }, 1471 | "suggest": { 1472 | "symfony/dependency-injection": "", 1473 | "symfony/http-kernel": "" 1474 | }, 1475 | "type": "library", 1476 | "extra": { 1477 | "branch-alias": { 1478 | "dev-master": "4.1-dev" 1479 | } 1480 | }, 1481 | "autoload": { 1482 | "psr-4": { 1483 | "Symfony\\Component\\EventDispatcher\\": "" 1484 | }, 1485 | "exclude-from-classmap": [ 1486 | "/Tests/" 1487 | ] 1488 | }, 1489 | "notification-url": "https://packagist.org/downloads/", 1490 | "license": [ 1491 | "MIT" 1492 | ], 1493 | "authors": [ 1494 | { 1495 | "name": "Fabien Potencier", 1496 | "email": "fabien@symfony.com" 1497 | }, 1498 | { 1499 | "name": "Symfony Community", 1500 | "homepage": "https://symfony.com/contributors" 1501 | } 1502 | ], 1503 | "description": "Symfony EventDispatcher Component", 1504 | "homepage": "https://symfony.com", 1505 | "time": "2018-07-26T09:10:45+00:00" 1506 | }, 1507 | { 1508 | "name": "symfony/finder", 1509 | "version": "v4.1.4", 1510 | "source": { 1511 | "type": "git", 1512 | "url": "https://github.com/symfony/finder.git", 1513 | "reference": "e162f1df3102d0b7472805a5a9d5db9fcf0a8068" 1514 | }, 1515 | "dist": { 1516 | "type": "zip", 1517 | "url": "https://api.github.com/repos/symfony/finder/zipball/e162f1df3102d0b7472805a5a9d5db9fcf0a8068", 1518 | "reference": "e162f1df3102d0b7472805a5a9d5db9fcf0a8068", 1519 | "shasum": "" 1520 | }, 1521 | "require": { 1522 | "php": "^7.1.3" 1523 | }, 1524 | "type": "library", 1525 | "extra": { 1526 | "branch-alias": { 1527 | "dev-master": "4.1-dev" 1528 | } 1529 | }, 1530 | "autoload": { 1531 | "psr-4": { 1532 | "Symfony\\Component\\Finder\\": "" 1533 | }, 1534 | "exclude-from-classmap": [ 1535 | "/Tests/" 1536 | ] 1537 | }, 1538 | "notification-url": "https://packagist.org/downloads/", 1539 | "license": [ 1540 | "MIT" 1541 | ], 1542 | "authors": [ 1543 | { 1544 | "name": "Fabien Potencier", 1545 | "email": "fabien@symfony.com" 1546 | }, 1547 | { 1548 | "name": "Symfony Community", 1549 | "homepage": "https://symfony.com/contributors" 1550 | } 1551 | ], 1552 | "description": "Symfony Finder Component", 1553 | "homepage": "https://symfony.com", 1554 | "time": "2018-07-26T11:24:31+00:00" 1555 | }, 1556 | { 1557 | "name": "symfony/http-foundation", 1558 | "version": "v4.1.4", 1559 | "source": { 1560 | "type": "git", 1561 | "url": "https://github.com/symfony/http-foundation.git", 1562 | "reference": "3a5c91e133b220bb882b3cd773ba91bf39989345" 1563 | }, 1564 | "dist": { 1565 | "type": "zip", 1566 | "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3a5c91e133b220bb882b3cd773ba91bf39989345", 1567 | "reference": "3a5c91e133b220bb882b3cd773ba91bf39989345", 1568 | "shasum": "" 1569 | }, 1570 | "require": { 1571 | "php": "^7.1.3", 1572 | "symfony/polyfill-mbstring": "~1.1" 1573 | }, 1574 | "require-dev": { 1575 | "predis/predis": "~1.0", 1576 | "symfony/expression-language": "~3.4|~4.0" 1577 | }, 1578 | "type": "library", 1579 | "extra": { 1580 | "branch-alias": { 1581 | "dev-master": "4.1-dev" 1582 | } 1583 | }, 1584 | "autoload": { 1585 | "psr-4": { 1586 | "Symfony\\Component\\HttpFoundation\\": "" 1587 | }, 1588 | "exclude-from-classmap": [ 1589 | "/Tests/" 1590 | ] 1591 | }, 1592 | "notification-url": "https://packagist.org/downloads/", 1593 | "license": [ 1594 | "MIT" 1595 | ], 1596 | "authors": [ 1597 | { 1598 | "name": "Fabien Potencier", 1599 | "email": "fabien@symfony.com" 1600 | }, 1601 | { 1602 | "name": "Symfony Community", 1603 | "homepage": "https://symfony.com/contributors" 1604 | } 1605 | ], 1606 | "description": "Symfony HttpFoundation Component", 1607 | "homepage": "https://symfony.com", 1608 | "time": "2018-08-27T17:47:02+00:00" 1609 | }, 1610 | { 1611 | "name": "symfony/http-kernel", 1612 | "version": "v4.1.4", 1613 | "source": { 1614 | "type": "git", 1615 | "url": "https://github.com/symfony/http-kernel.git", 1616 | "reference": "33de0a1ff2e1720096189e3ced682d7a4e8f5e35" 1617 | }, 1618 | "dist": { 1619 | "type": "zip", 1620 | "url": "https://api.github.com/repos/symfony/http-kernel/zipball/33de0a1ff2e1720096189e3ced682d7a4e8f5e35", 1621 | "reference": "33de0a1ff2e1720096189e3ced682d7a4e8f5e35", 1622 | "shasum": "" 1623 | }, 1624 | "require": { 1625 | "php": "^7.1.3", 1626 | "psr/log": "~1.0", 1627 | "symfony/debug": "~3.4|~4.0", 1628 | "symfony/event-dispatcher": "~4.1", 1629 | "symfony/http-foundation": "^4.1.1", 1630 | "symfony/polyfill-ctype": "~1.8" 1631 | }, 1632 | "conflict": { 1633 | "symfony/config": "<3.4", 1634 | "symfony/dependency-injection": "<4.1", 1635 | "symfony/var-dumper": "<4.1.1", 1636 | "twig/twig": "<1.34|<2.4,>=2" 1637 | }, 1638 | "provide": { 1639 | "psr/log-implementation": "1.0" 1640 | }, 1641 | "require-dev": { 1642 | "psr/cache": "~1.0", 1643 | "symfony/browser-kit": "~3.4|~4.0", 1644 | "symfony/config": "~3.4|~4.0", 1645 | "symfony/console": "~3.4|~4.0", 1646 | "symfony/css-selector": "~3.4|~4.0", 1647 | "symfony/dependency-injection": "^4.1", 1648 | "symfony/dom-crawler": "~3.4|~4.0", 1649 | "symfony/expression-language": "~3.4|~4.0", 1650 | "symfony/finder": "~3.4|~4.0", 1651 | "symfony/process": "~3.4|~4.0", 1652 | "symfony/routing": "~3.4|~4.0", 1653 | "symfony/stopwatch": "~3.4|~4.0", 1654 | "symfony/templating": "~3.4|~4.0", 1655 | "symfony/translation": "~3.4|~4.0", 1656 | "symfony/var-dumper": "^4.1.1" 1657 | }, 1658 | "suggest": { 1659 | "symfony/browser-kit": "", 1660 | "symfony/config": "", 1661 | "symfony/console": "", 1662 | "symfony/dependency-injection": "", 1663 | "symfony/var-dumper": "" 1664 | }, 1665 | "type": "library", 1666 | "extra": { 1667 | "branch-alias": { 1668 | "dev-master": "4.1-dev" 1669 | } 1670 | }, 1671 | "autoload": { 1672 | "psr-4": { 1673 | "Symfony\\Component\\HttpKernel\\": "" 1674 | }, 1675 | "exclude-from-classmap": [ 1676 | "/Tests/" 1677 | ] 1678 | }, 1679 | "notification-url": "https://packagist.org/downloads/", 1680 | "license": [ 1681 | "MIT" 1682 | ], 1683 | "authors": [ 1684 | { 1685 | "name": "Fabien Potencier", 1686 | "email": "fabien@symfony.com" 1687 | }, 1688 | { 1689 | "name": "Symfony Community", 1690 | "homepage": "https://symfony.com/contributors" 1691 | } 1692 | ], 1693 | "description": "Symfony HttpKernel Component", 1694 | "homepage": "https://symfony.com", 1695 | "time": "2018-08-28T06:17:42+00:00" 1696 | }, 1697 | { 1698 | "name": "symfony/polyfill-ctype", 1699 | "version": "v1.9.0", 1700 | "source": { 1701 | "type": "git", 1702 | "url": "https://github.com/symfony/polyfill-ctype.git", 1703 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" 1704 | }, 1705 | "dist": { 1706 | "type": "zip", 1707 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", 1708 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", 1709 | "shasum": "" 1710 | }, 1711 | "require": { 1712 | "php": ">=5.3.3" 1713 | }, 1714 | "suggest": { 1715 | "ext-ctype": "For best performance" 1716 | }, 1717 | "type": "library", 1718 | "extra": { 1719 | "branch-alias": { 1720 | "dev-master": "1.9-dev" 1721 | } 1722 | }, 1723 | "autoload": { 1724 | "psr-4": { 1725 | "Symfony\\Polyfill\\Ctype\\": "" 1726 | }, 1727 | "files": [ 1728 | "bootstrap.php" 1729 | ] 1730 | }, 1731 | "notification-url": "https://packagist.org/downloads/", 1732 | "license": [ 1733 | "MIT" 1734 | ], 1735 | "authors": [ 1736 | { 1737 | "name": "Symfony Community", 1738 | "homepage": "https://symfony.com/contributors" 1739 | }, 1740 | { 1741 | "name": "Gert de Pagter", 1742 | "email": "BackEndTea@gmail.com" 1743 | } 1744 | ], 1745 | "description": "Symfony polyfill for ctype functions", 1746 | "homepage": "https://symfony.com", 1747 | "keywords": [ 1748 | "compatibility", 1749 | "ctype", 1750 | "polyfill", 1751 | "portable" 1752 | ], 1753 | "time": "2018-08-06T14:22:27+00:00" 1754 | }, 1755 | { 1756 | "name": "symfony/polyfill-mbstring", 1757 | "version": "v1.9.0", 1758 | "source": { 1759 | "type": "git", 1760 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1761 | "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8" 1762 | }, 1763 | "dist": { 1764 | "type": "zip", 1765 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8", 1766 | "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8", 1767 | "shasum": "" 1768 | }, 1769 | "require": { 1770 | "php": ">=5.3.3" 1771 | }, 1772 | "suggest": { 1773 | "ext-mbstring": "For best performance" 1774 | }, 1775 | "type": "library", 1776 | "extra": { 1777 | "branch-alias": { 1778 | "dev-master": "1.9-dev" 1779 | } 1780 | }, 1781 | "autoload": { 1782 | "psr-4": { 1783 | "Symfony\\Polyfill\\Mbstring\\": "" 1784 | }, 1785 | "files": [ 1786 | "bootstrap.php" 1787 | ] 1788 | }, 1789 | "notification-url": "https://packagist.org/downloads/", 1790 | "license": [ 1791 | "MIT" 1792 | ], 1793 | "authors": [ 1794 | { 1795 | "name": "Nicolas Grekas", 1796 | "email": "p@tchwork.com" 1797 | }, 1798 | { 1799 | "name": "Symfony Community", 1800 | "homepage": "https://symfony.com/contributors" 1801 | } 1802 | ], 1803 | "description": "Symfony polyfill for the Mbstring extension", 1804 | "homepage": "https://symfony.com", 1805 | "keywords": [ 1806 | "compatibility", 1807 | "mbstring", 1808 | "polyfill", 1809 | "portable", 1810 | "shim" 1811 | ], 1812 | "time": "2018-08-06T14:22:27+00:00" 1813 | }, 1814 | { 1815 | "name": "symfony/routing", 1816 | "version": "v4.1.4", 1817 | "source": { 1818 | "type": "git", 1819 | "url": "https://github.com/symfony/routing.git", 1820 | "reference": "a5784c2ec4168018c87b38f0e4f39d2278499f51" 1821 | }, 1822 | "dist": { 1823 | "type": "zip", 1824 | "url": "https://api.github.com/repos/symfony/routing/zipball/a5784c2ec4168018c87b38f0e4f39d2278499f51", 1825 | "reference": "a5784c2ec4168018c87b38f0e4f39d2278499f51", 1826 | "shasum": "" 1827 | }, 1828 | "require": { 1829 | "php": "^7.1.3" 1830 | }, 1831 | "conflict": { 1832 | "symfony/config": "<3.4", 1833 | "symfony/dependency-injection": "<3.4", 1834 | "symfony/yaml": "<3.4" 1835 | }, 1836 | "require-dev": { 1837 | "doctrine/annotations": "~1.0", 1838 | "psr/log": "~1.0", 1839 | "symfony/config": "~3.4|~4.0", 1840 | "symfony/dependency-injection": "~3.4|~4.0", 1841 | "symfony/expression-language": "~3.4|~4.0", 1842 | "symfony/http-foundation": "~3.4|~4.0", 1843 | "symfony/yaml": "~3.4|~4.0" 1844 | }, 1845 | "suggest": { 1846 | "doctrine/annotations": "For using the annotation loader", 1847 | "symfony/config": "For using the all-in-one router or any loader", 1848 | "symfony/dependency-injection": "For loading routes from a service", 1849 | "symfony/expression-language": "For using expression matching", 1850 | "symfony/http-foundation": "For using a Symfony Request object", 1851 | "symfony/yaml": "For using the YAML loader" 1852 | }, 1853 | "type": "library", 1854 | "extra": { 1855 | "branch-alias": { 1856 | "dev-master": "4.1-dev" 1857 | } 1858 | }, 1859 | "autoload": { 1860 | "psr-4": { 1861 | "Symfony\\Component\\Routing\\": "" 1862 | }, 1863 | "exclude-from-classmap": [ 1864 | "/Tests/" 1865 | ] 1866 | }, 1867 | "notification-url": "https://packagist.org/downloads/", 1868 | "license": [ 1869 | "MIT" 1870 | ], 1871 | "authors": [ 1872 | { 1873 | "name": "Fabien Potencier", 1874 | "email": "fabien@symfony.com" 1875 | }, 1876 | { 1877 | "name": "Symfony Community", 1878 | "homepage": "https://symfony.com/contributors" 1879 | } 1880 | ], 1881 | "description": "Symfony Routing Component", 1882 | "homepage": "https://symfony.com", 1883 | "keywords": [ 1884 | "router", 1885 | "routing", 1886 | "uri", 1887 | "url" 1888 | ], 1889 | "time": "2018-08-03T07:58:40+00:00" 1890 | }, 1891 | { 1892 | "name": "symfony/translation", 1893 | "version": "v4.1.4", 1894 | "source": { 1895 | "type": "git", 1896 | "url": "https://github.com/symfony/translation.git", 1897 | "reference": "fa2182669f7983b7aa5f1a770d053f79f0ef144f" 1898 | }, 1899 | "dist": { 1900 | "type": "zip", 1901 | "url": "https://api.github.com/repos/symfony/translation/zipball/fa2182669f7983b7aa5f1a770d053f79f0ef144f", 1902 | "reference": "fa2182669f7983b7aa5f1a770d053f79f0ef144f", 1903 | "shasum": "" 1904 | }, 1905 | "require": { 1906 | "php": "^7.1.3", 1907 | "symfony/polyfill-mbstring": "~1.0" 1908 | }, 1909 | "conflict": { 1910 | "symfony/config": "<3.4", 1911 | "symfony/dependency-injection": "<3.4", 1912 | "symfony/yaml": "<3.4" 1913 | }, 1914 | "require-dev": { 1915 | "psr/log": "~1.0", 1916 | "symfony/config": "~3.4|~4.0", 1917 | "symfony/console": "~3.4|~4.0", 1918 | "symfony/dependency-injection": "~3.4|~4.0", 1919 | "symfony/finder": "~2.8|~3.0|~4.0", 1920 | "symfony/intl": "~3.4|~4.0", 1921 | "symfony/yaml": "~3.4|~4.0" 1922 | }, 1923 | "suggest": { 1924 | "psr/log-implementation": "To use logging capability in translator", 1925 | "symfony/config": "", 1926 | "symfony/yaml": "" 1927 | }, 1928 | "type": "library", 1929 | "extra": { 1930 | "branch-alias": { 1931 | "dev-master": "4.1-dev" 1932 | } 1933 | }, 1934 | "autoload": { 1935 | "psr-4": { 1936 | "Symfony\\Component\\Translation\\": "" 1937 | }, 1938 | "exclude-from-classmap": [ 1939 | "/Tests/" 1940 | ] 1941 | }, 1942 | "notification-url": "https://packagist.org/downloads/", 1943 | "license": [ 1944 | "MIT" 1945 | ], 1946 | "authors": [ 1947 | { 1948 | "name": "Fabien Potencier", 1949 | "email": "fabien@symfony.com" 1950 | }, 1951 | { 1952 | "name": "Symfony Community", 1953 | "homepage": "https://symfony.com/contributors" 1954 | } 1955 | ], 1956 | "description": "Symfony Translation Component", 1957 | "homepage": "https://symfony.com", 1958 | "time": "2018-08-07T12:45:11+00:00" 1959 | } 1960 | ], 1961 | "packages-dev": [], 1962 | "aliases": [], 1963 | "minimum-stability": "stable", 1964 | "stability-flags": [], 1965 | "prefer-stable": false, 1966 | "prefer-lowest": false, 1967 | "platform": { 1968 | "php": ">=7.1.0", 1969 | "ext-zmq": "*" 1970 | }, 1971 | "platform-dev": [] 1972 | } 1973 | -------------------------------------------------------------------------------- /src/Console/Commands/RatchetServerCommand.php: -------------------------------------------------------------------------------- 1 | class 94 | */ 95 | protected $ratchetServer; 96 | 97 | /** 98 | * WebSocket server instance. 99 | */ 100 | protected $wsServerInstance; 101 | 102 | /** 103 | * Get the console command options. 104 | * 105 | * @return array 106 | */ 107 | protected function getOptions() 108 | { 109 | return [ 110 | ['host', null, InputOption::VALUE_OPTIONAL, 'Ratchet server host', config('ratchet.host', '0.0.0.0')], 111 | ['port', 'p', InputOption::VALUE_OPTIONAL, 'Ratchet server port', config('ratchet.port', 8080)], 112 | ['class', null, InputOption::VALUE_OPTIONAL, 'Class that implements MessageComponentInterface.', config('ratchet.class')], 113 | ['driver', null, InputOption::VALUE_OPTIONAL, 'Ratchet connection driver [IoServer|WsServer|WampServer]', 'WampServer'], 114 | ['zmq', 'z', null, 'Bind server to a ZeroMQ socket (always on for WampServer)'], 115 | ['keepAlive', null, InputOption::VALUE_OPTIONAL, 'Option to enable WebSocket server keep alive [interval in seconds]', config('ratchet.keepAlive', 0)], 116 | ]; 117 | } 118 | 119 | /** 120 | * Execute the console command. 121 | */ 122 | public function handle() 123 | { 124 | $this->host = $this->option('host'); 125 | 126 | $this->port = intval($this->option('port')); 127 | 128 | $this->class = $this->option('class'); 129 | 130 | $this->driver = $this->option('driver'); 131 | 132 | $this->keepAlive = $this->option('keepAlive'); 133 | 134 | $this->tls = config('ratchet.tls', []); 135 | $peer_name = env('APP_URL'); 136 | $pos = strpos($peer_name, '://'); 137 | if ($pos !== false) { 138 | $peer_name = substr($peer_name, $pos+3); 139 | } 140 | $this->tls += [ 141 | 'peer_name' => $peer_name 142 | ]; 143 | 144 | $this->startServer(); 145 | } 146 | 147 | /** 148 | * Start the appropriate server. 149 | * 150 | * @param string $driver 151 | */ 152 | private function startServer($driver = null) 153 | { 154 | if (! $driver) { 155 | $driver = $this->driver; 156 | } 157 | 158 | $this->info(sprintf('Starting %s server on: %s:%d', $this->option('driver'), $this->host, $this->port)); 159 | 160 | $this->createServerInstance(); 161 | 162 | $this->{'start'.$driver}()->run(); 163 | } 164 | 165 | /** 166 | * Get/generate the server instance from the class provided. 167 | */ 168 | private function createServerInstance() 169 | { 170 | if (! $this->serverInstance instanceof $this->class) { 171 | $class = $this->class; 172 | $this->serverInstance = $this->ratchetServer = new $class($this); 173 | } 174 | } 175 | 176 | /** 177 | * Decorate a server instance with a blacklist instance and block any blacklisted addresses. 178 | */ 179 | private function bootWithBlacklist() 180 | { 181 | $this->serverInstance = new IpBlackList($this->serverInstance); 182 | 183 | foreach (config('ratchet.blackList') as $host) { 184 | $this->serverInstance->blockAddress($host); 185 | } 186 | } 187 | 188 | /** 189 | * Decorate the server instance with a WebSocket server. 190 | * 191 | * @param bool $withZmq 192 | * @return IoServer 193 | */ 194 | private function bootWebSocketServer($withZmq = false) 195 | { 196 | if ($withZmq || $this->option('zmq')) { 197 | $this->bootZmqConnection(); 198 | } 199 | 200 | $this->wsServerInstance = new WsServer($this->serverInstance); 201 | 202 | $this->serverInstance = new HttpServer( 203 | $this->wsServerInstance 204 | ); 205 | 206 | if($this->keepAlive > 0){ 207 | $this->wsServerInstance->enableKeepAlive($this->getEventLoop(), $this->keepAlive); 208 | } 209 | 210 | return $this->bootIoServer(); 211 | } 212 | 213 | /** 214 | * Deploy a WampServer 215 | * 216 | * @return IoServer 217 | */ 218 | private function startWampServer() 219 | { 220 | if (! $this->serverInstance instanceof RatchetWampServer) { 221 | throw new \Exception("{$this->class} must be an instance of ".RatchetWampServer::class." to create a Wamp server"); 222 | } 223 | 224 | // Decorate the server instance with a WampServer 225 | $this->serverInstance = new WampServer($this->serverInstance); 226 | 227 | return $this->bootWebSocketServer(true); 228 | } 229 | 230 | /** 231 | * Deploy a WsServer. 232 | * 233 | * @return IoServer 234 | */ 235 | private function startWsServer() 236 | { 237 | if (! $this->serverInstance instanceof RatchetWsServer) { 238 | throw new \Exception("{$this->class} must be an instance of ".RatchetWsServer::class." to create a WebSocket server"); 239 | } 240 | 241 | $this->bootWithBlacklist(); 242 | 243 | return $this->bootWebSocketServer(); 244 | } 245 | 246 | /** 247 | * Deploy an IoServer only 248 | * 249 | * @return IoServer 250 | */ 251 | private function startIoServer() 252 | { 253 | $this->bootWithBlacklist(); 254 | 255 | return $this->bootIoServer(); 256 | } 257 | 258 | /** 259 | * Create the IoServer instance to encapsulate our server in. 260 | * 261 | * @return IoServer 262 | */ 263 | private function bootIoServer() 264 | { 265 | $context = [ 266 | 'tls' => $this->tls, 267 | ]; 268 | $socket = new SocketServer($this->host.':'.$this->port, $this->getEventLoop(), $context); 269 | 270 | return new IoServer( 271 | $this->serverInstance, 272 | $socket, 273 | $this->getEventLoop() 274 | ); 275 | } 276 | 277 | /** 278 | * Boot a ZMQ listener and let the Ratchet server handle its events. 279 | */ 280 | private function bootZmqConnection() 281 | { 282 | $this->info(sprintf('Starting ZMQ listener on: %s:%s', config('ratchet.zmq.host'), config('ratchet.zmq.port'))); 283 | 284 | $context = new ZMQContext($this->getEventLoop()); 285 | $socket = $context->getSocket(config('ratchet.zmq.method', \ZMQ::SOCKET_PULL)); 286 | $socket->bind(sprintf('tcp://%s:%d', config('ratchet.zmq.host', '127.0.0.1'), config('ratchet.zmq.port', 5555))); 287 | 288 | $socket->on('messages', function ($messages) { 289 | $this->ratchetServer->onEntry($messages); 290 | }); 291 | 292 | $socket->on('message', function ($message) { 293 | $this->ratchetServer->onEntry($message); 294 | }); 295 | } 296 | 297 | /** 298 | * Generate and return a React EventLoop object. 299 | * 300 | * @return LoopInterface 301 | */ 302 | private function getEventLoop() 303 | { 304 | if (! $this->eventLoop instanceof LoopInterface) { 305 | $this->eventLoop = EventLoop::create(); 306 | } 307 | 308 | return $this->eventLoop; 309 | } 310 | } 311 | -------------------------------------------------------------------------------- /src/Examples/Pusher.php: -------------------------------------------------------------------------------- 1 | sendAll($entry[1]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Providers/LaravelRatchetServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->register(ThrottleServiceProvider::class); 19 | 20 | $this->app->singleton('command.ratchet.serve', function () { 21 | return new RatchetServerCommand(); 22 | }); 23 | 24 | $this->commands('command.ratchet.serve'); 25 | 26 | $this->mergeConfigFrom(__DIR__.'/../config/ratchet.php', 'ratchet'); 27 | } 28 | 29 | /** 30 | * Register routes, translations, views and publishers. 31 | * 32 | * @return void 33 | */ 34 | public function boot() 35 | { 36 | $this->loadTranslationsFrom(__DIR__.'/../lang', 'ratchet'); 37 | 38 | $this->publishes([ 39 | __DIR__.'/../lang' => resource_path('lang/askedio/ratchet'), 40 | ]); 41 | 42 | $this->publishes([ 43 | __DIR__.'/../config/ratchet.php' => config_path('ratchet.php'), 44 | ]); 45 | } 46 | 47 | /** 48 | * Get the services provided by the provider. 49 | * 50 | * @return array 51 | */ 52 | public function provides() 53 | { 54 | return ['command.ratchet.serve']; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/RatchetWampServer.php: -------------------------------------------------------------------------------- 1 | console = $console; 17 | } 18 | 19 | /** 20 | * @param string JSON'ified string we'll receive from ZeroMQ 21 | */ 22 | public function onEntry($entry) 23 | { 24 | $entryData = json_decode($entry, true); 25 | 26 | if (!array_key_exists($entryData['category'], $this->subscribedTopics)) { 27 | return; 28 | } 29 | 30 | $topic = $this->subscribedTopics[$entryData['category']]; 31 | 32 | $topic->broadcast($entryData); 33 | } 34 | 35 | /** 36 | * A request to subscribe to a topic has been made. 37 | * 38 | * @param \Ratchet\ConnectionInterface $conn 39 | * @param string|Topic $topic The topic to subscribe to 40 | */ 41 | public function onSubscribe(ConnectionInterface $conn, $topic) 42 | { 43 | $this->console->info("onSubscribe: {$conn->WAMP->sessionId} topic: $topic {$topic->count()}"); 44 | 45 | if (!array_key_exists($topic->getId(), $this->subscribedTopics)) { 46 | $this->subscribedTopics[$topic->getId()] = $topic; 47 | $this->console->info("subscribed to topic $topic"); 48 | } 49 | } 50 | 51 | /** 52 | * A request to unsubscribe from a topic has been made. 53 | * 54 | * @param \Ratchet\ConnectionInterface $conn 55 | * @param string|Topic $topic The topic to unsubscribe from 56 | */ 57 | public function onUnSubscribe(ConnectionInterface $conn, $topic) 58 | { 59 | $this->console->info("onUnSubscribe: topic: $topic {$topic->count()}"); 60 | } 61 | 62 | /** 63 | * When a new connection is opened it will be passed to this method. 64 | * 65 | * @param ConnectionInterface $conn The socket/connection that just connected to your application 66 | * 67 | * @throws \Exception 68 | */ 69 | public function onOpen(ConnectionInterface $conn) 70 | { 71 | $this->console->info("onOpen ({$conn->WAMP->sessionId})"); 72 | } 73 | 74 | /** 75 | * This is called before or after a socket is closed (depends on how it's closed). SendMessage to $conn will not result in an error if it has already been closed. 76 | * 77 | * @param ConnectionInterface $conn The socket/connection that is closing/closed 78 | * 79 | * @throws \Exception 80 | */ 81 | public function onClose(ConnectionInterface $conn) 82 | { 83 | $this->console->info("onClose ({$conn->WAMP->sessionId})"); 84 | } 85 | 86 | /** 87 | * An RPC call has been received. 88 | * 89 | * @param \Ratchet\ConnectionInterface $conn 90 | * @param string $id The unique ID of the RPC, required to respond to 91 | * @param string|Topic $topic The topic to execute the call against 92 | * @param array $params Call parameters received from the client 93 | */ 94 | public function onCall(ConnectionInterface $conn, $id, $topic, array $params) 95 | { 96 | $this->console->info('onCall'); 97 | $conn->callError($id, $topic, 'You are not allowed to make calls')->close(); 98 | } 99 | 100 | /** 101 | * A client is attempting to publish content to a subscribed connections on a URI. 102 | * 103 | * @param \Ratchet\ConnectionInterface $conn 104 | * @param string|Topic $topic The topic the user has attempted to publish to 105 | * @param string $event Payload of the publish 106 | * @param array $exclude A list of session IDs the message should be excluded from (blacklist) 107 | * @param array $eligible A list of session Ids the message should be send to (whitelist) 108 | */ 109 | public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) 110 | { 111 | $this->console->info('onPublish'); 112 | } 113 | 114 | /** 115 | * If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown, 116 | * the Exception is sent back down the stack, handled by the Server and bubbled back up the application through this method. 117 | * 118 | * @param ConnectionInterface $conn 119 | * @param \Exception $e 120 | * 121 | * @throws \Exception 122 | */ 123 | public function onError(ConnectionInterface $conn, \Exception $e) 124 | { 125 | $this->console->info('onError'.$e->getMessage()); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/RatchetWsServer.php: -------------------------------------------------------------------------------- 1 | clients = new \SplObjectStorage(); 55 | $this->console = $console; 56 | } 57 | 58 | /** 59 | * Perform action on open. 60 | * 61 | * @param ConnectionInterface $conn [description] 62 | * 63 | * @return [type] [description] 64 | */ 65 | public function onOpen(ConnectionInterface $conn) 66 | { 67 | $this->conn = $conn; 68 | 69 | $this->attach()->throttle()->limit(); 70 | } 71 | 72 | protected function attach() 73 | { 74 | $this->clients->attach($this->conn); 75 | $this->console->info(sprintf('Connected: %d', $this->conn->resourceId)); 76 | 77 | $this->connections = count($this->clients); 78 | $this->console->info(sprintf('%d %s', $this->connections, Str::plural('connection', $this->connections))); 79 | 80 | return $this; 81 | } 82 | 83 | /** 84 | * Throttle connections. 85 | * 86 | * @return [type] [description] 87 | */ 88 | protected function throttle() 89 | { 90 | if ($this->isThrottled($this->conn, 'onOpen')) { 91 | $this->console->info(sprintf('Connection throttled: %d', $this->conn->resourceId)); 92 | $this->conn->send(trans('ratchet::messages.tooManyConnectionAttempts')); 93 | $this->throttled = true; 94 | $this->conn->close(); 95 | } 96 | 97 | return $this; 98 | } 99 | 100 | /** 101 | * Limit connections. 102 | * 103 | * @return [type] [description] 104 | */ 105 | protected function limit() 106 | { 107 | if (($connectionLimit = config('ratchet.connectionLimit')) && $this->connections - 1 >= $connectionLimit) { 108 | $this->console->info(sprintf('To many connections: %d of %d', $this->connections - 1, $connectionLimit)); 109 | $this->conn->send(trans('ratchet::messages.tooManyConnections')); 110 | $this->conn->close(); 111 | } 112 | 113 | return $this; 114 | } 115 | 116 | /** 117 | * Check if the called function is throttled. 118 | * 119 | * @param [type] $conn [description] 120 | * @param [type] $setting [description] 121 | * 122 | * @return bool [description] 123 | */ 124 | protected function isThrottled($conn, $setting) 125 | { 126 | $connectionThrottle = explode(':', config(sprintf('ratchet.throttle.%s', $setting))); 127 | 128 | return !Throttle::attempt( 129 | [ 130 | 'ip' => $conn->remoteAddress, 131 | 'route' => $setting, 132 | ], 133 | (int) $connectionThrottle[0], 134 | (int) $connectionThrottle[1] 135 | ); 136 | } 137 | 138 | /** 139 | * Perform action on message. 140 | * 141 | * @param ConnectionInterface $conn [description] 142 | * @param [type] $input [description] 143 | * 144 | * @return [type] [description] 145 | */ 146 | public function onMessage(ConnectionInterface $conn, $input) 147 | { 148 | $this->console->comment(sprintf('Message from %d: %s', $conn->resourceId, $input)); 149 | 150 | if ($this->isThrottled($conn, 'onMessage')) { 151 | $this->console->info(sprintf('Message throttled: %d', $conn->resourceId)); 152 | $this->send($conn, trans('ratchet::messages.tooManyMessages')); 153 | $this->throttled = true; 154 | 155 | if (config('ratchet.abortOnMessageThrottle')) { 156 | $this->abort($conn); 157 | } 158 | } 159 | } 160 | 161 | /** 162 | * Perform action on close. 163 | * 164 | * @param ConnectionInterface $conn [description] 165 | * 166 | * @return [type] [description] 167 | */ 168 | public function onClose(ConnectionInterface $conn) 169 | { 170 | $this->clients->detach($conn); 171 | $this->console->error(sprintf('Disconnected: %d', $conn->resourceId)); 172 | } 173 | 174 | /** 175 | * Perform action on error. 176 | * 177 | * @param ConnectionInterface $conn [description] 178 | * @param Exception $exception [description] 179 | * 180 | * @return [type] [description] 181 | */ 182 | public function onError(ConnectionInterface $conn, \Exception $exception) 183 | { 184 | $message = $exception->getMessage(); 185 | $conn->close(); 186 | $this->console->error(sprintf('Error: %s', $message)); 187 | } 188 | 189 | /** 190 | * Close the current connection. 191 | * 192 | * @return [type] [description] 193 | */ 194 | public function abort(ConnectionInterface $conn) 195 | { 196 | $this->clients->detach($conn); 197 | $conn->close(); 198 | } 199 | 200 | /** 201 | * Send a message to the current connection. 202 | * 203 | * @param [type] $message [description] 204 | * 205 | * @return [type] [description] 206 | */ 207 | public function send(ConnectionInterface $conn, $message) 208 | { 209 | $conn->send($message); 210 | } 211 | 212 | /** 213 | * Send a message to all connections. 214 | * 215 | * @param [type] $message [description] 216 | * 217 | * @return [type] [description] 218 | */ 219 | public function sendAll($message) 220 | { 221 | foreach ($this->clients as $client) { 222 | $client->send($message); 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/config/ratchet.php: -------------------------------------------------------------------------------- 1 | \Askedio\LaravelRatchet\Examples\Pusher::class, 15 | 'host' => '0.0.0.0', // Prepend tls:// to host address to enable SSL/TLS. Example: tls://0.0.0.0 16 | 'port' => '8080', 17 | 'connectionLimit' => false, 18 | 'throttle' => [ 19 | 'onOpen' => '5:1', 20 | 'onMessage' => '20:1', 21 | ], 22 | 'abortOnMessageThrottle' => false, 23 | 'blackList' => [], 24 | 'zmq' => [ 25 | 'host' => '127.0.0.1', 26 | 'port' => 5555, 27 | 'method' => \ZMQ::SOCKET_PULL, 28 | ], 29 | /** 30 | * Look up http://php.net/manual/en/context.ssl.php to configure SSL/TLS. 31 | */ 32 | 'tls' => [ 33 | // 'peer_name' => '', 34 | // 'verify_peer' => true, 35 | // 'verify_peer_name' => true, 36 | // 'allow_self_signed' => false, 37 | 'cafile' => env('SSL_CA_FILE', ''), 38 | 'capath' => env('SSL_CA_PATH', ''), 39 | 'local_cert' => env('SSL_PUBLIC_CERT', ''), 40 | 'local_pk' => env('SSL_PRIVATE_KEY', ''), 41 | 'passphrase' => env('SSL_PASSPHRASE', ''), 42 | ], 43 | ]; 44 | -------------------------------------------------------------------------------- /src/lang/en/messages.php: -------------------------------------------------------------------------------- 1 | json_encode(['error' => 'tooManyConnectionAttempts']), 15 | 'tooManyConnections' => json_encode(['error' => 'tooManyConnections']), 16 | 'tooManyMessages' => json_encode(['error' => 'tooManyMessages']), 17 | ]; 18 | -------------------------------------------------------------------------------- /tests/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * node index.js 3 | * - A simple echo test. 4 | */ 5 | 6 | 7 | var WebSocket = require('ws'); 8 | var ws = new WebSocket('ws://0.0.0.0:8080'); 9 | 10 | ws.on('open', function open() { 11 | console.log('connected'); 12 | }); 13 | 14 | ws.on('close', function close() { 15 | console.log('disconnected'); 16 | }); 17 | 18 | ws.on('message', function message(data, flags) { 19 | console.log(data); 20 | 21 | setTimeout(function timeout() { 22 | ws.send(Date.now().toString(), {mask: true}); 23 | }, 500); 24 | }); 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/pubsub.html: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------