Menu

Reference / Http\WebSocket

upgrade()

function
function upgrade(\Http\Request $req, callable $session, ?Options $o = null): \Http\Response

Answer a WebSocket upgrade request inside an Http\Server handler.

Return the result from the handler. When the request is a valid upgrade, the result is a 101 Switching Protocols response and, once it is sent, $session runs with the new Connection in its own fiber. When the request is not a valid upgrade, the result is an ordinary error response, not an exception:

When $session returns, a connection still open is closed with 1000. If it throws, the connection is closed with 1011 and the exception is rethrown into the server's own error path. The session holds the server's maxConnections permit for its whole life. Server::stop() closes every open session with 1001 "server shutdown".

(new Server('tcp://0.0.0.0:8080'))->serve(function (Request $req): Response {
    return Http\WebSocket\upgrade($req, function (Connection $ws): void {
        foreach ($ws as $m) {
            $ws->send('echo: ' . $m->data);
        }
    });
});

Parameters

$req \Http\Request
the request the handler received
$session callable
called as function (Connection $ws): void
$o Options|null = null
settings; defaults when null

Returns

\Http\Response — the 101 response, or a 400, 426 or 403 error response

Example

// An echo server and a client in one program, over loopback.

use function Async\async;
use function Async\spawn;
use Http\WebSocket as WS;

$l = stream_socket_server('tcp://127.0.0.1:0');
stream_set_blocking($l, false);
$name = stream_socket_get_name($l, false);
$port = (int)substr($name, strrpos($name, ':') + 1);
$server = \Http\Server::onListener($l)->acceptWait(0.02);

async(function () use ($server, $port) {
    spawn(function () use ($server) {
        $server->serve(function (\Http\Request $req): \Http\Response {
            return WS\upgrade($req, function (WS\Connection $ws): void {
                foreach ($ws as $m) {
                    if ($m->binary) {
                        $ws->sendBinary($m->data);
                    } else {
                        $ws->send('echo: ' . $m->data);
                    }
                }
            });
        });
    });

    $ws = WS\connect("ws://127.0.0.1:$port/");
    $ws->send('hello');
    $m = $ws->receive();
    echo $m->data, ' (', $m->binary ? 'binary' : 'text', ")\n";

    $ws->sendBinary("\x00\x01\x02");
    $m = $ws->receive();
    echo bin2hex($m->data), ' (', $m->binary ? 'binary' : 'text', ")\n";

    $ws->close(1000, 'done');
    echo 'open: ', var_export($ws->isOpen(), true), ', close code: ', $ws->closeCode(), "\n";
    $server->stop();
});

Output

echo: hello (text)
000102 (binary)
open: false, close code: 1000

See also: connect, handler

View source