| [ Index ] |
PHP Cross Reference of YOURLS |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Sun Aug 9 05:10:27 2026 | Cross-referenced by PHPXref 0.7.1 |