Introduzione
Quando si usa cURL in PHP, spesso ci si concentra solo sull’invio della richiesta e sulla lettura della risposta. In realtà, un aspetto molto utile e molto pratico è la gestione dei redirect HTTP, cioè quei casi in cui un URL risponde con un codice come 301 o 302 e indica al client di proseguire verso un altro indirizzo.
Questo scenario è comune in applicazioni reali: link abbreviati, pagine spostate, endpoint che cambiano versione, servizi esterni che reindirizzano da HTTP a HTTPS. Se non gestisci correttamente i redirect, potresti salvare URL sbagliati, perdere informazioni utili oppure fermarti alla prima risposta senza raggiungere la risorsa finale.
In questo tutorial vedremo come usare cURL in PHP per:
- seguire automaticamente i redirect;
- ottenere l’URL finale dopo tutti i passaggi;
- distinguere tra URL iniziale e URL effettivamente raggiunto;
- gestire in modo sicuro i casi in cui il redirect non è consentito o non funziona.
Codice completo
<?php
/**
* Esempio pratico: eseguire una richiesta HTTP con cURL
* seguendo i redirect e recuperando l´URL finale.
*/
function fetchWithRedirects(string $url): array
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true, // segue i redirect 301, 302, 307, 308
CURLOPT_MAXREDIRS => 5, // limite di sicurezza
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_HEADER => true, // include header + body nella risposta
CURLOPT_USERAGENT => ´PHP cURL Redirect Tutorial/1.0´,
]);
$response = curl_exec($ch);
if ($response === false) {
$error = curl_error($ch);
$errno = curl_errno($ch);
curl_close($ch);
return [
´success´ => false,
´error´ => "Errore cURL ($errno): $error",
];
}
$info = curl_getinfo($ch);
// Separiamo header e body usando la dimensione dell´header finale.
// Nota: con redirect multipli, curl_getinfo(´header_size´) si riferisce
// all´ultimo blocco di header ricevuto.
$headerSize = $info[´header_size´];
$headers = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
curl_close($ch);
return [
´success´ => true,
´requested_url´ => $url,
´final_url´ => $info[´url´] ?? $url,
´http_code´ => $info[´http_code´] ?? 0,
´redirect_count´ => $info[´redirect_count´] ?? 0,
´content_type´ => $info[´content_type´] ?? ´´,
´headers´ => $headers,
´body´ => $body,
];
}
// URL di esempio: un servizio che effettua redirect verso HTTPS
$result = fetchWithRedirects(´http://example.com´);
if (!$result[´success´]) {
echo ´<p>Errore: ´ . htmlspecialchars($result[´error´]) . ´</p>´;
exit;
}
echo ´<h3>Risultato richiesta</h3>´;
echo ´<p>URL richiesto: ´ . htmlspecialchars($result[´requested_url´]) . ´</p>´;
echo ´<p>URL finale: ´ . htmlspecialchars($result[´final_url´]) . ´</p>´;
echo ´<p>Codice HTTP finale: ´ . (int)$result[´http_code´] . ´</p>´;
echo ´<p>Numero redirect: ´ . (int)$result[´redirect_count´] . ´</p>´;
echo ´<h3>Header finali</h3>´;
echo ´<pre>´ . htmlspecialchars($result[´headers´]) . ´</pre>´;
echo ´<h3>Body della risposta</h3>´;
echo ´<pre>´ . htmlspecialchars(substr($result[´body´], 0, 500)) . ´</pre>´;
?> Spiegazione
Il codice sopra crea una funzione fetchWithRedirects() che riceve un URL, esegue la richiesta e restituisce un array con i dati più utili. Vediamo i punti principali.
1. CURLOPT_FOLLOWLOCATION
Questa opzione dice a cURL di seguire automaticamente i redirect. Se il server risponde con un codice 301, 302, 307 o 308 e un header Location, cURL effettuerà una nuova richiesta verso l’URL indicato.
È la parte più importante del tutorial, perché evita di dover leggere manualmente il redirect e rilanciare la richiesta con un secondo passaggio.
2. CURLOPT_MAXREDIRS
Impostare un limite al numero di redirect è una buona pratica. Senza limite, un server mal configurato potrebbe causare un ciclo infinito, ad esempio:
- URL A redirige verso URL B
- URL B redirige verso URL A
Con CURLOPT_MAXREDIRS blocchi il comportamento dopo un numero massimo di passaggi, proteggendo la tua applicazione da loop indesiderati.
3. CURLOPT_HEADER e separazione header/body
Con CURLOPT_HEADER => true cURL restituisce sia gli header HTTP sia il corpo della risposta in un’unica stringa. Questo è utile quando vuoi analizzare i metadati della risposta, ma richiede di separare i due blocchi usando header_size ottenuto da curl_getinfo().
Nel nostro esempio, gli header finali e il body vengono estratti con substr(). Questo approccio è molto pratico quando vuoi ispezionare la risposta finale dopo i redirect.
4. curl_getinfo() e URL finale
La funzione curl_getinfo() fornisce informazioni preziose sulla richiesta. Tra queste, il campo url indica l’URL finale effettivamente raggiunto, cioè quello dopo eventuali redirect.
Questo è molto utile in casi come:
- normalizzare URL memorizzati nel database;
- verificare la destinazione reale di un link esterno;
- controllare se un sito forza il passaggio da HTTP a HTTPS;
- registrare il percorso finale di una risorsa.
5. Gestione degli errori
Se la richiesta fallisce, il codice usa curl_error() e curl_errno() per restituire un messaggio chiaro. È importante non limitarsi a controllare solo il codice HTTP: alcuni problemi, come errore di rete o timeout, si verificano prima di ricevere una risposta dal server.
Best practice
- Imposta sempre un limite ai redirect con CURLOPT_MAXREDIRS per evitare loop infiniti.
- Usa timeout ragionevoli per non bloccare il flusso dell’applicazione in caso di server lenti o non raggiungibili.
- Controlla sempre l’URL finale quando il risultato della richiesta ha valore funzionale o di sicurezza.
- Non fidarti ciecamente dei redirect esterni: in contesti sensibili, verifica che il dominio finale sia consentito.
- Separa sempre errori di rete e errori HTTP: un 404 non è la stessa cosa di un timeout o di un DNS fallito.
- Usa un User-Agent esplicito per rendere più chiaro il comportamento del tuo client verso i server remoti.
- Se devi analizzare redirect multipli, valuta di salvare anche gli header intermedi, non solo quelli finali.
Riepilogo
La gestione dei redirect con cURL in PHP è una competenza molto utile perché ti permette di lavorare con URL dinamici, migrazioni di sito e servizi esterni senza perdere il controllo della richiesta. Con poche opzioni ben scelte puoi:
- seguire automaticamente i redirect;
- limitare i passaggi per sicurezza;
- recuperare l’URL finale raggiunto;
- analizzare header e body della risposta;
- gestire correttamente gli errori di rete.
Se sviluppi script di integrazione, crawler, strumenti di monitoraggio o semplici utility per validare link, questo approccio ti farà risparmiare tempo e ti aiuterà a scrivere codice più robusto.
Approfondisci con risorse ufficiali
- PHP Manual - cURL: documentazione ufficiale delle funzioni e delle opzioni cURL in PHP.
- PHP Manual - curl_setopt(): elenco completo delle opzioni configurabili.
- PHP Manual - curl_getinfo(): informazioni disponibili dopo l’esecuzione della richiesta.
- cURL Official Documentation: approfondimenti sul comportamento delle opzioni lato libreria.
