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'); } } }