phasync
WebSocket / accept

Method

WebSocket::accept

Answer the handshake and return the open connection, or null after refusing the request.

Description#

public static WebSocket::accept(
    ClientRequest $request,
    array $subprotocols = [],
    ?array $origins = null,
    int $maxMessage = self::MAX_MESSAGE
): ?WebSocket

The request must be a GET over HTTP/1.1 with Upgrade: websocket, Connection: upgrade, version 13 and a key of 16 bytes (base64), and no body. Otherwise the response is 426 (not a WebSocket request at all: Upgrade or Connection is missing), 400 (a WebSocket request that is not valid, naming version 13) or 403 (an Origin that $origins does not allow), and null is returned. The handler returns then. No extension (permessage-deflate) is accepted.

The caller reads with WebSocket::receive and must call WebSocket::end when done: the close frame is written by end(), before the handler returns. $onMessage is not called.

Parameters#

$request ClientRequest
$subprotocols array = []
The subprotocols you speak, in your order of preference: the first one the client offered is chosen, and none when they share none
$origins ?array = null
The allowed Origins (compared case-insensitively), null: any. A client that sends none (not a browser) is let through.
$maxMessage int = self::MAX_MESSAGE
The largest message received, in bytes; a larger one closes with 1009

Return values#

?WebSocket

Examples#

Example 1Read with receive() and close yourself
use Swerve\ClientRequest;
use Swerve\RequestHandler;
use Swerve\WebSocket;

$app = new RequestHandler(function (ClientRequest $request) {
    if (null === $ws = WebSocket::accept($request)) {
        return;                                  // refused: swerve answered 426, 400 or 403
    }
    try {
        $total = 0;
        while (null !== ($message = $ws->receive())) {
            $total += (int) $message;
            $ws->send("total $total");
            if ($total >= 10) {
                break;
            }
        }
    } finally {
        $ws->end(1000, 'enough');                // with accept(), the handler closes
    }
});

if (debug_backtrace()) {
    return $app;   // swerve loads this file: it is the application's swerve.php
}

// Run directly: serve the application with swerve, and talk to it as a browser would
require __DIR__ . '/../serve.php';
websocket(__FILE__, '/sum', ['3', '4', '5']);
Output
HTTP/1.1 101 Switching Protocols
upgrade: websocket
connection: Upgrade
sec-websocket-accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Server: Swerve

> 3
> 4
> 5
< total 3
< total 7
< total 12
< close 1000 enough
Example 2
if (null === $ws = WebSocket::accept($request)) {
    return;
}
try {
    foreach ($ws as $message) {
        $ws->send($message);
    }
} finally {
    $ws->end();
}