Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/web/http/curl/ |
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/web/http/curl/handler.php |
<?php /** * Bitrix Framework * @package bitrix * @subpackage main * @copyright 2001-2023 Bitrix */ namespace Bitrix\Main\Web\Http\Curl; use Bitrix\Main\Web\Http; use Bitrix\Main\Web\IpAddress; use Psr\Http\Message\RequestInterface; use Bitrix\Main\Web\HttpDebug; class Handler extends Http\Handler { protected \CurlHandle $handle; protected $logFileHandle; /** * @param RequestInterface $request * @param Http\ResponseBuilder $responseBuilder * @param array $options */ public function __construct(RequestInterface $request, Http\ResponseBuilder $responseBuilder, array $options = []) { Http\Handler::__construct($request, $responseBuilder, $options); $this->handle = curl_init(); $this->setOptions($options); } public function __destruct() { curl_close($this->handle); if (is_resource($this->logFileHandle)) { fclose($this->logFileHandle); } } protected function setOptions(array $options): void { $request = $this->request; $uri = $request->getUri(); $curlOptions = [ CURLOPT_URL => (string)$uri, CURLOPT_HEADER => false, CURLOPT_RETURNTRANSFER => false, CURLOPT_FOLLOWLOCATION => false, CURLOPT_HTTP_VERSION => ($request->getProtocolVersion() === '1.1' ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0), CURLOPT_CONNECTTIMEOUT => (int)($options['socketTimeout'] ?? 30), CURLOPT_LOW_SPEED_TIME => (int)($options['streamTimeout'] ?? 60), CURLOPT_LOW_SPEED_LIMIT => 1, // bytes/sec CURLOPT_HTTPHEADER => $this->buildHeaders(), ]; if (isset($options['contextOptions']['ssl']['verify_peer'])) { $curlOptions[CURLOPT_SSL_VERIFYPEER] = (bool)$options['contextOptions']['ssl']['verify_peer']; } if (isset($options['contextOptions']['ssl']['verify_peer_name'])) { $curlOptions[CURLOPT_SSL_VERIFYHOST] = $options['contextOptions']['ssl']['verify_peer_name'] ? 2 : 0; } $method = $request->getMethod(); if ($method === 'HEAD') { $curlOptions[CURLOPT_NOBODY] = true; } else { $curlOptions[CURLOPT_CUSTOMREQUEST] = $method; } if (isset($options['effectiveIp']) && $options['effectiveIp'] instanceof IpAddress) { //resolved in HttpClient if private IPs were disabled $curlOptions[CURLOPT_RESOLVE] = [$uri->getHost() . ':' . $uri->getPort() . ':' . $options['effectiveIp']]; } if (isset($options['proxyHost'])) { $curlOptions[CURLOPT_PROXY] = (string)$options['proxyHost']; if (isset($options['proxyPort'])) { $curlOptions[CURLOPT_PROXYPORT] = (int)$options['proxyPort']; } } if ($method != 'GET' && $method != 'HEAD' && $method != 'TRACE') { $body = $request->getBody(); $size = $body->getSize(); if ($size !== 0) { if ($body->isSeekable()) { $body->rewind(); } $curlOptions[CURLOPT_UPLOAD] = true; if ($size !== null) { $curlOptions[CURLOPT_INFILESIZE] = $size; } $curlOptions[CURLOPT_READFUNCTION] = [$this, 'readRequestBody']; } } $curlOptions[CURLOPT_HEADERFUNCTION] = [$this, 'receiveHeaders']; $curlOptions[CURLOPT_WRITEFUNCTION] = [$this, 'receiveBody']; if (!empty($options['curlLogFile'])) { $this->logFileHandle = fopen($options['curlLogFile'], 'a+'); $curlOptions[CURLOPT_STDERR] = $this->logFileHandle; $curlOptions[CURLOPT_VERBOSE] = true; } curl_setopt_array($this->handle, $curlOptions); } /** * @internal Callback */ public function readRequestBody($handle, $resource, $length) { $part = $this->request->getBody()->read($length); $this->log($part, HttpDebug::REQUEST_BODY); return $part; } /** * @internal Callback */ public function receiveHeaders($handle, $data) { if ($data === "\r\n") { // got all headers $this->log("\n<<<RESPONSE\n" . $this->responseHeaders . "\n", HttpDebug::RESPONSE_HEADERS); // build the response for the next stage $this->response = $this->responseBuilder->createFromString($this->responseHeaders); $fetchBody = $this->waitResponse; if ($this->shouldFetchBody !== null) { $fetchBody = call_user_func($this->shouldFetchBody, $this->response, $this->request); } if (!$fetchBody) { // this is not an error really throw new SkipBodyException(); } } else { $this->responseHeaders .= $data; } return strlen($data); } /** * @internal Callback */ public function receiveBody($handle, $data) { $body = $this->response->getBody(); try { $result = $body->write($data); } catch (\RuntimeException) { return false; } if ($this->bodyLengthMax > 0 && $body->getSize() > $this->bodyLengthMax) { return false; } return $result; } protected function buildHeaders(): array { $headers = []; foreach ($this->request->getHeaders() as $name => $values) { foreach ($values as $value) { $headers[] = $name . ': ' . $value; } } if ($this->getLogger() && $this->debugLevel) { $request = $this->request->getMethod() . ' ' . $this->request->getRequestTarget() . ' HTTP/' . $this->request->getProtocolVersion() . "\r\n" . implode("\r\n", $headers) . "\r\n"; $this->log(">>>REQUEST\n" . $request, HttpDebug::REQUEST_HEADERS); } return $headers; } /** * @return \CurlHandle */ public function getHandle(): \CurlHandle { return $this->handle; } }