۱۳۹۰/۰۷/۰۳

يافتن آدرس نهايي يك Url پس از Redirect


براي مثال آدرس http://feedproxy.google.com/~r/nettuts/~3/tWCksueANyY/ را در نظر بگيريد. گوگل پس از خريد feedburner ، از feedproxy.google.com جهت رديابي آدرس‌هاي فيدها استفاده مي‌كند؛‌ مثلا فيد شما چند نفر خواننده دارد، كدام موارد بيشتر خوانده شده، با چه مرورگرهايي، از چه مكان‌هايي و مواردي از اين دست. البته مي‌توان در تنظيمات فيدبرنر اين نوع آدرس دهي را خاموش كرد ولي به صورت پيش فرض فعال است. مشكل feedproxy.google.com هم اين است كه در ايران فيلتر است. بنابراين يافتن آدرس اصلي اين نوع لينك‌ها پس از Redirect نهايي مي‌تواند جهت ارائه عمومي آن‌ها مفيد باشد. با استفاده از قطعه كد زير مي‌توان اين آدرس را يافت:

using System;
using System.Net;

namespace Linq2Rss
{
    public class RedirectFinder 
    {
        public CookieContainer Cookies { set; get; }
        public string Url { get; set; }

        public string GetRedirectUrl()
        {
            var hops = 1;
            const int MaxRedirects = 20;

            do
            {
                var request = (HttpWebRequest)WebRequest.Create(Url);
                request.UserAgent = "MyUA";
                request.KeepAlive = true;
                request.Referer = Url;
                if (Cookies == null) Cookies = new CookieContainer();
                request.CookieContainer = Cookies;
                request.AllowAutoRedirect = false;

                using (var webResp = request.GetResponse() as HttpWebResponse)
                {
                    if ((webResp.StatusCode == HttpStatusCode.Found) ||
                    (webResp.StatusCode == HttpStatusCode.Redirect) ||
                    (webResp.StatusCode == HttpStatusCode.Moved) ||
                    (webResp.StatusCode == HttpStatusCode.MovedPermanently))
                    {
                        var newLocation = webResp.Headers["Location"];
                        if (newLocation.StartsWith("/"))
                        {
                            var uri = new Uri(Url);
                            Url = string.Format("{0}://{1}:{2}{3}", uri.Scheme, uri.Host, uri.Port, newLocation);
                        }
                        else
                            Url = newLocation;
                    }
                    else
                    {
                        if (webResp.StatusCode == HttpStatusCode.OK)
                            return Url;
                    }
                }

                hops++;
            } while (hops <= MaxRedirects);
            return Url;
        }
    }
}


براي يافتن آدرس واقعي يك Url پس از Redirect راهي بجز درخواست آن از وب سرور اوليه وجود ندارد. سپس وضعيت پاسخ داده شده بررسي مي‌شود؛ اگر حاوي Found ، Moved يا Redirect بود، به اين معنا است كه بايد آدرس جديد را از هدر پاسخ دريافتي استخراج كنيم. اين آدرس، در كليد Location ذخيره مي‌شود. اكنون يكبار ديگر نياز است تا اين آدرس جديد بررسي شود، زيرا ممكن است اين مورد هم به آدرس ديگري اشاره كند. در كل، كد فوق 20 بار اين بررسي را انجام خواهد داد (هر چند عموما در دو يا سه سعي به جواب خواهيم رسيد).