transport = $transport; $this->timeoutSeconds = $timeoutSeconds; } /** @return array{status:int,body:array} */ 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} */ 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} */ 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 : [], ]; } }