back to top

PHP: risolvere l’errore CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set

Un errore PHP piuttosto comune quando si utilizza la libreria cURL all’interno di un comune piano hosting è il seguente:

PHP Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set in...

Questo errore è dovuto a delle comuni implementazioni di sicurezza presenti sulla maggior parte degli shared hosting, impostazioni che confliggono con l’opzione CURLOPT_FOLLOWLOCATION utilizzata in diversi script che ricorrono alla libreria cURL per accedere a risorse remote.

Ma come ovviare a questo problema? La soluzione "da manuale" prevede un intervento sulla configurazione di PHP per le direttive safe_mode e open_basedir, tuttavia, per ovvie ragioni, all’interno di un hosting condiviso la strada appare difficilmente percorribile.

Per questo motivo può essere utile cercare una soluzione alternativa che è possibile implementare da soli, senza dover necessariamente agire sulle impostazioni del web server.

Ma andiamo per gradi…

Il problema: CURLOPT_FOLLOWLOCATION

Di seguito un esempio di codice che potrebbe generare l’errore oggetto del nostro articolo:

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, 'http://www.sito.com/pagina.php');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$res = curl_exec($ch); 
curl_close($ch);
echo $res;

L’opzione colpevole dell’errore, come già anticipato, è la seguente:

curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);

Grazie a questa opzione, cURL può seguire gli eventuali redirect della risorsa remota (in alter parole: se la risorsa remota è stata spostata, lo script è in grado di seguire il/i redirect eventualmente implementati).

Per ragioni di sicurezza, quando la direttiva safe_mode è attiva e/o open_basedir è settato esplicitamente (cioè il suo valore non è "null"), questa opzione di cURL produce un errore in quanto il sistema blocca questo tipo di richiesta.

Soluzione n.1 – contattare l’hosting provider

Per risolvere il problema sarebbe sufficiente agire sul file php.ini settando safe_mode su "off" e open_basedir su "null" (è anche sufficiente commentare la riga).

Purtroppo la maggior parte degli hosting provider vi risponderà negativamente, in quanto queste direttive sono piuttosto importanti per questioni di sicurezza, quindi questa strada appare difficilemnte percorribile.

Soluzione n.2 – disattivare CURLOPT_FOLLOWLOCATION

Se non è possibile modificare le impostazioni del web server, la cosa più facile da fare per risolvere il nostro problema sarebbe disattivare l’opzione incriminata. Per farlo è sufficiente rimuovere o commentare la riga, oppure settare esplicitamente l’opzione su 0 o false in questo modo:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);

Se la risorsa remota non effettua alcun redirect non avremo alcun problema, in caso contrario questa soluzione non è risolutiva.

Soluzione n.3 – implementare una funzione per simulare CURLOPT_FOLLOWLOCATION

Quando entrambe le soluzioni precedenti non sono praticabili, la risposta al nostro problema può essere trovata nell’implementazione di una funzione in grado di simulare il comportamento di CURLOPT_FOLLOWLOCATION.

Questa funzione è disponibile online in diverse varianti. La versione che vi propongo è stata reperita direttamente tra i commenti sul sito PHP.NET:

function curl_exec_follow($ch, &$maxredirect = null) {
  $mr = $maxredirect === null ? 5 : intval($maxredirect);
  if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $mr > 0);
    curl_setopt($ch, CURLOPT_MAXREDIRS, $mr);
  }else{
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
    if ($mr > 0) {
      $newurl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
      $rch = curl_copy_handle($ch);
      curl_setopt($rch, CURLOPT_HEADER, true);
      curl_setopt($rch, CURLOPT_NOBODY, true);
      curl_setopt($rch, CURLOPT_FORBID_REUSE, false);
      curl_setopt($rch, CURLOPT_RETURNTRANSFER, true);
      do {
        curl_setopt($rch, CURLOPT_URL, $newurl);
        $header = curl_exec($rch);
        if (curl_errno($rch)) {
          $code = 0;
        }else{
          $code = curl_getinfo($rch, CURLINFO_HTTP_CODE);
          if ($code == 301 || $code == 302) {
            preg_match('/Location:(.*?)\n/', $header, $matches);
            $newurl = trim(array_pop($matches));
          }else{
            $code = 0;
          }
        }
      }
      while ($code && --$mr);
      curl_close($rch);
      if (!$mr) {
        if ($maxredirect === null) {
          trigger_error('Too many redirects.', E_USER_WARNING);
        }else{
          $maxredirect = 0;
        }
        return false;
      }
      curl_setopt($ch, CURLOPT_URL, $newurl);
    }
  }
  return curl_exec($ch);
}

Una volta aggiunta la funzione all’interno del sorgente del nostro script, possiamo modificare il codice originale in questo modo:

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, 'http://www.sito.com/pagina.php');
curl_setopt($ch, CURLOPT_POST, 1);
$res = curl_exec_follow($ch); 
curl_close($ch);
echo $res;

Come potete notare abbiamo rimosso la linea relativa all’opzione CURLOPT_FOLLOWLOCATION ed abbiamo sostituito l’invocazione della funzione nativa curl_exec() con curl_exec_follow().

In questo modo otteniamo lo stesso risultato che avremmo ottenuto con CURLOPT_FOLLOWLOCATION, senza incorrere in limitazioni o errori dovuti alla configurazione di PHP.

Pubblicitร 
Massimiliano Bossi
Massimiliano Bossi
Stregato dalla rete sin dai tempi delle BBS e dei modem a 2.400 baud, ho avuto la fortuna di poter trasformare la mia passione in un lavoro (nonostante una Laurea in Giurisprudenza). Adoro scrivere codice e mi occupo quotidianamente di comunicazione, design e nuovi media digitali. Orgogliosamente "nerd" sono il fondatore di MRW.it (per il quale ho scritto centinaia di articoli) e di una nota Web-Agency (dove seguo in prima persona progetti digitali per numerosi clienti sia in Italia che all'estero).

Leggi anche...

Correggere l’errore the uploaded file exceeds the upload_max_filesize directive in php.ini

L'errore the uploaded file exceeds the upload_max_filesize directive in...

Cannot modify header information – headers already sent: come risolvere l’errore PHP

L'errore di PHP cannot modify header information - headers...

Ricavare l’estensione di un file con PHP

Quando si lavora con i file in un'applicazione web,...

GD Library: creazione, manipolazione e ridimensionamento immagini con PHP

Le librerie GD (o GD Library), sono componenti fondamentali...

PHP: impostare il fuso orario italiano

Le tue pagine PHP non mostrano l’orario corretto? Probabilmente...
Pubblicitร