Получение перенаправленного URL из исходного URL-адреса

У меня есть таблица в моей базе данных, содержащая URL-адреса некоторых веб-сайтов. Мне нужно открыть эти URL-адреса и проверить некоторые ссылки на этих страницах. Проблема в том, что некоторые URL-адреса перенаправляются на другие URL-адреса. Моя логика не подходит для таких URL-адресов.

Есть ли способ передать исходную строку URL-адреса и вернуть перенаправленный URL-адрес?

Пример: я пытаюсь использовать этот URL:  http://individual.troweprice.com/public/Retail/xStaticFiles/FormsAndLiterature/CollegeSavings/trp529Disclosure.pdf

Он перенаправляется на этот: http://individual.troweprice.com/staticFiles/Retail/Shared/PDFs/trp529Disclosure.pdf

Я попытался использовать следующий код:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Uris);
req.Proxy = proxy;
req.Method = "HEAD";
req.AllowAutoRedirect = false;

HttpWebResponse myResp = (HttpWebResponse)req.GetResponse();
if (myResp.StatusCode == HttpStatusCode.Redirect)
{
  MessageBox.Show("redirected to:" + myResp.GetResponseHeader("Location"));
}

Когда я выполняю код выше, он дает мне HttpStatusCodeOk. Я удивлен, почему он не рассматривает это перенаправление. Если я открою ссылку в Internet Explorer, она перенаправит другой URL-адрес и откроет файл PDF.

Может кто-нибудь помочь мне понять, почему он не работает правильно для URL-адреса примера?

Кстати, я проверил с URL Hotmail (http://www.hotmail.com), и он правильно возвращает перенаправленный URL.

Спасибо,

Ответы

Ответ 1

В указанном вами URL-адресе используется перенаправление JavaScript, которое будет перенаправлять браузер. Таким образом, нет простого способа обнаружить перенаправление.

Для правильной (перенаправления HTTP-кода и местоположения HTTP-кода) вы можете удалить

req.AllowAutoRedirect = false;

и получите окончательный URL-адрес, используя

myResp.ResponseUri

поскольку может быть более одного перенаправления.

ОБНОВЛЕНИЕ: больше разъяснений относительно перенаправления:

Существует несколько способов перенаправления браузера на другой URL.

Первый способ - использовать код состояния HTTP 3xx и заголовок Location:. Это то, как боги предполагали, что перенаправление HTTP работает, и также известно как "один истинный путь". Этот метод будет работать на всех браузерах и сканерах.

И тогда есть пути дьявола. К ним относятся meta refresh, заголовок Refresh: и JavaScript. Хотя эти методы работают в большинстве браузеров, они определенно не гарантированно работают, а иногда приводят к странному поведению (ака. нарушение кнопки назад).

Большинство веб-сканеров, включая робота Googlebot, игнорируют эти методы перенаправления, и вы тоже должны. Если вам абсолютно необходимо обнаружить все переадресации, вам придется анализировать HTML-теги META, искать Refresh: заголовки в ответе и оценивать Javascript. Удачи с последним.

Ответ 2

Эта функция вернет конечный пункт назначения ссылки - даже если есть несколько перенаправлений. Он не учитывает переадресацию на основе JavaScript или перенаправление метаданных. Обратите внимание, что предыдущее решение не касалось Абсолютных и Относительных URL-адресов, поскольку заголовок LOCATION может возвращать что-то вроде "/newhome", которое вам нужно объединить с URL-адресом, который служил для этого ответа, чтобы идентифицировать полный URL-адрес.

    public static string GetFinalRedirect(string url)
    {
        if(string.IsNullOrWhiteSpace(url))
            return url;

        int maxRedirCount = 8;  // prevent infinite loops
        string newUrl = url;
        do
        {
            HttpWebRequest req = null;
            HttpWebResponse resp = null;
            try
            {
                req = (HttpWebRequest) HttpWebRequest.Create(url);
                req.Method = "HEAD";
                req.AllowAutoRedirect = false;
                resp = (HttpWebResponse)req.GetResponse();
                switch (resp.StatusCode)
                {
                    case HttpStatusCode.OK:
                        return newUrl;
                    case HttpStatusCode.Redirect:
                    case HttpStatusCode.MovedPermanently:
                    case HttpStatusCode.RedirectKeepVerb:
                    case HttpStatusCode.RedirectMethod:
                        newUrl = resp.Headers["Location"];
                        if (newUrl == null)
                            return url;

                        if (newUrl.IndexOf("://", System.StringComparison.Ordinal) == -1)
                        {
                            // Doesn't have a URL Schema, meaning it a relative or absolute URL
                            Uri u = new Uri(new Uri(url), newUrl);
                            newUrl = u.ToString();
                        }
                        break;
                    default:
                        return newUrl;
                }
                url = newUrl;
            }
            catch (WebException)
            {
                // Return the last known good URL
                return newUrl;
            }
            catch (Exception ex)
            {
                return null;
            }
            finally
            {
                if (resp != null)
                    resp.Close();
            }
        } while (maxRedirCount-- > 0);

        return newUrl;
    }

Ответ 3

используйте этот код, чтобы перенаправить URL-адрес

public void GrtUrl(string url)
    {
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
        webRequest.AllowAutoRedirect = false;  // IMPORTANT

        webRequest.Timeout = 10000;           // timeout 10s
        webRequest.Method = "HEAD";
        // Get the response ...
        HttpWebResponse webResponse;
        using (webResponse = (HttpWebResponse)webRequest.GetResponse())
        {
            // Now look to see if it a redirect
            if ((int)webResponse.StatusCode >= 300 && (int)webResponse.StatusCode <= 399)
            {
                string uriString = webResponse.Headers["Location"];
                Console.WriteLine("Redirect to " + uriString ?? "NULL");
                webResponse.Close(); // don't forget to close it - or bad things happen!
            }

        }

    }

Ответ 4

Вы можете проверить Request.UrlReferrer.AbsoluteUri, чтобы узнать, откуда я пришел. Если это не сработает, вы можете передать старый url в качестве параметра строки запроса?

Ответ 5

Этот код работает для меня

var request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "POST";
request.AllowAutoRedirect = true;
request.ContentType = "application/x-www-form-urlencoded";
var response = request.GetResponse();

//После отправки запроса и ожидаемого перенаправления запроса на какую-либо страницу вашего веб-сайта ответ. ResponseUri.AbsoluteUri содержит этот url, включая строки запроса // (www.yourwebsite.com/returnulr?r = ""... и т.д.)

Redirect(response.ResponseUri.AbsoluteUri); //then just do your own redirect.

Надеюсь, что это поможет

Ответ 6

У меня была такая же проблема, и после многих попыток я не смог получить то, что хотел с HttpWebRequest, поэтому я использовал класс веб-браузера для перехода к первому URL-адресу, а затем я мог получить перенаправленный URL-адрес!

WebBrowser browser = new WebBrowser();
browser.Navigating += new System.Windows.Forms.WebBrowserNavigatingEventHandler(this.browser_Navigating);
string urlToNavigate = "your url";
browser.Navigate(new Uri(urlToNavigate));

то при навигации вы можете получить свой перенаправленный URL. Будьте осторожны, чтобы первый обработчик события browser_Navigating выполнял, e.url - это тот же URL-адрес, который вы использовали для начала просмотра, чтобы вы могли перенаправить URL-адрес при втором вызове

private void browser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
    Uri uri = e.Url;
}

Ответ 7

Я использовал этот метод, используя ваш код, и он возвращает окончательный перенаправленный URL.

        public string GetFinalRedirectedUrl(string url)
    {
        string result = string.Empty;

        Uri Uris = new Uri(url);

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Uris);
        //req3.Proxy = proxy;
        req.Method = "HEAD";
        req.AllowAutoRedirect = false;

        HttpWebResponse myResp = (HttpWebResponse)req.GetResponse();
        if (myResp.StatusCode == HttpStatusCode.Redirect)
        {
            string temp = myResp.GetResponseHeader("Location");
            //Recursive call
            result = GetFinalRedirectedUrl(temp);
        }
        else
        {
            result = url;
        }

        return result;
    }

Примечание: myResp.ResponseUri не возвращает конечный URL