| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- <?php
- declare(strict_types=1);
- namespace EKSRelay\Core;
- /**
- * Thin cURL wrapper for JSON APIs.
- */
- final class HttpClient
- {
- /**
- * @return array{status: int, body: string, json: mixed}
- */
- public static function request(
- string $method,
- string $url,
- array $headers = [],
- ?array $jsonBody = null,
- int $timeoutSeconds = 30,
- ): array {
- $ch = curl_init();
- $opts = [
- CURLOPT_URL => $url,
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_TIMEOUT => $timeoutSeconds,
- CURLOPT_CONNECTTIMEOUT => 10,
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_MAXREDIRS => 3,
- ];
- // Use bundled CA certs if PHP/system doesn't have them configured
- $caBundle = Env::get('CURL_CA_BUNDLE');
- if ($caBundle === '') {
- // Common fallback locations
- foreach ([
- dirname(__DIR__, 2) . '/cacert.pem',
- (getenv('APPDATA') ?: '') . '/php/cacert.pem',
- ] as $candidate) {
- if ($candidate !== '' && is_file($candidate)) {
- $caBundle = $candidate;
- break;
- }
- }
- }
- if ($caBundle !== '') {
- $opts[CURLOPT_CAINFO] = $caBundle;
- }
- curl_setopt_array($ch, $opts);
- $headers[] = 'Accept: application/json';
- if ($jsonBody !== null) {
- $encoded = json_encode($jsonBody, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded);
- $headers[] = 'Content-Type: application/json';
- }
- $method = strtoupper($method);
- match ($method) {
- 'GET' => null,
- 'POST' => curl_setopt($ch, CURLOPT_POST, true),
- 'PUT' => curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'),
- 'PATCH' => curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH'),
- 'DELETE' => curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'),
- default => curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method),
- };
- curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
- $body = curl_exec($ch);
- $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
- $error = curl_error($ch);
- curl_close($ch);
- if ($body === false) {
- throw new HttpException(502, 'UPSTREAM_ERROR', "cURL error: {$error}");
- }
- $json = json_decode((string)$body, true);
- return [
- 'status' => $status,
- 'body' => (string)$body,
- 'json' => $json,
- ];
- }
- }
|