public function __invoke(Request $request, Response $response, ...$args)
{
if ($request->getMethod() !== "GET") {
$response->setStatus(HTTP_STATUS["METHOD_NOT_ALLOWED"]);
$response->setHeader("Allow", "GET");
$response->setHeader("Aerys-Generic-Response", "enable");
$response->end();
return;
}
if ($request->getProtocolVersion() !== "1.1") {
$response->setStatus(HTTP_STATUS["HTTP_VERSION_NOT_SUPPORTED"]);
$response->setHeader("Aerys-Generic-Response", "enable");
$response->end();
return;
}
$body = $request->getBody();
if (!$body instanceof NullBody) {
$response->setStatus(HTTP_STATUS["BAD_REQUEST"]);
$response->setReason("Bad Request: Entity body disallowed for websocket endpoint");
$response->setHeader("Connection", "close");
$response->setHeader("Aerys-Generic-Response", "enable");
$response->end();
return;
}
$hasUpgradeWebsocket = false;
foreach ($request->getHeaderArray("Upgrade") as $value) {
if (strcasecmp($value, "websocket") === 0) {
$hasUpgradeWebsocket = true;
break;
}
}
if (empty($hasUpgradeWebsocket)) {
$response->setStatus(HTTP_STATUS["UPGRADE_REQUIRED"]);
$response->setHeader("Aerys-Generic-Response", "enable");
$response->end();
return;
}
$hasConnectionUpgrade = false;
foreach ($request->getHeaderArray("Connection") as $value) {
$values = array_map("trim", explode(",", $value));
foreach ($values as $token) {
if (strcasecmp($token, "Upgrade") === 0) {
$hasConnectionUpgrade = true;
break;
}
}
}
if (empty($hasConnectionUpgrade)) {
$response->setStatus(HTTP_STATUS["UPGRADE_REQUIRED"]);
$response->setReason("Bad Request: \"Connection: Upgrade\" header required");
$response->setHeader("Upgrade", "websocket");
$response->setHeader("Aerys-Generic-Response", "enable");
$response->end();
return;
}
if (!($acceptKey = $request->getHeader("Sec-Websocket-Key"))) {
$response->setStatus(HTTP_STATUS["BAD_REQUEST"]);
$response->setReason("Bad Request: \"Sec-Websocket-Key\" header required");
$response->setHeader("Aerys-Generic-Response", "enable");
$response->end();
return;
}
if (!in_array("13", $request->getHeaderArray("Sec-Websocket-Version"))) {
$response->setStatus(HTTP_STATUS["BAD_REQUEST"]);
$response->setReason("Bad Request: Requested Websocket version unavailable");
$response->setHeader("Sec-WebSocket-Version", "13");
$response->setHeader("Aerys-Generic-Response", "enable");
$response->end();
return;
}
$handshaker = new Handshake($response, $acceptKey);
$onHandshakeResult = $this->application->onHandshake($request, $handshaker, ...$args);
if ($onHandshakeResult instanceof \Generator) {
$onHandshakeResult = (yield from $onHandshakeResult);
}
$request->setLocalVar("aerys.websocket", $onHandshakeResult);
$handshaker->end();
}