Skip to content

Commit d713c75

Browse files
committed
Update readme
1 parent ee45d5a commit d713c75

File tree

1 file changed

+70
-17
lines changed

1 file changed

+70
-17
lines changed

README.md

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
# amphp/websocket-server
22

33
AMPHP is a collection of event-driven libraries for PHP designed with fibers and concurrency in mind.
4-
This 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).
4+
This 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).
5+
6+
## Requirements
7+
8+
- PHP 8.1+
59

610
## Installation
711

@@ -13,14 +17,51 @@ composer require amphp/websocket-server
1317

1418
## Documentation
1519

16-
The documentation for this library is currently a work in progress. Pull Requests to improve the documentation are
17-
always welcome!
20+
The 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.
1821

19-
## Requirements
22+
Creating a `Websocket` endpoint requires the user to specify a number of parameters:
23+
- The `Amp\Http\Server\HttpServer` instance which will be used
24+
- A [PSR-3](https://www.php-fig.org/psr/psr-3/) logger instance
25+
- A `WebsocketAcceptor` to accept client connections
26+
- A `WebsocketClientHandler` to handle client connections once accepted
27+
- An optional `WebsocketCompressionContextFactory` if compression should be enabled on the server
28+
- An optional `WebsocketClientFactory` if custom logic is needed when creating `WebsocketClient` instances
2029

21-
- PHP 8.1+
30+
### Accepting Client Connections
31+
32+
Accepting client connections is performed by an instance of `WebsocketAcceptor`. This library provides two implementations: and `AllowOriginAcceptor`
33+
- `Rfc6455Acceptor`: Accepts client connections based on [RFC6455](https://datatracker.ietf.org/doc/html/rfc6455) with no further restrictions.
34+
- `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).
35+
36+
### Handling Client Connections
37+
38+
Once established, a WebSocket connection is handled by an implementation of `WebsocketClientHandler`. This is where your WebSocket application logic will go.
39+
40+
`WebsocketClientHanler` has a single method which must be implemented, `handleClient()`.
41+
42+
```php
43+
public function handleClient(
44+
WebsocketClient $client,
45+
Request $request,
46+
Response $response,
47+
): void;
48+
```
2249

23-
## Example
50+
After 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.
51+
52+
This method should not return until the client connection should be closed. This method generally should not throw an exception. 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.
53+
54+
### Gateways
55+
56+
A `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.
57+
58+
### Compression
59+
60+
Message 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).
61+
62+
### Example Server
63+
64+
The 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.
2465

2566
```php
2667
<?php
@@ -44,13 +85,13 @@ use Amp\Websocket\Server\WebsocketClientHandler;
4485
use Amp\Websocket\Server\WebsocketGateway;
4586
use Amp\Websocket\WebsocketClient;
4687
use Monolog\Logger;
47-
use Psr\Log\NullLogger;
88+
use function Amp\trapSignal;
4889
use function Amp\ByteStream\getStdout;
4990

5091
require __DIR__ . '/../../vendor/autoload.php';
5192

5293
$logHandler = new StreamHandler(getStdout());
53-
$logHandler->setFormatter(new ConsoleFormatter);
94+
$logHandler->setFormatter(new ConsoleFormatter());
5495
$logger = new Logger('server');
5596
$logger->pushHandler($logHandler);
5697

@@ -61,7 +102,7 @@ $server->expose(new Socket\InternetAddress('[::1]', 1337));
61102

62103
$errorHandler = new DefaultErrorHandler();
63104

64-
$handshakeHandler = new AllowOriginAcceptor(
105+
$acceptor = new AllowOriginAcceptor(
65106
['http://localhost:1337', 'http://127.0.0.1:1337', 'http://[::1]:1337'],
66107
);
67108

@@ -73,13 +114,13 @@ $clientHandler = new class implements WebsocketClientHandler {
73114

74115
public function handleClient(
75116
WebsocketClient $client,
76-
Request $request,
77-
Response $response
117+
Request $request,
118+
Response $response,
78119
): void {
79120
$this->gateway->addClient($client);
80121

81-
while ($message = $client->receive()) {
82-
$this->gateway->broadcastText(\sprintf(
122+
foreach ($client as $message) {
123+
$this->gateway->broadcastText(sprintf(
83124
'%d: %s',
84125
$client->getId(),
85126
(string) $message,
@@ -88,18 +129,30 @@ $clientHandler = new class implements WebsocketClientHandler {
88129
}
89130
};
90131

91-
$websocket = new Websocket($server, $logger, $handshakeHandler, $clientHandler);
132+
$websocket = new Websocket($server, $logger, $acceptor, $clientHandler);
92133

93-
$router = new Router($server, new NullLogger(), $errorHandler);
134+
$router = new Router($server, $logger, $errorHandler);
94135
$router->addRoute('GET', '/broadcast', $websocket);
95136
$router->setFallback(new DocumentRoot($server, $errorHandler, __DIR__ . '/public'));
96137

97138
$server->start($router, $errorHandler);
98139

99140
// Await SIGINT or SIGTERM to be received.
100-
$signal = Amp\trapSignal([\SIGINT, \SIGTERM]);
141+
$signal = trapSignal([SIGINT, SIGTERM]);
101142

102-
$logger->info(\sprintf("Received signal %d, stopping HTTP server", $signal));
143+
$logger->info(sprintf("Received signal %d, stopping HTTP server", $signal));
103144

104145
$server->stop();
105146
```
147+
148+
## Versioning
149+
150+
`amphp/websocket-server` follows the [semver](http://semver.org/) semantic versioning specification like all other `amphp` packages.
151+
152+
## Security
153+
154+
If you discover any security related issues, please use the private security issue reporter instead of using the public issue tracker.
155+
156+
## License
157+
158+
The MIT License (MIT). Please see [`LICENSE`](./LICENSE) for more information.

0 commit comments

Comments
 (0)