php-http2/src/Http2.php

118 lines
2.5 KiB
PHP

<?php
namespace JoopSchilder\Http2;
use RuntimeException;
/**
* Class Http2
*/
class Http2
{
/** @var resource */
private $multihandle;
/** @var callable */
private $responseHandler;
/**
* Http2 constructor.
*/
public function __construct()
{
$this->multihandle = curl_multi_init();
curl_multi_setopt($this->multihandle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
curl_multi_setopt($this->multihandle, CURLMOPT_MAX_HOST_CONNECTIONS, 1);
curl_multi_setopt($this->multihandle, CURLMOPT_MAX_TOTAL_CONNECTIONS, 1);
}
/**
* Http2 destructor.
*/
public function __destruct()
{
if (is_resource($this->multihandle)) {
curl_multi_close($this->multihandle);
}
}
/**
* @param string $url
* @param bool $priorKnowledge
* @return Request
*/
public function createRequest(string $url, bool $priorKnowledge = true): Request
{
return (new Request($url))->setOptions([
CURLOPT_AUTOREFERER => 1,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_HEADER => 1,
CURLOPT_HTTP_VERSION => ($priorKnowledge ? CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE : CURL_HTTP_VERSION_2),
CURLOPT_MAXREDIRS => 5,
CURLOPT_PIPEWAIT => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_TIMEOUT => 10,
]);
}
/**
* @param Request $request
*/
public function addRequest(Request $request): void
{
$handle = curl_init($request->getUri());
curl_setopt_array($handle, $request->getOptions());
curl_multi_add_handle($this->multihandle, $handle);
}
/**
* @param callable $responseHandler
*/
public function onResponse(callable $responseHandler): void
{
$this->responseHandler = $responseHandler;
}
/**
*
*/
public function execute(): void
{
$this->guardNoResponseHandler();
do {
curl_multi_exec($this->multihandle, $stillRunning);
while (false !== ($message = curl_multi_info_read($this->multihandle))) {
$handle = $message['handle'];
$content = curl_multi_getcontent($handle);
$header = substr($content, 0, curl_getinfo($handle, CURLINFO_HEADER_SIZE));
$content = str_replace($header, '', $content);
$url = curl_getinfo($handle, CURLINFO_EFFECTIVE_URL);
call_user_func($this->responseHandler, new Response($url, $header, $content));
curl_multi_remove_handle($this->multihandle, $handle);
curl_close($handle);
}
usleep(5);
} while ($stillRunning > 0);
}
/**
*
*/
private function guardNoResponseHandler(): void
{
if (!is_callable($this->responseHandler)) {
throw new RuntimeException('No valid response handler found');
}
}
}