vendor/ruflin/elastica/src/Transport/Http.php line 178

Open in your IDE?
  1. <?php
  2. namespace Elastica\Transport;
  3. use Elastica\Exception\Connection\HttpException;
  4. use Elastica\Exception\ConnectionException;
  5. use Elastica\Exception\PartialShardFailureException;
  6. use Elastica\Exception\ResponseException;
  7. use Elastica\JSON;
  8. use Elastica\Request;
  9. use Elastica\Response;
  10. use Elastica\Util;
  11. /**
  12.  * Elastica Http Transport object.
  13.  *
  14.  * @author Nicolas Ruflin <spam@ruflin.com>
  15.  */
  16. class Http extends AbstractTransport
  17. {
  18.     /**
  19.      * Http scheme.
  20.      *
  21.      * @var string Http scheme
  22.      */
  23.     protected $_scheme 'http';
  24.     /**
  25.      * Curl resource to reuse.
  26.      *
  27.      * @var \CurlHandle|resource|null Curl resource to reuse
  28.      */
  29.     protected static $_curlConnection;
  30.     /**
  31.      * Makes calls to the elasticsearch server.
  32.      *
  33.      * All calls that are made to the server are done through this function
  34.      *
  35.      * @param array<string, mixed> $params Host, Port, ...
  36.      *
  37.      * @throws ConnectionException
  38.      * @throws ResponseException
  39.      * @throws HttpException
  40.      *
  41.      * @return Response Response object
  42.      */
  43.     public function exec(Request $request, array $params): Response
  44.     {
  45.         $connection $this->getConnection();
  46.         $conn $this->_getConnection($connection->isPersistent());
  47.         // If url is set, url is taken. Otherwise port, host and path
  48.         $url $connection->hasConfig('url') ? $connection->getConfig('url') : '';
  49.         if (!empty($url)) {
  50.             $baseUri $url;
  51.         } else {
  52.             $baseUri $this->_scheme.'://'.$connection->getHost().':'.$connection->getPort().'/'.$connection->getPath();
  53.         }
  54.         $requestPath $request->getPath();
  55.         if (!Util::isDateMathEscaped($requestPath)) {
  56.             $requestPath Util::escapeDateMath($requestPath);
  57.         }
  58.         $baseUri .= $requestPath;
  59.         $query $request->getQuery();
  60.         if (!empty($query)) {
  61.             $baseUri .= '?'.\http_build_query(
  62.                 $this->sanityzeQueryStringBool($query)
  63.             );
  64.         }
  65.         \curl_setopt($conn\CURLOPT_URL$baseUri);
  66.         \curl_setopt($conn\CURLOPT_TIMEOUT_MS$connection->getTimeout() * 1000);
  67.         \curl_setopt($conn\CURLOPT_FORBID_REUSE0);
  68.         // Tell ES that we support the compressed responses
  69.         // An "Accept-Encoding" header containing all supported encoding types is sent
  70.         // curl will decode the response automatically if the response is encoded
  71.         \curl_setopt($conn\CURLOPT_ENCODING'');
  72.         /* @see Connection::setConnectTimeout() */
  73.         $connectTimeoutMs $connection->getConnectTimeout() * 1000;
  74.         // Let's only apply this value if the number of ms is greater than or equal to "1".
  75.         // In case "0" is passed as an argument, the value is reset to its default (300 s)
  76.         if ($connectTimeoutMs >= 1) {
  77.             \curl_setopt($conn\CURLOPT_CONNECTTIMEOUT_MS$connectTimeoutMs);
  78.         }
  79.         if (null !== $proxy $connection->getProxy()) {
  80.             \curl_setopt($conn\CURLOPT_PROXY$proxy);
  81.         }
  82.         $username $connection->getUsername();
  83.         $password $connection->getPassword();
  84.         if (null !== $username && null !== $password) {
  85.             \curl_setopt($conn\CURLOPT_HTTPAUTH$this->_getAuthType());
  86.             \curl_setopt($conn\CURLOPT_USERPWD"{$username}:{$password}");
  87.         }
  88.         $this->_setupCurl($conn);
  89.         $headersConfig $connection->hasConfig('headers') ? $connection->getConfig('headers') : [];
  90.         $headers = [];
  91.         if (!empty($headersConfig)) {
  92.             foreach ($headersConfig as $header => $headerValue) {
  93.                 $headers[] = $header.': '.$headerValue;
  94.             }
  95.         }
  96.         // TODO: REFACTOR
  97.         $data $request->getData();
  98.         $httpMethod $request->getMethod();
  99.         $headers[] = 'Content-Type: '.$request->getContentType();
  100.         if (!empty($data)) {
  101.             if ($this->hasParam('postWithRequestBody') && true == $this->getParam('postWithRequestBody')) {
  102.                 $httpMethod Request::POST;
  103.             }
  104.             if (\is_array($data)) {
  105.                 $content JSON::stringify($data\JSON_UNESCAPED_UNICODE \JSON_UNESCAPED_SLASHES);
  106.             } else {
  107.                 $content $data;
  108.                 // Escaping of / not necessary. Causes problems in base64 encoding of files
  109.                 $content \str_replace('\/''/'$content);
  110.             }
  111.             if ($connection->hasCompression()) {
  112.                 // Compress the body of the request ...
  113.                 \curl_setopt($conn\CURLOPT_POSTFIELDS\gzencode($content));
  114.                 // ... and tell ES that it is compressed
  115.                 $headers[] = 'Content-Encoding: gzip';
  116.             } else {
  117.                 \curl_setopt($conn\CURLOPT_POSTFIELDS$content);
  118.             }
  119.         } else {
  120.             \curl_setopt($conn\CURLOPT_POSTFIELDS'');
  121.         }
  122.         \curl_setopt($conn\CURLOPT_HTTPHEADER$headers);
  123.         \curl_setopt($conn\CURLOPT_NOBODY'HEAD' === $httpMethod);
  124.         \curl_setopt($conn\CURLOPT_CUSTOMREQUEST$httpMethod);
  125.         $start \microtime(true);
  126.         // cURL opt returntransfer leaks memory, therefore OB instead.
  127.         \ob_start();
  128.         \curl_exec($conn);
  129.         $responseString \ob_get_clean();
  130.         $end \microtime(true);
  131.         // Checks if error exists
  132.         $errorNumber \curl_errno($conn);
  133.         $response = new Response($responseString\curl_getinfo($conn\CURLINFO_RESPONSE_CODE));
  134.         $response->setQueryTime($end $start);
  135.         $response->setTransferInfo(\curl_getinfo($conn));
  136.         if ($connection->hasConfig('bigintConversion')) {
  137.             $response->setJsonBigintConversion($connection->getConfig('bigintConversion'));
  138.         }
  139.         if ($response->hasError()) {
  140.             throw new ResponseException($request$response);
  141.         }
  142.         if ($response->hasFailedShards()) {
  143.             throw new PartialShardFailureException($request$response);
  144.         }
  145.         if ($errorNumber 0) {
  146.             throw new HttpException($errorNumber$request$response);
  147.         }
  148.         return $response;
  149.     }
  150.     /**
  151.      * Called to add additional curl params.
  152.      *
  153.      * @param \CurlHandle|resource $curlConnection Curl connection
  154.      */
  155.     protected function _setupCurl($curlConnection): void
  156.     {
  157.         if ($this->getConnection()->hasConfig('curl')) {
  158.             foreach ($this->getConnection()->getConfig('curl') as $key => $param) {
  159.                 \curl_setopt($curlConnection$key$param);
  160.             }
  161.         }
  162.     }
  163.     /**
  164.      * Return Curl resource.
  165.      *
  166.      * @param bool $persistent False if not persistent connection
  167.      *
  168.      * @return \CurlHandle|resource Connection resource
  169.      */
  170.     protected function _getConnection(bool $persistent true)
  171.     {
  172.         if (!$persistent || !self::$_curlConnection) {
  173.             self::$_curlConnection \curl_init();
  174.         }
  175.         return self::$_curlConnection;
  176.     }
  177.     /**
  178.      * @return int
  179.      */
  180.     protected function _getAuthType()
  181.     {
  182.         switch ($this->_connection->getAuthType()) {
  183.             case 'digest':
  184.                 return \CURLAUTH_DIGEST;
  185.             case 'gssnegotiate':
  186.                 return \CURLAUTH_GSSNEGOTIATE;
  187.             case 'ntlm':
  188.                 return \CURLAUTH_NTLM;
  189.             case 'basic':
  190.                 return \CURLAUTH_BASIC;
  191.             default:
  192.                 return \CURLAUTH_ANY;
  193.         }
  194.     }
  195. }