Intereting Posts
Как сохранить пользовательские шаблоны страниц WordPress в другой папке, кроме папки темы Автозаполнение jQuery Перенаправление при вводе Обновить расширение ICU в xampp? Решение для «Неустранимая ошибка: максимальный уровень вложенности функции« 100 »достигнут, прерван!» В PHP Есть ли способ определить, был ли файл excel создан в Windows или Mac с помощью PHPExcel? Как отправить данные с чересстрочной кодировкой для проверки уязвимостей? Используйте $ _POST для получения входных значений на одной странице хранить несколько размеров одного образа, подсистемы файловой системы или базы данных PHP SLIM не принимает точку (.) В аргументе uri Как предотвратить инъекции SQL путем обновления кодов Предупреждение: mysqli_stmt :: bind_param (): Число переменных не соответствует количеству параметров в подготовленном операторе в C: \ User .. \ on 148 Отображение массива в PHP с ключами каково использование сегмента $ this-> uri-> (3) в разбиении на страницы кода Morris Js и Codeigniter передают данные от контроллера Сравнение строк PHP – int

Как получить окончательный URL-адрес после перенаправления HTTP в чистом PHP?

То, что я хотел бы сделать, это узнать, что является последним / окончательным URL после перенаправления .

Я бы предпочел не использовать cURL. Я хотел бы придерживаться чистого PHP (обтекатели потоков).

Прямо сейчас у меня есть URL (скажем, http: //domain.test ), и я использую get_headers () для получения определенных заголовков с этой страницы. get_headers также возвратит несколько заголовков Location: (см. раздел «Редактирование» ниже). Есть ли способ использовать эти заголовки для создания конечного URL-адреса? или есть функция PHP, которая автоматически сделает это?

Изменить: get_headers () следует перенаправлениям и возвращает все заголовки для каждого ответа / перенаправления, поэтому у меня есть все заголовки Location:

 /** * get_redirect_url() * Gets the address that the provided URL redirects to, * or FALSE if there's no redirect. * * @param string $url * @return string */ function get_redirect_url($url){ $redirect_url = null; $url_parts = @parse_url($url); if (!$url_parts) return false; if (!isset($url_parts['host'])) return false; //can't process relative URLs if (!isset($url_parts['path'])) $url_parts['path'] = '/'; $sock = fsockopen($url_parts['host'], (isset($url_parts['port']) ? (int)$url_parts['port'] : 80), $errno, $errstr, 30); if (!$sock) return false; $request = "HEAD " . $url_parts['path'] . (isset($url_parts['query']) ? '?'.$url_parts['query'] : '') . " HTTP/1.1\r\n"; $request .= 'Host: ' . $url_parts['host'] . "\r\n"; $request .= "Connection: Close\r\n\r\n"; fwrite($sock, $request); $response = ''; while(!feof($sock)) $response .= fread($sock, 8192); fclose($sock); if (preg_match('/^Location: (.+?)$/m', $response, $matches)){ if ( substr($matches[1], 0, 1) == "/" ) return $url_parts['scheme'] . "://" . $url_parts['host'] . trim($matches[1]); else return trim($matches[1]); } else { return false; } } /** * get_all_redirects() * Follows and collects all redirects, in order, for the given URL. * * @param string $url * @return array */ function get_all_redirects($url){ $redirects = array(); while ($newurl = get_redirect_url($url)){ if (in_array($newurl, $redirects)){ break; } $redirects[] = $newurl; $url = $newurl; } return $redirects; } /** * get_final_url() * Gets the address that the URL ultimately leads to. * Returns $url itself if it isn't a redirect. * * @param string $url * @return string */ function get_final_url($url){ $redirects = get_all_redirects($url); if (count($redirects)>0){ return array_pop($redirects); } else { return $url; } } 

И, как всегда, отдавайте должное:

http://w-shadow.com/blog/2008/07/05/how-to-get-redirect-url-in-php/

 function getRedirectUrl ($url) { stream_context_set_default(array( 'http' => array( 'method' => 'HEAD' ) )); $headers = get_headers($url, 1); if ($headers !== false && isset($headers['Location'])) { return $headers['Location']; } return false; } 

Дополнительно…

Как уже упоминалось в комментарии, конечный элемент в $headers['Location'] станет вашим окончательным URL после всех перенаправлений. Однако важно отметить, что он не всегда будет массивом. Иногда это просто переменная, отличная от массива. В этом случае попытка доступа к последнему элементу массива скорее всего вернет один символ. Не идеально.

Если вас интересует только конечный URL-адрес, после всех переадресаций я предлагаю изменить

 return $headers['Location']; 

в

 return is_array($headers['Location']) ? array_pop($headers['Location']) : $headers['Location']; 

… это просто короткая рука для

 if(is_array($headers['Location'])){ return array_pop($headers['Location']); }else{ return $headers['Location']; } 

Это исправление позаботится о любом случае (массив, не-массив) и устранит необходимость отсеивания конечного URL после вызова функции.

В случае отсутствия переадресаций функция возвращает false . Аналогично, функция также вернет false для недопустимых URL-адресов (по какой-либо причине недействительна). Поэтому важно проверить URL-адрес на достоверность перед запуском этой функции или включить проверку перенаправления где-нибудь в вашу проверку.

xaav ответ очень хорош; за исключением следующих двух вопросов:

  • Он не поддерживает протокол HTTPS => Решение было предложено в качестве комментария на исходном сайте: http://w-shadow.com/blog/2008/07/05/how-to-get-redirect-url-in- PHP /
  • Некоторые сайты не будут работать, поскольку они не будут распознавать базовый пользовательский агент (клиентский браузер) => Это просто исправлено добавлением поля заголовка User-agent: я добавил пользовательский агент Android (вы можете найти здесь http: // www. useragentstring.com/pages/useragentstring.php другие примеры агента пользователя в соответствии с вашими потребностями):

    $ request. = «User-Agent: Mozilla / 5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build / IML74K) AppleWebkit / 534.30 (KHTML, например, Gecko) Версия / 4.0 Mobile Safari / 534.30 \ г \ п ";

Вот измененный ответ:

 /** * get_redirect_url() * Gets the address that the provided URL redirects to, * or FALSE if there's no redirect. * * @param string $url * @return string */ function get_redirect_url($url){ $redirect_url = null; $url_parts = @parse_url($url); if (!$url_parts) return false; if (!isset($url_parts['host'])) return false; //can't process relative URLs if (!isset($url_parts['path'])) $url_parts['path'] = '/'; $sock = fsockopen($url_parts['host'], (isset($url_parts['port']) ? (int)$url_parts['port'] : 80), $errno, $errstr, 30); if (!$sock) return false; $request = "HEAD " . $url_parts['path'] . (isset($url_parts['query']) ? '?'.$url_parts['query'] : '') . " HTTP/1.1\r\n"; $request .= 'Host: ' . $url_parts['host'] . "\r\n"; $request .= "User-Agent: Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\r\n"; $request .= "Connection: Close\r\n\r\n"; fwrite($sock, $request); $response = ''; while(!feof($sock)) $response .= fread($sock, 8192); fclose($sock); if (preg_match('/^Location: (.+?)$/m', $response, $matches)){ if ( substr($matches[1], 0, 1) == "/" ) return $url_parts['scheme'] . "://" . $url_parts['host'] . trim($matches[1]); else return trim($matches[1]); } else { return false; } } /** * get_all_redirects() * Follows and collects all redirects, in order, for the given URL. * * @param string $url * @return array */ function get_all_redirects($url){ $redirects = array(); while ($newurl = get_redirect_url($url)){ if (in_array($newurl, $redirects)){ break; } $redirects[] = $newurl; $url = $newurl; } return $redirects; } /** * get_final_url() * Gets the address that the URL ultimately leads to. * Returns $url itself if it isn't a redirect. * * @param string $url * @return string */ function get_final_url($url){ $redirects = get_all_redirects($url); if (count($redirects)>0){ return array_pop($redirects); } else { return $url; } 

В то время как OP хотел избежать cURL , лучше использовать его, когда он доступен. Вот решение, которое имеет следующие преимущества:

  • использует завиток для всего тяжелого подъема, поэтому работает с https
  • справляется с серверами, которые возвращают более низкое имя заголовка location (оба ответа xaav и webjay не справляются с этим)
  • позволяет вам контролировать, насколько глубоко вы хотите, чтобы вы ушли, прежде чем отказаться от

Вот функция:

 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; } 

Вот более подробная версия, которая позволяет вам проверять цепочку перенаправления, а не следить за ней.

 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; } 

В качестве примера цепочки перенаправления, которую обрабатывает эта функция, а другие нет, попробуйте следующее:

 echo findUltimateDestination('http://dx.doi.org/10.1016/j.infsof.2016.05.005') 

На момент написания это включает 4 запроса, в которых участвуют заголовки location и location .