85 lines
2.8 KiB
PHP
85 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\common\service\iam;
|
|
|
|
use RuntimeException;
|
|
|
|
class IamHttpClient
|
|
{
|
|
/** @var callable|null */
|
|
private $transport;
|
|
private int $timeoutSeconds;
|
|
|
|
public function __construct(?callable $transport = null, int $timeoutSeconds = 10)
|
|
{
|
|
$this->transport = $transport;
|
|
$this->timeoutSeconds = $timeoutSeconds;
|
|
}
|
|
|
|
/** @return array{status:int,body:array<string,mixed>} */
|
|
public function json(string $method, string $url, array $headers = [], ?array $json = null): array
|
|
{
|
|
$headers[] = 'Accept: application/json';
|
|
$body = null;
|
|
if ($json !== null) {
|
|
$headers[] = 'Content-Type: application/json';
|
|
$body = json_encode($json, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
|
|
}
|
|
|
|
return $this->send($method, $url, $headers, $body);
|
|
}
|
|
|
|
/** @return array{status:int,body:array<string,mixed>} */
|
|
public function form(string $url, array $form): array
|
|
{
|
|
return $this->send(
|
|
'POST',
|
|
$url,
|
|
['Accept: application/json', 'Content-Type: application/x-www-form-urlencoded'],
|
|
http_build_query($form, '', '&', PHP_QUERY_RFC3986)
|
|
);
|
|
}
|
|
|
|
/** @return array{status:int,body:array<string,mixed>} */
|
|
private function send(string $method, string $url, array $headers, ?string $body): array
|
|
{
|
|
if ($this->transport !== null) {
|
|
$result = ($this->transport)($method, $url, $headers, $body);
|
|
if (!is_array($result) || !isset($result['status'], $result['body'])) {
|
|
throw new RuntimeException('IAM HTTP transport returned an invalid response');
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
$curl = curl_init($url);
|
|
if ($curl === false) {
|
|
throw new RuntimeException('Unable to initialize IAM HTTP request');
|
|
}
|
|
curl_setopt_array($curl, [
|
|
CURLOPT_CUSTOMREQUEST => strtoupper($method),
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_FOLLOWLOCATION => false,
|
|
CURLOPT_CONNECTTIMEOUT => min(5, $this->timeoutSeconds),
|
|
CURLOPT_TIMEOUT => $this->timeoutSeconds,
|
|
CURLOPT_HTTPHEADER => $headers,
|
|
]);
|
|
if ($body !== null) {
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
|
|
}
|
|
$raw = curl_exec($curl);
|
|
$status = (int) curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
|
|
$error = curl_error($curl);
|
|
curl_close($curl);
|
|
if ($raw === false) {
|
|
throw new RuntimeException('IAM HTTP request failed: ' . $error);
|
|
}
|
|
$decoded = json_decode((string) $raw, true);
|
|
return [
|
|
'status' => $status,
|
|
'body' => is_array($decoded) ? $decoded : [],
|
|
];
|
|
}
|
|
}
|