Skip to content

Commit

Permalink
Fix #24: Require compression context factory in acceptor.
Browse files Browse the repository at this point in the history
  • Loading branch information
trowski committed Sep 14, 2023
1 parent 8a57456 commit 4a18362
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
28 changes: 25 additions & 3 deletions src/Rfc6455Acceptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,27 @@

use Amp\ForbidCloning;
use Amp\ForbidSerialization;
use Amp\Http;
use Amp\Http\HttpStatus;
use Amp\Http\Server\ErrorHandler;
use Amp\Http\Server\Request;
use Amp\Http\Server\Response;
use Amp\Websocket\Compression\WebsocketCompressionContextFactory;
use function Amp\Websocket\generateAcceptFromKey;

final class Rfc6455Acceptor implements WebsocketAcceptor
{
use ForbidCloning;
use ForbidSerialization;

public function __construct(private readonly ErrorHandler $errorHandler = new Internal\UpgradeErrorHandler())
{
/**
* @param WebsocketCompressionContextFactory|null $compressionContextFactory Provide the same instance to the
* {@see WebsocketClientFactory}. Use null to disable compression.
*/
public function __construct(
private readonly ErrorHandler $errorHandler = new Internal\UpgradeErrorHandler(),
private readonly ?WebsocketCompressionContextFactory $compressionContextFactory = null,
) {
}

public function handleHandshake(Request $request): Response
Expand Down Expand Up @@ -81,10 +89,24 @@ public function handleHandshake(Request $request): Response
return $response;
}

return new Response(HttpStatus::SWITCHING_PROTOCOLS, [
$response = new Response(HttpStatus::SWITCHING_PROTOCOLS, [
'connection' => 'upgrade',
'upgrade' => 'websocket',
'sec-websocket-accept' => generateAcceptFromKey($acceptKey),
]);

if ($this->compressionContextFactory) {
$extensions = Http\splitHeader($request, 'sec-websocket-extensions') ?? [];

foreach ($extensions as $extension) {
if ($this->compressionContextFactory->fromClientHeader($extension, $headerLine)) {
/** @psalm-suppress PossiblyNullArgument */
$response->setHeader('sec-websocket-extensions', $headerLine);
break;
}
}
}

return $response;
}
}
9 changes: 4 additions & 5 deletions src/Rfc6455ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Amp\ByteStream\ResourceStream;
use Amp\ForbidCloning;
use Amp\ForbidSerialization;
use Amp\Http;
use Amp\Http\Server\Request;
use Amp\Http\Server\Response;
use Amp\Socket\Socket;
Expand All @@ -24,7 +25,8 @@ final class Rfc6455ClientFactory implements WebsocketClientFactory
use ForbidSerialization;

/**
* @param WebsocketCompressionContextFactory|null $compressionContextFactory Use null to disable compression.
* @param WebsocketCompressionContextFactory|null $compressionContextFactory Use the same instance which is
* provided to the {@see WebsocketAcceptor}. Use null to disable compression.
* @param WebsocketHeartbeatQueue|null $heartbeatQueue Use null to disable automatic heartbeats (pings).
* @param WebsocketRateLimit|null $rateLimit Use null to disable client rate limits.
*/
Expand Down Expand Up @@ -66,12 +68,9 @@ public function createClient(

$compressionContext = null;
if ($this->compressionContextFactory) {
$extensions = \array_map('trim', \explode(',', (string) $request->getHeader('sec-websocket-extensions')));

$extensions = Http\splitHeader($request, 'sec-websocket-extensions') ?? [];
foreach ($extensions as $extension) {
if ($compressionContext = $this->compressionContextFactory->fromClientHeader($extension, $headerLine)) {
/** @psalm-suppress PossiblyNullArgument */
$response->setHeader('sec-websocket-extensions', $headerLine);
break;
}
}
Expand Down

0 comments on commit 4a18362

Please sign in to comment.