Menu
Reference
- Manticore\Ds
- Async
- Http
- Http\WebSocket
- Interfaces
- Handler
- Classes
- Connection
- ConnectionClosedException
- HandshakeException
- Hub
- Message
- Options
- Functions
- connect()
- handler()
- run()
- upgrade()
- Buffer
- Process
- Io\Poll
- Manticore\Sapi
- Ffi
upgrade()
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:
- 400: not
GET, not HTTP/1.1, a missing or malformedSec-WebSocket-Key, nowebsockettoken inUpgrade, or noupgradetoken inConnection. - 426 with
Sec-WebSocket-Version: 13: any other protocol version. - 403: Options::$allowedOrigins is set and the
Originheader is not in it.
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
$sessioncallable- called as
function (Connection $ws): void $oOptions|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