102 lines
3.2 KiB
PHP
102 lines
3.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Support\Api;
|
|
|
|
use RuntimeException;
|
|
|
|
final class ApiClient
|
|
{
|
|
private const DEFAULT_TIMEOUT_SECONDS = 30;
|
|
|
|
public function __construct(private readonly string $baseUrl)
|
|
{
|
|
}
|
|
|
|
public function get(string $path, array $headers = []): ApiResponse
|
|
{
|
|
return $this->request('GET', $path, null, $headers);
|
|
}
|
|
|
|
public function post(string $path, ?array $payload = null, array $headers = []): ApiResponse
|
|
{
|
|
return $this->request('POST', $path, $payload, $headers);
|
|
}
|
|
|
|
public function put(string $path, ?array $payload = null, array $headers = []): ApiResponse
|
|
{
|
|
return $this->request('PUT', $path, $payload, $headers);
|
|
}
|
|
|
|
public function delete(string $path, ?array $payload = null, array $headers = []): ApiResponse
|
|
{
|
|
return $this->request('DELETE', $path, $payload, $headers);
|
|
}
|
|
|
|
public function request(string $method, string $path, ?array $payload = null, array $headers = []): ApiResponse
|
|
{
|
|
$curl = curl_init();
|
|
if ($curl === false) {
|
|
throw new RuntimeException('Unable to initialize cURL for API tests.');
|
|
}
|
|
|
|
$timeoutSeconds = (int)(getenv('API_TEST_REQUEST_TIMEOUT') ?: self::DEFAULT_TIMEOUT_SECONDS);
|
|
if ($timeoutSeconds <= 0) {
|
|
$timeoutSeconds = self::DEFAULT_TIMEOUT_SECONDS;
|
|
}
|
|
|
|
$responseHeaders = [];
|
|
$normalizedHeaders = [];
|
|
foreach ($headers as $name => $value) {
|
|
$normalizedHeaders[] = $name . ': ' . $value;
|
|
}
|
|
|
|
if ($payload !== null) {
|
|
$normalizedHeaders[] = 'Content-Type: application/json';
|
|
}
|
|
|
|
curl_setopt_array($curl, [
|
|
CURLOPT_URL => rtrim($this->baseUrl, '/') . $path,
|
|
CURLOPT_CUSTOMREQUEST => $method,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_HEADER => false,
|
|
CURLOPT_HTTPHEADER => $normalizedHeaders,
|
|
CURLOPT_CONNECTTIMEOUT => $timeoutSeconds,
|
|
CURLOPT_TIMEOUT => $timeoutSeconds,
|
|
CURLOPT_HEADERFUNCTION => static function ($curlHandle, string $headerLine) use (&$responseHeaders): int {
|
|
$length = strlen($headerLine);
|
|
$parts = explode(':', $headerLine, 2);
|
|
if (count($parts) === 2) {
|
|
$responseHeaders[strtolower(trim($parts[0]))] = trim($parts[1]);
|
|
}
|
|
|
|
return $length;
|
|
},
|
|
]);
|
|
|
|
if ($payload !== null) {
|
|
$encodedPayload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
if (!is_string($encodedPayload)) {
|
|
throw new RuntimeException('Unable to encode the API request payload.');
|
|
}
|
|
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $encodedPayload);
|
|
}
|
|
|
|
$body = curl_exec($curl);
|
|
if ($body === false) {
|
|
$error = curl_error($curl);
|
|
curl_close($curl);
|
|
throw new RuntimeException('API request failed: ' . $error);
|
|
}
|
|
|
|
$status = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
|
curl_close($curl);
|
|
|
|
$decoded = json_decode($body, true);
|
|
|
|
return new ApiResponse($status, $responseHeaders, $decoded, (string)$body);
|
|
}
|
|
}
|