2011-02-23 18 views
6

La función curl_getinfo devuelve una gran cantidad de metadatos sobre el resultado de una solicitud HTTP. Sin embargo, por alguna razón, no incluye el bit de información que quiero en este momento, que es la URL objetivo si la solicitud devuelve un código de redirección HTTP.PHP cURL: Obtiene el objetivo de redirigir, sin seguirlo

No estoy usando CURLOPT_FOLLOWLOCATION porque quiero manejar códigos de redireccionamiento específicos como casos especiales.

Si cURL puede seguir los redireccionamientos, ¿por qué no puede decirme a qué se redirigen cuando no los sigue?

Por supuesto, podría establecer el indicador CURLOPT_HEADER y seleccionar el encabezado de la ubicación. Pero, ¿hay una manera más eficiente?

+0

CURLOPT_NOBODY? – HyderA

+0

Mi programa usa realmente el cuerpo, en aquellos casos en que la URL no es una redirección. Entonces esto no mejoraría las cosas en absoluto. Mi consulta era básicamente sobre si hay un método para extraer el encabezado de ubicación que ahorra la sobrecarga de hacerlo en código PHP. – Stewart

+0

http://stackoverflow.com/questions/1439040/how-can-i-get-the-destination-url-using-curl –

Respuesta

0

No hay ninguna manera más eficiente es
Su puede utilizar CURLOPT_WRITEHEADER + VariableStream
Así que .. usted podría escribir cabeceras a variable y analizarlo

+0

Parece exagerado para mis propósitos ... tal vez solo use una devolución de llamada simple ahora He logrado darles sentido. – Stewart

2

curl no parecen tener una función o una opción para obtener el objetivo de redirección, puede ser extraído por medio de varias técnicas:

partir de la respuesta:

Apache puede responder con una página HTML en caso de una redirección 301 (No parece ser el caso con 302).

Si la respuesta tiene un formato similar a:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
<html><head> 
<title>301 Moved Permanently</title> 
</head><body> 
<h1>Moved Permanently</h1> 
<p>The document has moved <a href="http://www.xxx.yyy/zzz">here</a>.</p> 
<hr> 
<address>Apache/2.2.16 (Debian) Server at www.xxx.yyy Port 80</address> 
</body></html> 

Puede extraer la URL de redirección utilizando DOMXPath:

$i = 0; 
foreach($urls as $url) { 
    if(substr($url,0,4) == "http") { 
     $c = curl_init($url); 
     curl_setopt($c, CURLOPT_RETURNTRANSFER, true); 
     $result = @curl_exec($c); 
     $status = curl_getinfo($c,CURLINFO_HTTP_CODE); 
     curl_close($c); 
     $results[$i]['code'] = $status; 
     $results[$i]['url'] = $url; 

     if($status === 301) { 
      $xml = new DOMDocument(); 
      $xml->loadHTML($result); 
      $xpath = new DOMXPath($xml); 
      $href = $xpath->query("//*[@href]")->item(0); 
      $results[$i]['target'] = $href->attributes->getNamedItem('href')->nodeValue; 
     } 
     $i++; 
    } 
} 

Usando CURLOPT_NOBODY

Hay una manera más rápida sin embargo , como señala @gAMBOOKa; Usando CURLOPT_NOBODY. Este enfoque solo envía una solicitud HEAD en lugar de GET (no descarga el contenido real, por lo que debe ser más rápido y más eficiente) y almacena el encabezado de respuesta.

Usando una expresión regular la URL de destino puede ser extraído de la cabecera:

foreach($urls as $url) { 
    if(substr($url,0,4) == "http") { 
     $c = curl_init($url); 
     curl_setopt($c, CURLOPT_RETURNTRANSFER, true); 
     curl_setopt($c, CURLOPT_NOBODY,true); 
     curl_setopt($c, CURLOPT_HEADER, true); 
     $result = @curl_exec($c); 
     $status = curl_getinfo($c,CURLINFO_HTTP_CODE); 
     curl_close($c); 
     $results[$i]['code'] = $status; 
     $results[$i]['url'] = $url; 

     if($status === 301 || $status === 302) { 
      preg_match("@https?://([-\w\.]+)+(:\d+)?(/([\w/_\-\.]*(\?\S+)?)?)[email protected]",$result,$m); 
      $results[$i]['target'] = $m[0]; 
     } 
     $i++; 
    } 
} 
+0

CURLOPT_NOBODY para la victoria! Imprescindible ... ¡¡¡Gracias !!! – Gor

4

Esto se puede hacer en 4 sencillos pasos:

Paso 1. Inicializar enrollamiento

curl_init($ch); //initialise the curl handle 
//COOKIESESSION is optional, use if you want to keep cookies in memory 
curl_setopt($this->ch, CURLOPT_COOKIESESSION, true); 

Paso 2. Obtenga los encabezados para $url

curl_setopt($ch, CURLOPT_URL, $url); //specify your URL 
curl_setopt($ch, CURLOPT_HEADER, true); //include headers in http data 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); //don't follow redirects 
$http_data = curl_exec($ch); //hit the $url 
$curl_info = curl_getinfo($ch); 
$headers = substr($http_data, 0, $curl_info['header_size']); //split out header 

Paso 3. Comprobar si tiene el código de respuesta correcta

if (!($curl_info['http_code']>299 && $curl_info['http_code']<309)) { 
    //return, echo, die, whatever you like 
    return 'Error - http code'.curl_info['http_code'].' received.'; 
} 

Paso 4.Analizar los encabezados para obtener el nuevo URL

preg_match("!\r\n(?:Location|URI): *(.*?) *\r\n!", $headers, $matches); 
$url = $matches[1]; 

Una vez que tenga la nueva dirección URL a continuación, puede repetir los pasos 2-4 tantas veces como desee.

0

Tuve el mismo problema y curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); fue de mucha ayuda.

lo tanto, decidí no usar CURL pero file_get_contents lugar:

$data = file_get_contents($url); 
$data = str_replace("<meta http-equiv=\"Refresh\" content=\"0;","<meta",$data); 

La última línea me ayudó a bloquear la redirección aunque el producto no es un código html limpio.

Analicé los datos y pude recuperar la URL de redireccionamiento que quería obtener.

+0

Me parece que la página en la que intentaba bloquear la redirección estaba utilizando una meta-actualización, en lugar de una redirección HTTP. Esto último es lo que estoy tratando. – Stewart

1

Simplemente puede usarlo: (CURLINFO_REDIRECT_URL)

$info = curl_getinfo($ch, CURLINFO_REDIRECT_URL); 
echo $info; // the redirect URL without following it 

como usted ha mencionado, desactivar la opción CURLOPT_FOLLOWLOCATION (antes de ejecutar) y coloque el código después de la ejecución.

CURLINFO_REDIRECT_URL - Con la opción CURLOPT_FOLLOWLOCATION discapacitados: redirigir URL que se encuentra en la última transacción, que debe ser solicitada manualmente siguiente. Con la opción CURLOPT_FOLLOWLOCATION habilitada: esto está vacío. La URL de redireccionamiento en este caso, está disponible en CURLINFO_EFFECTIVE_URL

Refrence