[ Index ]

PHP Cross Reference of YOURLS

title

Body

[close]

/includes/vendor/maxmind/web-service-common/src/WebService/Http/ -> CurlRequest.php (source)

   1  <?php
   2  
   3  declare(strict_types=1);
   4  
   5  namespace MaxMind\WebService\Http;
   6  
   7  use MaxMind\Exception\HttpException;
   8  
   9  /**
  10   * This class is for internal use only. Semantic versioning does not not apply.
  11   *
  12   * @internal
  13   */
  14  class CurlRequest implements Request
  15  {
  16      private readonly \CurlHandle $ch;
  17      private readonly string $url;
  18  
  19      /**
  20       * @var array{
  21       *     caBundle?: string,
  22       *     connectTimeout: float|int,
  23       *     curlHandle: \CurlHandle,
  24       *     headers: array<int, string>,
  25       *     proxy: string|null,
  26       *     timeout: float|int,
  27       *     userAgent: string
  28       * }
  29       */
  30      private readonly array $options;
  31  
  32      /**
  33       * @param array{
  34       *     caBundle?: string,
  35       *     connectTimeout: float|int,
  36       *     curlHandle: \CurlHandle,
  37       *     headers: array<int, string>,
  38       *     proxy: string|null,
  39       *     timeout: float|int,
  40       *     userAgent: string
  41       * } $options
  42       */
  43      public function __construct(string $url, array $options)
  44      {
  45          $this->url = $url;
  46          $this->options = $options;
  47          $this->ch = $options['curlHandle'];
  48      }
  49  
  50      /**
  51       * @throws HttpException
  52       *
  53       * @return array{0:int, 1:string|null, 2:string|null}
  54       */
  55      public function post(string $body): array
  56      {
  57          $curl = $this->createCurl();
  58  
  59          curl_setopt($curl, \CURLOPT_POST, true);
  60          curl_setopt($curl, \CURLOPT_POSTFIELDS, $body);
  61  
  62          return $this->execute($curl);
  63      }
  64  
  65      /**
  66       * @return array{0:int, 1:string|null, 2:string|null}
  67       */
  68      public function get(): array
  69      {
  70          $curl = $this->createCurl();
  71  
  72          curl_setopt($curl, \CURLOPT_HTTPGET, true);
  73  
  74          return $this->execute($curl);
  75      }
  76  
  77      private function createCurl(): \CurlHandle
  78      {
  79          curl_reset($this->ch);
  80  
  81          $opts = [];
  82          $opts[\CURLOPT_URL] = $this->url;
  83  
  84          if (!empty($this->options['caBundle'])) {
  85              $opts[\CURLOPT_CAINFO] = $this->options['caBundle'];
  86          }
  87  
  88          $opts[\CURLOPT_ENCODING] = '';
  89          $opts[\CURLOPT_SSL_VERIFYHOST] = 2;
  90          $opts[\CURLOPT_FOLLOWLOCATION] = false;
  91          $opts[\CURLOPT_SSL_VERIFYPEER] = true;
  92          $opts[\CURLOPT_RETURNTRANSFER] = true;
  93  
  94          $opts[\CURLOPT_HTTPHEADER] = $this->options['headers'];
  95          $opts[\CURLOPT_USERAGENT] = $this->options['userAgent'];
  96          if ($this->options['proxy'] !== null) {
  97              $opts[\CURLOPT_PROXY] = $this->options['proxy'];
  98          }
  99  
 100          $connectTimeout = $this->options['connectTimeout'];
 101          $opts[\CURLOPT_CONNECTTIMEOUT_MS] = (int) ceil($connectTimeout * 1000);
 102  
 103          $timeout = $this->options['timeout'];
 104          $opts[\CURLOPT_TIMEOUT_MS] = (int) ceil($timeout * 1000);
 105  
 106          // @phpstan-ignore argument.type (PHPStan's curl stubs require non-empty-string for URL/userAgent)
 107          curl_setopt_array($this->ch, $opts);
 108  
 109          return $this->ch;
 110      }
 111  
 112      /**
 113       * @throws HttpException
 114       *
 115       * @return array{0:int, 1:string|null, 2:string|null}
 116       */
 117      private function execute(\CurlHandle $curl): array
 118      {
 119          $body = curl_exec($curl);
 120          if ($errno = curl_errno($curl)) {
 121              $errorMessage = curl_error($curl);
 122  
 123              throw new HttpException(
 124                  "cURL error ({$errno}): {$errorMessage}",
 125                  0,
 126                  $this->url
 127              );
 128          }
 129  
 130          $statusCode = curl_getinfo($curl, \CURLINFO_HTTP_CODE);
 131          $contentType = curl_getinfo($curl, \CURLINFO_CONTENT_TYPE);
 132  
 133          return [
 134              $statusCode,
 135              // The PHP docs say "Content-Type: of the requested document. NULL
 136              // indicates server did not send valid Content-Type: header" for
 137              // CURLINFO_CONTENT_TYPE. However, it will return FALSE if no header
 138              // is set. To keep our types simple, we return null in this case.
 139              $contentType === false ? null : $contentType,
 140              // curl_exec returns false on failure, but we've already checked
 141              // for errors above and thrown an exception. Cast to string to
 142              // satisfy PHPStan since curl_exec technically returns string|bool.
 143              $body === false ? null : (string) $body,
 144          ];
 145      }
 146  }


Generated: Sun Aug 9 05:10:27 2026 Cross-referenced by PHPXref 0.7.1