{"id":19665910,"url":"https://github.com/amphp/websocket-server","last_synced_at":"2025-04-05T09:08:55.605Z","repository":{"id":56947343,"uuid":"124775290","full_name":"amphp/websocket-server","owner":"amphp","description":"WebSocket component for PHP based on the Amp HTTP server.","archived":false,"fork":false,"pushed_at":"2024-02-16T22:55:24.000Z","size":342,"stargazers_count":119,"open_issues_count":4,"forks_count":17,"subscribers_count":10,"default_branch":"4.x","last_synced_at":"2025-03-29T08:08:15.679Z","etag":null,"topics":["amphp","async","http","php","rfc-6455","websocket","websockets"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amphp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-11T16:20:54.000Z","updated_at":"2025-03-02T14:28:22.000Z","dependencies_parsed_at":"2023-12-28T06:38:12.809Z","dependency_job_id":"fac3c739-b4fb-490e-8f87-990db1dad96f","html_url":"https://github.com/amphp/websocket-server","commit_stats":{"total_commits":157,"total_committers":5,"mean_commits":31.4,"dds":0.3312101910828026,"last_synced_commit":"4c4e57cb5c1568e778759c21acc2b6a4ad7d3adf"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amphp%2Fwebsocket-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amphp%2Fwebsocket-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amphp%2Fwebsocket-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amphp%2Fwebsocket-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amphp","download_url":"https://codeload.github.com/amphp/websocket-server/tar.gz/refs/heads/4.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247312081,"owners_count":20918344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amphp","async","http","php","rfc-6455","websocket","websockets"],"created_at":"2024-11-11T16:25:25.192Z","updated_at":"2025-04-05T09:08:55.164Z","avatar_url":"https://github.com/amphp.png","language":"PHP","funding_links":[],"categories":["Websocket"],"sub_categories":["Tunnel"],"readme":"# amphp/websocket-server\n\nAMPHP is a collection of event-driven libraries for PHP designed with fibers and concurrency in mind.\nThis library provides a [`RequestHandler`](https://amphp.org/http-server/classes/request-handler) to easily handle WebSocket connections using [`amphp/http-server`](https://github.com/amphp/http-server).\n\n## Requirements\n\n- PHP 8.1+\n\n## Installation\n\nThis package can be installed as a [Composer](https://getcomposer.org) dependency.\n\n```\ncomposer require amphp/websocket-server\n```\n\n## Documentation\n\nThe primary component of this library is the `Websocket` class, an implementation of the `RequestHandler` interface from [`amphp/http-server`](https://github.com/amphp/http-server). Endpoints using the `Websocket` request handler will upgrade incoming requests to a WebSocket connection.\n\nCreating a `Websocket` endpoint requires the user to specify a number of parameters:\n- The `Amp\\Http\\Server\\HttpServer` instance which will be used\n- A [PSR-3](https://www.php-fig.org/psr/psr-3/) logger instance\n- A `WebsocketAcceptor` to accept client connections\n- A `WebsocketClientHandler` to handle client connections once accepted\n- An optional `WebsocketCompressionContextFactory` if compression should be enabled on the server\n- An optional `WebsocketClientFactory` if custom logic is needed when creating `WebsocketClient` instances\n\n### Accepting Client Connections\n\nAccepting client connections is performed by an instance of `WebsocketAcceptor`. This library provides two implementations:\n- `Rfc6455Acceptor`: Accepts client connections based on [RFC6455](https://datatracker.ietf.org/doc/html/rfc6455) with no further restrictions.\n- `AllowOriginAcceptor`: Requires the `\"Origin\"` header of the HTTP request to match one of the allowed origins provided to the constructor. Accepting the connection is then delegated to another `WebsocketAcceptor` implementation (`Rfc6455Acceptor` by default).\n\n### Handling Client Connections\n\nOnce established, a WebSocket connection is handled by an implementation of `WebsocketClientHandler`. Your application logic will be within an implementation of this interface.\n\n`WebsocketClientHanler` has a single method which must be implemented, `handleClient()`.\n\n```php\npublic function handleClient(\n    WebsocketClient $client,\n    Request $request,\n    Response $response,\n): void;\n```\n\nAfter accepting a client connection, `WebsocketClientHandler::handleClient()` is invoked with the `WebsocketClient` instance, as well as the `Request` and `Response` instances which were used to establish the connection.\n\nThis method should not return until the client connection should be closed. Exceptions should not be thrown from this method. Any exception thrown will close the connection with an `UNEXPECTED_SERVER_ERROR` error code (1011) and forward the exception to the HTTP server logger. There is one exception to this: `WebsocketClosedException`, which is thrown when receiving or sending a message to a connection fails due to the connection being closed. If `WebsocketClosedException` is thrown from `handleClient()`, the exception is ignored.\n\n### Gateways\n\nA `WebsocketGateway` provides a means of collecting WebSocket clients into related groups to allow broadcasting a single message efficiently (and asynchronously) to multiple clients. `WebsocketClientGateway` provided by this library may be used by one or more client handlers to group clients from one or more endpoints (or multiple may be used on a single endpoint if desired). See the [example server](#example-server) below for basic usage of a gateway in a client handler. Clients added to the gateway are automatically removed when the client connection is closed.\n\n### Compression\n\nMessage compression may optionally be enabled on individual WebSocket endpoints by passing an instance of `WebsocketCompressionContextFactory` to the `Websocket` constructor. Currently, the only implementation available is `Rfc7692CompressionFactory` which implements compression based on [RFC-7692](https://datatracker.ietf.org/doc/html/rfc7692).\n\n### Example Server\n\nThe server below creates a simple WebSocket endpoint which broadcasts all received messages to all other connected clients. [`amphp/http-server-router`](https://github.com/amphp/http-server-router) and [`amphp/http-server-static-content`](https://github.com/amphp/http-server-static-content) are used to attach the `Websocket` handler to a specific route and to serve static files from the `/public` directory if the route is not defined in the router.\n\n```php\n\u003c?php\n\n// Note that this example requires amphp/http-server-router,\n// amphp/http-server-static-content and amphp/log to be installed.\n\nuse Amp\\Http\\Server\\DefaultErrorHandler;\nuse Amp\\Http\\Server\\Request;\nuse Amp\\Http\\Server\\Response;\nuse Amp\\Http\\Server\\Router;\nuse Amp\\Http\\Server\\SocketHttpServer;\nuse Amp\\Http\\Server\\StaticContent\\DocumentRoot;\nuse Amp\\Log\\ConsoleFormatter;\nuse Amp\\Log\\StreamHandler;\nuse Amp\\Socket;\nuse Amp\\Websocket\\Server\\AllowOriginAcceptor;\nuse Amp\\Websocket\\Server\\Websocket;\nuse Amp\\Websocket\\Server\\WebsocketClientGateway;\nuse Amp\\Websocket\\Server\\WebsocketClientHandler;\nuse Amp\\Websocket\\Server\\WebsocketGateway;\nuse Amp\\Websocket\\WebsocketClient;\nuse Monolog\\Logger;\nuse function Amp\\trapSignal;\nuse function Amp\\ByteStream\\getStdout;\n\nrequire __DIR__ . '/../../vendor/autoload.php';\n\n$logHandler = new StreamHandler(getStdout());\n$logHandler-\u003esetFormatter(new ConsoleFormatter());\n$logger = new Logger('server');\n$logger-\u003epushHandler($logHandler);\n\n$server = SocketHttpServer::createForDirectAccess($logger);\n\n$server-\u003eexpose(new Socket\\InternetAddress('127.0.0.1', 1337));\n$server-\u003eexpose(new Socket\\InternetAddress('[::1]', 1337));\n\n$errorHandler = new DefaultErrorHandler();\n\n$acceptor = new AllowOriginAcceptor(\n    ['http://localhost:1337', 'http://127.0.0.1:1337', 'http://[::1]:1337'],\n);\n\n$clientHandler = new class implements WebsocketClientHandler {\n    public function __construct(\n        private readonly WebsocketGateway $gateway = new WebsocketClientGateway(),\n    ) {\n    }\n\n    public function handleClient(\n        WebsocketClient $client,\n        Request $request,\n        Response $response,\n    ): void {\n        $this-\u003egateway-\u003eaddClient($client);\n\n        foreach ($client as $message) {\n            $this-\u003egateway-\u003ebroadcastText(sprintf(\n                '%d: %s',\n                $client-\u003egetId(),\n                (string) $message,\n            ));\n        }\n    }\n};\n\n$websocket = new Websocket($server, $logger, $acceptor, $clientHandler);\n\n$router = new Router($server, $logger, $errorHandler);\n$router-\u003eaddRoute('GET', '/broadcast', $websocket);\n$router-\u003esetFallback(new DocumentRoot($server, $errorHandler, __DIR__ . '/public'));\n\n$server-\u003estart($router, $errorHandler);\n\n// Await SIGINT or SIGTERM to be received.\n$signal = trapSignal([SIGINT, SIGTERM]);\n\n$logger-\u003einfo(sprintf(\"Received signal %d, stopping HTTP server\", $signal));\n\n$server-\u003estop();\n```\n\n## Versioning\n\n`amphp/websocket-server` follows the [semver](http://semver.org/) semantic versioning specification like all other `amphp` packages.\n\n## Security\n\nIf you discover any security related issues, please use the private security issue reporter instead of using the public issue tracker.\n\n## License\n\nThe MIT License (MIT). Please see [`LICENSE`](./LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famphp%2Fwebsocket-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famphp%2Fwebsocket-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famphp%2Fwebsocket-server/lists"}