refactor solution to PHP through AI
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ElixForms\Common;
|
||||
|
||||
/**
|
||||
* Client HTTP robusto per effettuare chiamate REST esterne.
|
||||
* Utilizza l'estensione cURL di PHP ed implementa best practices per
|
||||
* la gestione degli header, dell'autenticazione e degli errori.
|
||||
*/
|
||||
class HttpClient
|
||||
{
|
||||
private array $defaultHeaders = [];
|
||||
private ?string $username = null;
|
||||
private ?string $password = null;
|
||||
private int $timeout = 10;
|
||||
|
||||
/**
|
||||
* @param array $defaultHeaders Header predefiniti per ogni richiesta
|
||||
*/
|
||||
public function __construct(array $defaultHeaders = [])
|
||||
{
|
||||
$this->defaultHeaders = $defaultHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
$this->timeout = $seconds;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Esegue una richiesta HTTP GET.
|
||||
*
|
||||
* @param string $url URL della richiesta
|
||||
* @param array $queryParams Parametri query aggiuntivi
|
||||
* @param array $headers Header specifici per questa richiesta
|
||||
* @return string Risposta in formato testuale
|
||||
* @throws \RuntimeException In caso di errore curl o codice di stato non 2xx
|
||||
*/
|
||||
public function get(string $url, array $queryParams = [], array $headers = []): string
|
||||
{
|
||||
if (!empty($queryParams)) {
|
||||
$separator = (strpos($url, '?') === false) ? '?' : '&';
|
||||
$url .= $separator . http_build_query($queryParams);
|
||||
}
|
||||
|
||||
return $this->request($url, 'GET', null, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 $headers Header specifici per questa richiesta
|
||||
* @return string Risposta in formato testuale
|
||||
* @throws \RuntimeException In caso di errore curl o codice di stato non 2xx
|
||||
*/
|
||||
public function post(string $url, $data, array $headers = []): string
|
||||
{
|
||||
return $this->request($url, 'POST', $data, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Metodo interno per eseguire la richiesta tramite cURL.
|
||||
*/
|
||||
private function request(string $url, string $method, $data = null, array $headers = []): string
|
||||
{
|
||||
$ch = curl_init();
|
||||
if ($ch === false) {
|
||||
throw new \RuntimeException('Impossibile inizializzare cURL.');
|
||||
}
|
||||
|
||||
// Configura le opzioni cURL di base
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->timeout);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
|
||||
|
||||
// Disabilita la verifica SSL in ambiente di sviluppo locale se necessario,
|
||||
// ma di default è attiva per sicurezza.
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
|
||||
// Gestione metodo HTTP
|
||||
$method = strtoupper($method);
|
||||
if ($method === 'POST') {
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
if ($data !== null) {
|
||||
if (is_array($data)) {
|
||||
$postData = http_build_query($data);
|
||||
} else {
|
||||
$postData = $data;
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
}
|
||||
} elseif ($method !== 'GET') {
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
}
|
||||
|
||||
// Costruisci gli header
|
||||
$mergedHeaders = array_merge($this->defaultHeaders, $headers);
|
||||
$formattedHeaders = [];
|
||||
foreach ($mergedHeaders as $name => $value) {
|
||||
$formattedHeaders[] = "{$name}: {$value}";
|
||||
}
|
||||
|
||||
if (!empty($formattedHeaders)) {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $formattedHeaders);
|
||||
}
|
||||
|
||||
// Autenticazione Basic
|
||||
if ($this->username !== null && $this->password !== null) {
|
||||
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||
curl_setopt($ch, CURLOPT_USERPWD, "{$this->username}:{$this->password}");
|
||||
}
|
||||
|
||||
// Esegui la richiesta
|
||||
$response = curl_exec($ch);
|
||||
$error = curl_error($ch);
|
||||
$errno = curl_errno($ch);
|
||||
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
// curl_close non è più necessario in PHP 8.0+ ed è deprecato in PHP 8.5+
|
||||
|
||||
if ($errno !== 0) {
|
||||
throw new \RuntimeException("Errore cURL durante la chiamata a {$url}: [{$errno}] {$error}");
|
||||
}
|
||||
|
||||
if ($statusCode < 200 || $statusCode >= 300) {
|
||||
throw new \RuntimeException("Richiesta fallita con codice di stato HTTP {$statusCode}.");
|
||||
}
|
||||
|
||||
return (string)$response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user