An HTTP wrapper class that abstracts away the common needs for adding post keys and firing update events as data is received. This class is real easy to use with many common operations requiring single method calls. The class also provides automated cookie and state handling, GZip compression decompression, simplified proxy and authentication mechanisms to provide a simple single level class interface. The underlying WebRequest is also exposed so you will not loose any functionality from the .NET BCL class.
       public async Task PlainHTtpRequest()
        {
            var client = new HttpClient();
            string result = await client.DownloadStringAsync("http://west-wind.com");

            Console.WriteLine(result);
        }
        public void InvalidUrlTest()
        {
            var client = new HttpClient();

            var html = client.DownloadString("http://weblog.west-wind.com/nonexistantpage.htm");
            Assert.IsTrue(client.WebResponse.StatusCode == System.Net.HttpStatusCode.NotFound);            
            Console.WriteLine(client.WebResponse.StatusCode);                        
        }
        public void HttpTimingsTest()
        {
            var client = new HttpClient();

            var html = client.DownloadString("http://weblog.west-wind.com/posts/2015/Jan/06/Using-Cordova-and-Visual-Studio-to-build-iOS-Mobile-Apps");

            Console.WriteLine(client.WebResponse.ContentLength);
            Console.WriteLine(client.HttpTimings.StartedTime);
            Console.WriteLine("First Byte: " + client.HttpTimings.TimeToFirstByteMs);
            Console.WriteLine("Last Byte: " + client.HttpTimings.TimeToLastByteMs);            
        }
        private HttpClient CreateHttpClient(string url, string json = null)
        {
            var http = new Westwind.Utilities.InternetTools.HttpClient();

            http.CreateWebRequestObject(url);
            CurrentUrl    = url;
            http.PostMode = HttpPostMode.Json;
            http.WebRequest.Headers.Add("Accept-Charset", "utf-8");
            http.WebRequest.ContentType = "application/json";
            http.WebRequest.Headers.Add("Authorization", "Bearer " + MediumApiUserToken);


            if (!string.IsNullOrEmpty(json))
            {
                http.AddPostKey(json);
            }

            return(http);
        }
        public async Task ReusePlainHTtpRequest()
        {
            string url = "http://localhost/aspnetperf/static.htm";

            var client = new HttpClient();
            string result = client.DownloadString(url);

            var swatch = new Stopwatch();
            swatch.Start();

            for (int i = 0; i < 100000; i++)
            {
                result = client.DownloadString(url);
            }

            swatch.Stop();

            Console.WriteLine(swatch.ElapsedMilliseconds + " " + result);
        }
        public ActionResult New(string message = null)
        {
            ViewData["UserState"] = AppUserState;

            var snippet = new CodeSnippet();
            snippet.Author = this.AppUserState.Name;

            string codeUrl = Request.QueryString["url"];            

            if (!string.IsNullOrEmpty(codeUrl))
            {                
                HttpClient client = new HttpClient();
                client.Timeout = 4000;
                snippet.Code = client.DownloadString(codeUrl);

                snippet.Title = Path.GetFileName(codeUrl); 
                string extension = Path.GetExtension(codeUrl);

                snippet.Language = CodeFormatFactory.GetStringLanguageFromExtension(extension);    
                Response.Write(snippet.Language);
            }

            if (!string.IsNullOrEmpty(message))            
                this.ErrorDisplay.ShowMessage(message);
            
            return this.View("New",snippet);
        }
        public ActionResult ShowUrl()
        {
            string url = Request.QueryString["url"];
            string lang = Request.QueryString["language"];
            if (string.IsNullOrEmpty(lang))
                lang = Request.QueryString["lang"] ?? string.Empty;

            if (lang.ToLower() == "csharp")
                lang = "C#";                

            ShowSnippetViewModel model = new ShowSnippetViewModel(this);
            model.AppUserState = this.AppUserState;

            ViewData["originalUrl"] = url;
            ViewData["fileName"] = Path.GetFileName(url);
            ViewData["language"] = lang;

            if (string.IsNullOrEmpty(url))
            {
                ViewData["languageList"] = this.GetLanguageList(lang);
                return View(model);
            }

            HttpClient client = new HttpClient();
            client.Timeout = 4000;
            
            string result = client.DownloadString(url);

            if (result == null)            
                return 
                    this.DisplayErrorPage("Unable to retrieve Code Url", client.ErrorMessage, null);

            if (result.Length > App.Configuration.MaxCodeLength)
                return this.DisplayErrorPage("Snippet is too large", "Your code snippet to display is too long. Snippets can be no larger than " + App.Configuration.MaxCodeLength.ToString("n0") + " bytes.",null);

            busCodeSnippet snippetBusiness = new busCodeSnippet();

            if (string.IsNullOrEmpty(lang))
            {
                string extension = Path.GetExtension(url).ToLower();
                
                if (extension.StartsWith("."))
                    lang = extension.Substring(1);
            }

            model.FormattedCode = snippetBusiness.GetFormattedCode(result, lang, false, false);
            
            snippetBusiness.Dispose();

            return this.View(model);
        }
        async Task<int> RunHttpRequestAsync()
        {
            using (var client = new HttpClient())
            {
                client.CreateWebRequestObject(testUrl);                
                string result = await client.DownloadStringAsync(testUrl);
            }
            Interlocked.Increment(ref counter);

            return 0;
        }
        int RunHttpRequest()
        {
            using (var client = new HttpClient())
            {                
                string result =  client.DownloadString(testUrl);                
            }
            Interlocked.Increment(ref counter2);

            return 0;
        }
        /// <summary>
        /// Checks an individual site and returns a new HttpRequestData object
        /// </summary>
        /// <param name="reqData"></param>
        /// <returns></returns>
        public HttpRequestData CheckSite(HttpRequestData reqData)
        {
            if (CancelThreads)
                return null;

            // create a new instance
            var result = HttpRequestData.Copy(reqData);

            result.ErrorMessage = "Request is incomplete"; // assume not going to make it

            result.IsWarmupRequest =  StartTime.AddSeconds(Options.WarmupSeconds) > DateTime.UtcNow;

            try
            {
                var client = new HttpClient();
                

                    if (!string.IsNullOrEmpty(Options.ReplaceDomain))
                        result.Url = ReplaceDomain(result.Url);

                    if (!string.IsNullOrEmpty(Options.ReplaceQueryStringValuePairs))
                        result.Url = ReplaceQueryStringValuePairs(result.Url, Options.ReplaceQueryStringValuePairs);

                    client.CreateWebRequestObject(result.Url);
                    var webRequest = client.WebRequest;

                    // TODO: Connection Groups might help with sharing connections more efficiently
                    // Initial tests show no improvements - more research required
                    //webRequest.ConnectionGroupName = "_WebSurge_" + Thread.CurrentContext.ContextID;

                    if (!string.IsNullOrEmpty(Options.Username))
                    {
                        client.Username = Options.Username;
                        webRequest.UnsafeAuthenticatedConnectionSharing = true;
                    }
                    if (!string.IsNullOrEmpty(Options.Password))
                        client.Password = Options.Password;

                    webRequest.Method = reqData.HttpVerb;

                    client.ContentType = reqData.ContentType;
                    client.Timeout = Options.RequestTimeoutMs/1000;                    
                
                    // don't auto-add gzip headers and don't decode by default
                    client.UseGZip = false;

                    if (Options.NoContentDecompression)
                        webRequest.AutomaticDecompression = DecompressionMethods.None;
                    else
                        webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

                    if (!string.IsNullOrEmpty(reqData.RequestContent))
                    {
                        var data = reqData.GetRequestContentBytes();
                        client.AddPostKey(data);
                    }
                    else
                    {
                        webRequest.ContentLength = 0;
                    }

                    foreach (var header in result.Headers)
                    {
                        var lheader = header.Name.ToLower();

                        // Header Overrides that fail if you try to set them
                        // directly in HTTP
                        if (lheader == "cookie" && !string.IsNullOrEmpty(Options.ReplaceCookieValue))
                        {
                            string cookie = Options.ReplaceCookieValue;
                            webRequest.Headers.Add("Cookie", cookie);
                            header.Value = cookie;
                            continue;
                        }
                        if (lheader == "authorization" && !string.IsNullOrEmpty(Options.ReplaceAuthorization))
                        {
                            webRequest.Headers.Add("Authorization", Options.ReplaceAuthorization);
                            header.Value = Options.ReplaceAuthorization;
                            continue;
                        }
                        if (lheader == "user-agent")
                        {
                            client.UserAgent = header.Value;
                            continue;
                        }
                        if (lheader == "accept")
                        {
                            webRequest.Accept = header.Value;
                            continue;
                        }
                        if (lheader == "referer")
                        {
                            webRequest.Referer = header.Value;
                            continue;
                        }
                        if (lheader == "connection")
                        {
                            if (header.Value.ToLower() == "keep-alive")
                                webRequest.KeepAlive = true; // this has no effect
                            else if (header.Value.ToLower() == "close")
                                webRequest.KeepAlive = false;
                            continue;
                        }
                        // set above view property
                        if (lheader == "content-type")
                            continue;
                        // not handled at the moment
                        if (lheader == "proxy-connection")
                            continue; // TODO: Figure out what to do with this one

                        // set explicitly via properties
                        if (lheader == "transfer-encoding")
                        {
                            webRequest.TransferEncoding = header.Value;
                            continue;
                        }
                        if (lheader == "date")
                            continue;
                        if (lheader == "expect")
                        {
                            //webRequest.Expect = header.Value;
                            continue;
                        }
                        if (lheader == "if-modified-since")
                            continue;

                        webRequest.Headers.Add(header.Name, header.Value);
                    }

                    foreach (var plugin in App.Plugins)
                    {
                        try
                        {
                            if (!plugin.OnBeforeRequestSent(result))
                                return result;
                        }
                        catch (Exception ex)
                        {
                            App.Log(plugin.GetType().Name + " failed in OnBeforeRequestSent(): " + ex.Message);
                        }
                    }

                    DateTime dt = DateTime.UtcNow;

                    if (CancelThreads)
                        return null;

                    string httpOutput = client.DownloadString(result.Url);

                    if (CancelThreads)
                        return null;

                    result.TimeTakenMs = (int) DateTime.UtcNow.Subtract(dt).TotalMilliseconds;
                    // result.TimeToFirstByteMs = client.Timings.TimeToFirstByteMs;

                    if (client.Error || client.WebResponse == null)
                    {
                        result.ErrorMessage = client.ErrorMessage;
                        return result;
                    }

                    result.StatusCode = ((int) client.WebResponse.StatusCode).ToString();
                    result.StatusDescription = client.WebResponse.StatusDescription ?? string.Empty;
                    result.TimeToFirstByteMs = client.HttpTimings.TimeToFirstByteMs;

                    result.ResponseLength = (int) client.WebResponse.ContentLength;
                    result.ResponseContent = httpOutput;

                    StringBuilder sb = new StringBuilder();
                    foreach (string key in client.WebResponse.Headers.Keys)
                    {
                        sb.AppendLine(key + ": " + client.WebResponse.Headers[key]);
                    }

                    result.ResponseHeaders = sb.ToString();

                    // update to actual Http headers sent
                    result.Headers.Clear();
                    foreach (string key in webRequest.Headers.Keys)
                    {
                        result.Headers.Add(new HttpRequestHeader() {Name = key, Value = webRequest.Headers[key]});
                    }

                    char statusCode = result.StatusCode[0];
                    if (statusCode == '4' || statusCode == '5')
                    {
                        result.IsError = true;
                        result.ErrorMessage = client.WebResponse.StatusDescription;
                    }
                    else
                    {
                        result.IsError = false;
                        result.ErrorMessage = null;

                        if (Options.MaxResponseSize > 0 && result.ResponseContent.Length > Options.MaxResponseSize)
                            result.ResponseContent = result.ResponseContent.Substring(0, Options.MaxResponseSize);
                    }

                //} // using client
                client.Dispose();

                if (!CancelThreads)
                    OnRequestProcessed(result);

                return result;
                
            }

            // these will occur on shutdown - don't log since they will return
            // unstable results - just ignore
            catch (ThreadAbortException)
            {                
                return null;
            }
            catch (Exception ex)
            {                
                Console.WriteLine("Exception: " + ex.Message);
                result.IsError = true;
                result.ErrorMessage = "CheckSite Error: " + ex.GetBaseException().Message;
                
                if (!CancelThreads)
                    OnRequestProcessed(result);

                return result;
            }
        }
        public bool IsWebSurgeAllowedForUrl(string serverUrl)
        {
            string serverRootUrl = GetServerRootUrl(serverUrl);

            if (new Uri(serverRootUrl).IsLoopback)
                return true;

            var http = new HttpClient();
            if (!string.IsNullOrEmpty(StressTester.Options.Username))
                http.Username = StressTester.Options.Username;
            if (!string.IsNullOrEmpty(StressTester.Options.Password))
                http.Password = StressTester.Options.Password;

            try
            {
                var text = http.DownloadString(serverRootUrl + "websurge-allow.txt");
                if (http.WebResponse.StatusCode != System.Net.HttpStatusCode.OK || text.Length > 5)
                {
                    string robots = http.DownloadString(serverRootUrl + "robots.txt");
                    if (!robots.Contains("Allow: WebSurge"))
                        return false;
                }
            }
            catch
            {
                return false;
            }

            return true;
        }