puff / websocket-server
Fiber-based WebSocket application for PHP Unison Fiber Framework
Requires
- php: ^8.2
- psr/log: ^3.0
- puff/application: dev-main
- puff/async: dev-main
- puff/config: dev-main
- puff/server: dev-main
Requires (Dev)
- phpunit/phpunit: ^11.0
This package is auto-updated.
Last update: 2026-08-28 10:59:33 UTC
README
Fiber-based RFC 6455 WebSocket server for Puff. It reuses puff/server for non-blocking TCP I/O and provides strict handshakes, masked frame parsing, fragmentation, Ping/Pong, graceful close frames and ordered per-connection message handling. Composer discovery mounts Puff\WebsocketServer\WebSocketApplication automatically.
$app = new Puff\Application\Application($config); $app->run(); // Starts every installed application on one shared event loop.
The package publishes config/websocket.server.php; its values are available under websocket.server. The default endpoint is ws://127.0.0.1:8791. Incoming messages are echoed unless handler or routes is configured.
return [ 'addr' => '127.0.0.1:8791', 'routes' => dirname(__DIR__) . '/app/websocket.php', 'workers' => 1, 'max_message_size' => 2 * 1024 * 1024, 'max_handshake_size' => 16 * 1024, 'max_headers' => 100, 'max_pending_messages' => 128, 'allowed_origins' => ['https://example.com'], 'protocols' => ['json'], ];
An empty allowed_origins list accepts any syntactically valid Origin. Configure an explicit list for browser-facing production services. Messages from one connection run sequentially; separate connections can run concurrently.
Routes are grouped by handshake path and then by message event:
return [ '/chat' => [ 'events' => [ 'message.send' => [ChatController::class, 'send'], ], 'lifecycle' => [ 'open' => [ChatController::class, 'open'], 'close' => [ChatController::class, 'close'], ], ], '*' => [ 'events' => [ 'ping' => [SystemController::class, 'ping'], ], ], ];
Clients send JSON messages such as {"event":"message.send","data":{"message":"Hello"}}. Controller arguments are resolved by the application container. The following values are injectable by name or type:
data,event, andpathHandshake $handshakeheaders,query, andcookiesConnection $connectionServer $server
Arrays and objects returned by controllers are encoded as JSON. Event routing accepts text JSON frames; use a custom HandlerInterface for binary protocols.
Custom handler
Implement HandlerInterface when the connection lifecycle or binary frames require direct control:
use Puff\Server\Connection; use Puff\WebsocketServer\Frame; use Puff\WebsocketServer\Handshake; use Puff\WebsocketServer\HandlerInterface; use Puff\WebsocketServer\Server; final class SocketHandler implements HandlerInterface { public function open(Handshake $handshake, Connection $connection, Server $server): mixed { return null; } public function message( Handshake $handshake, string $payload, int $opcode, Connection $connection, Server $server, ): mixed { return $opcode === Frame::BINARY ? $payload : strtoupper($payload); } public function close(Handshake $handshake, Connection $connection, Server $server): void { } }
Throw HandshakeException from open() to reject a connection before the 101 Switching Protocols response.