从原始URL获取重定向的URL

时间:2009-04-01 10:40:32

标签: c# .net

我的数据库中有一个表格,其中包含某些网站的网址。我必须打开这些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文件。

有人可以帮助我理解为什么它无法正常运行示例网址吗?

顺便说一句,我查看了Hotmail的网址(http://www.hotmail.com),并正确地返回了重定向的网址。

谢谢,

11 个答案:

答案 0 :(得分:18)

您提到的网址使用JavaScript重定向,该重定向仅重定向浏览器。因此,没有简单的方法来检测重定向。

要正确(HTTP状态代码和位置:)重定向,您可能需要删除

req.AllowAutoRedirect = false;

并使用

获取最终的网址
myResp.ResponseUri

因为可以有多个重定向。

更新:有关重定向的更多说明:

将浏览器重定向到另一个网址的方法不止一种。

第一种方法是使用3xx HTTP状态代码和Location:标头。这是神想要HTTP重定向工作的方式,也被称为“一种真正的方式”。此方法适用于所有浏览器和抓取工具。

然后有魔鬼的方式。其中包括meta refresh,Refresh:标头和JavaScript。虽然这些方法适用于大多数浏览器,但它们绝对不能保证工作,偶尔会导致奇怪的行为(又名。breaking the back button)。

大多数网络抓取工具(包括Googlebot)都会忽略这些重定向方法,您也应该这样做。如果你绝对来检测所有重定向,那么你必须解析META标签的HTML,在响应中查找Refresh:headers,并评估Javascript。祝最后一个好运。

答案 1 :(得分:17)

此功能将返回链接的最终目的地 - 即使有多个重定向。它没有考虑基于JavaScript的重定向或META重定向。请注意,之前的解决方案并未处理Absolute& amp;相对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's 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;
    }

答案 2 :(得分:7)

使用此代码获取重定向网址

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's 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!
            }

        }

    }

答案 3 :(得分:1)

在查看了每个人的建议后,我至少在我的案例中发现了这一点,它基本上对 https 进行了 3 次循环,对实际结束位置进行了第二次循环。 这是这里的递归函数调用:

public static string GrtUrl(string url, int counter)
{
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
    | SecurityProtocolType.Tls11
    | SecurityProtocolType.Tls12
    | SecurityProtocolType.Ssl3;
    string ReturnURL = 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's a redirect
        if ((int)webResponse.StatusCode >= 300 && (int)webResponse.StatusCode <= 399)
        {
            string uriString = webResponse.Headers["Location"];
            ReturnURL = uriString;
            if (ReturnURL == url)

            {
                webResponse.Close(); // don't forget to close it - or bad things happen!
                return ReturnURL;

            }
            else
            {
                webResponse.Close(); // don't forget to close it - or bad things happen!
                if (counter > 50)
                    return ReturnURL;
                else
                    return GrtUrl(ReturnURL, counter++);
            }

            
        }

    }
    return ReturnURL; 

}

答案 4 :(得分:0)

您可以查看Request.UrlReferrer.AbsoluteUri以查看我的来源。如果这不起作用,您可以将旧URL作为查询字符串参数传递吗?

答案 5 :(得分:0)

此代码适用于我

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

//发送请求后,请求会重定向到您网站的某个页面,response.ResponseUri.AbsoluteUri包含该网址包含查询字符串 //(www.yourwebsite.com/returnulr?r =“”......等等)

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

希望这有帮助

答案 6 :(得分:0)

我遇到了同样的问题,在尝试了很多之后我无法通过HttpWebRequest获得我想要的东西,所以我使用网络浏览器类导航到第一个网址然后我可以获得重定向的网址!

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

然后在导航时,您可以获得重定向的网址。请注意,第一次发生browser_Navigating事件处理程序时,e.url与您用于开始浏览的URL相同,因此您可以在第二次调用时获得重定向的URL

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

答案 7 :(得分:0)

string url = ".......";
var request = (HttpWebRequest)WebRequest.Create(url);
var response = (HttpWebResponse)request.GetResponse();

string redirectUrl = response.ResponseUri.ToString();

答案 8 :(得分:0)

异步HttpClient版本:

// works in .Net Framework and .Net Core
public static async Task<Uri> GetRedirectedUrlAsync(Uri uri, CancellationToken cancellationToken = default)
{
    using var client = new HttpClient(new HttpClientHandler
    {
        AllowAutoRedirect = false,
    }, true);
    using var response = await client.GetAsync(uri, cancellationToken);

    return new Uri(response.Headers.GetValues("Location").First();
}

// works in .Net Core
public static async Task<Uri> GetRedirectedUrlAsync(Uri uri, CancellationToken cancellationToken = default)
{
    using var client = new HttpClient();
    using var response = await client.GetAsync(uri, cancellationToken);

    return response.RequestMessage.RequestUri;
}

P.S。如果需要限制尝试次数,可以使用handler.MaxAutomaticRedirections = 1

答案 9 :(得分:0)

处理 javascript 重定向的一种方法是查看将加载的初始域页面的源代码,然后直接从源代码中提取新域,即最终域。因为它是一个 javascript 重定向,所以新域又名最终域应该在那里。干杯

从页面源中提取 URL 地址的代码:

string href = "";
string pageSrc = "get page source using web client download string method and place output here";
Match m = Regex.Match(pageSrc, @"href=\""(.*?)\""", RegexOptions.Singleline);
if (m2.Success){
    href = m.Groups[1].Value; /* will result in http://finalurl.com */
}

答案 10 :(得分:-1)

我使用您的代码创建了此方法,并返回最终重定向的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不会返回最终的网址