140 lines
4.6 KiB
PHP
140 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace ElixForms\Common;
|
|
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\ClientInterface;
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
use GuzzleHttp\Exception\RequestException;
|
|
use GuzzleHttp\RequestOptions;
|
|
|
|
/**
|
|
* Client HTTP robusto per effettuare chiamate REST esterne.
|
|
* Adapter applicativo basato su Guzzle per la gestione uniforme di
|
|
* header, autenticazione, timeout ed errori delle chiamate esterne.
|
|
*/
|
|
class HttpClient
|
|
{
|
|
private ClientInterface $client;
|
|
private array $defaultHeaders;
|
|
private ?string $username = null;
|
|
private ?string $password = null;
|
|
private int $timeout = 10;
|
|
|
|
/**
|
|
* @param array<string, string> $defaultHeaders Header predefiniti per ogni richiesta
|
|
*/
|
|
public function __construct(array $defaultHeaders = [], ?ClientInterface $client = null)
|
|
{
|
|
$this->defaultHeaders = $defaultHeaders;
|
|
$this->client = $client ?? new Client();
|
|
}
|
|
|
|
/**
|
|
* Imposta le credenziali per l'autenticazione Basic.
|
|
*/
|
|
public function setBasicAuth(string $username, string $password): self
|
|
{
|
|
$this->username = $username;
|
|
$this->password = $password;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Imposta il timeout massimo per la connessione e l'esecuzione.
|
|
*/
|
|
public function setTimeout(int $seconds): self
|
|
{
|
|
if ($seconds <= 0) {
|
|
throw new \InvalidArgumentException('Il timeout deve essere maggiore di zero.');
|
|
}
|
|
|
|
$this->timeout = $seconds;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Esegue una richiesta HTTP GET.
|
|
*
|
|
* @param string $url URL della richiesta
|
|
* @param array<string, mixed> $queryParams Parametri query aggiuntivi
|
|
* @param array<string, string> $headers Header specifici per questa richiesta
|
|
* @return string Risposta in formato testuale
|
|
* @throws \RuntimeException In caso di errore HTTP o di trasporto
|
|
*/
|
|
public function get(string $url, array $queryParams = [], array $headers = []): string
|
|
{
|
|
$options = $queryParams === [] ? [] : [RequestOptions::QUERY => $queryParams];
|
|
|
|
return $this->request($url, 'GET', $headers, $options);
|
|
}
|
|
|
|
/**
|
|
* Esegue una richiesta HTTP POST.
|
|
*
|
|
* @param string $url URL della richiesta
|
|
* @param mixed $data Dati da inviare nel body (array, stringa o JSON)
|
|
* @param array<string, string> $headers Header specifici per questa richiesta
|
|
* @return string Risposta in formato testuale
|
|
* @throws \RuntimeException In caso di errore HTTP o di trasporto
|
|
*/
|
|
public function post(string $url, $data, array $headers = []): string
|
|
{
|
|
$options = is_array($data)
|
|
? [RequestOptions::FORM_PARAMS => $data]
|
|
: [RequestOptions::BODY => $data];
|
|
|
|
return $this->request($url, 'POST', $headers, $options);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string> $headers
|
|
* @param array<string, mixed> $requestOptions
|
|
*/
|
|
private function request(string $url, string $method, array $headers, array $requestOptions = []): string
|
|
{
|
|
$options = [
|
|
RequestOptions::HEADERS => array_merge($this->defaultHeaders, $headers),
|
|
RequestOptions::TIMEOUT => $this->timeout,
|
|
RequestOptions::CONNECT_TIMEOUT => $this->timeout,
|
|
RequestOptions::ALLOW_REDIRECTS => ['max' => 3],
|
|
RequestOptions::VERIFY => true,
|
|
RequestOptions::HTTP_ERRORS => true,
|
|
];
|
|
|
|
if ($this->username !== null && $this->password !== null) {
|
|
$options[RequestOptions::AUTH] = [$this->username, $this->password];
|
|
}
|
|
|
|
try {
|
|
$response = $this->client->request(
|
|
strtoupper($method),
|
|
$url,
|
|
array_replace($options, $requestOptions)
|
|
);
|
|
} catch (RequestException $exception) {
|
|
$response = $exception->getResponse();
|
|
if ($response !== null) {
|
|
throw new \RuntimeException(
|
|
"Richiesta fallita con codice di stato HTTP {$response->getStatusCode()}.",
|
|
0,
|
|
$exception
|
|
);
|
|
}
|
|
|
|
throw new \RuntimeException('Errore di connessione al servizio esterno.', 0, $exception);
|
|
} catch (GuzzleException $exception) {
|
|
throw new \RuntimeException('Errore durante la chiamata al servizio esterno.', 0, $exception);
|
|
}
|
|
|
|
$statusCode = $response->getStatusCode();
|
|
if ($statusCode < 200 || $statusCode >= 300) {
|
|
throw new \RuntimeException("Richiesta fallita con codice di stato HTTP {$statusCode}.");
|
|
}
|
|
|
|
return (string)$response->getBody();
|
|
}
|
|
}
|