Mientras que el PO quería evitar cURL
, lo mejor es usarlo cuando esté disponible. He aquí una solución que tiene las siguientes ventajas
- utiliza rizo para todo el trabajo pesado, por lo que trabaja con https
- hace frente a los servidores que devuelven entubado inferior nombre de encabezado
location
(tanto xaav y respuestas de webjay No manipular este)
- le permite controlar la profundidad que desea que vaya antes de renunciar a
Aquí está la función:
function findUltimateDestination($url, $maxRequests = 10)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, $maxRequests);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
//customize user agent if you desire...
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Link Checker)');
curl_setopt($ch, CURLOPT_URL, $url);
curl_exec($ch);
$url=curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close ($ch);
return $url;
}
Aquí hay una versión más detallada que le permite inspeccionar la cadena de redirección en lugar de dejar que curl la siga.
function findUltimateDestination($url, $maxRequests = 10)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
//customize user agent if you desire...
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Link Checker)');
while ($maxRequests--) {
//fetch
curl_setopt($ch, CURLOPT_URL, $url);
$response = curl_exec($ch);
//try to determine redirection url
$location = '';
if (in_array(curl_getinfo($ch, CURLINFO_HTTP_CODE), [301, 302, 303, 307, 308])) {
if (preg_match('/Location:(.*)/i', $response, $match)) {
$location = trim($match[1]);
}
}
if (empty($location)) {
//we've reached the end of the chain...
return $url;
}
//build next url
if ($location[0] == '/') {
$u = parse_url($url);
$url = $u['scheme'] . '://' . $u['host'];
if (isset($u['port'])) {
$url .= ':' . $u['port'];
}
$url .= $location;
} else {
$url = $location;
}
}
return null;
}
Como un ejemplo de cadena de redirección que se encarga de esta función, pero los otros no, intenta esto:
echo findUltimateDestination('http://dx.doi.org/10.1016/j.infsof.2016.05.005')
En el momento de la escritura, esto implica 4 solicitudes, con una mezcla de Location
y location
encabezados involucrados.
Hay * múltiples * 'Ubicación:' encabezados en una sola respuesta? – Tomalak
get_headers sigue las redirecciones automáticamente por defualt, así que obtengo múltiples encabezados 'Location:'. Lo que me gustaría tener es la URL final completa (http: //domain.test/final/page.ext? Attr ...) – Weboide
No entendí la pregunta :( – Stewie