2024-02-25 00:18:33 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace NoccyLabs\React\Http2;
|
|
|
|
|
|
|
|
use NoccyLabs\React\Http2\Connection\Http2Connection;
|
|
|
|
use NoccyLabs\React\Http2\Frame\SettingsFrame;
|
|
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
|
|
use React\Stream\DuplexResourceStream;
|
|
|
|
use React\Stream\DuplexStreamInterface;
|
|
|
|
use React\Stream\ThroughStream;
|
|
|
|
use SplObjectStorage;
|
|
|
|
|
|
|
|
class Http2Middleware
|
|
|
|
{
|
|
|
|
/** @var SplObjectStorage<Http2Connection> Active connections */
|
|
|
|
private SplObjectStorage $connections;
|
|
|
|
|
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
$this->connections = new SplObjectStorage();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __invoke(ServerRequestInterface $request, ?callable $next=null)
|
|
|
|
{
|
2024-02-27 00:21:54 +01:00
|
|
|
// expect upgrade h2 for secure connections, h2c for plaintext
|
|
|
|
|
|
|
|
// TODO handle HTTP/2 upgrade from HTTP/1.1
|
|
|
|
// TODO handle HTTP/2 with prior knowledge
|
2024-02-25 00:18:33 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-02-27 00:21:54 +01:00
|
|
|
/**
|
|
|
|
* Parse the settings frame present in the HTTP/1.1 upgrade request.
|
|
|
|
*
|
|
|
|
* @param string $settings
|
|
|
|
* @return SettingsFrame
|
|
|
|
*/
|
2024-02-25 00:18:33 +01:00
|
|
|
private function parseSettingsFromBase64String(string $settings): SettingsFrame
|
|
|
|
{
|
|
|
|
$decoded = base64_decode($settings);
|
|
|
|
$frame = new SettingsFrame();
|
2024-02-27 00:21:54 +01:00
|
|
|
$frame->fromBinary($decoded);
|
2024-02-25 00:18:33 +01:00
|
|
|
return $frame;
|
|
|
|
}
|
|
|
|
|
2024-02-27 00:21:54 +01:00
|
|
|
/**
|
|
|
|
* Prepare a connection for the HTTP/2 session.
|
|
|
|
*
|
|
|
|
* @param ServerRequestInterface $request
|
|
|
|
* @return Http2Connection
|
|
|
|
*/
|
2024-02-25 00:18:33 +01:00
|
|
|
private function setupConnection(ServerRequestInterface $request): Http2Connection
|
|
|
|
{
|
|
|
|
$stream = new ThroughStream();
|
|
|
|
$connection = new Http2Connection($stream);
|
|
|
|
|
|
|
|
$this->connections->attach($connection);
|
|
|
|
$connection->on('close', function () use ($connection) {
|
|
|
|
$this->connections->detach($connection);
|
|
|
|
});
|
|
|
|
|
|
|
|
return $connection;
|
|
|
|
}
|
|
|
|
}
|