private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
        {
            var request = CreateWebRequest(options.Url);
            var httpWebRequest = request as HttpWebRequest;

            if (httpWebRequest != null)
            {
                AddRequestHeaders(httpWebRequest, options);

                httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
            }

            request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);

            if (httpWebRequest != null)
            {
                if (options.EnableKeepAlive)
                {
                    httpWebRequest.KeepAlive = true;
                }
            }

            request.Method = method;
            request.Timeout = options.TimeoutMs;
            
            if (httpWebRequest != null)
            {
                if (!string.IsNullOrEmpty(options.Host))
                {
                    httpWebRequest.Host = options.Host;
                }

                if (!string.IsNullOrEmpty(options.Referer))
                {
                    httpWebRequest.Referer = options.Referer;
                }
            }

            return request;
        }
        /// <summary>
        /// Throws the cancellation exception.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <param name="client">The client.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="exception">The exception.</param>
        /// <returns>Exception.</returns>
        private Exception GetCancellationException(HttpRequestOptions options, HttpClientInfo client, CancellationToken cancellationToken, OperationCanceledException exception)
        {
            // If the HttpClient's timeout is reached, it will cancel the Task internally
            if (!cancellationToken.IsCancellationRequested)
            {
                var msg = string.Format("Connection to {0} timed out", options.Url);

                if (options.LogErrors)
                {
                }

                client.LastTimeout = DateTime.UtcNow;

                // Throw an HttpException so that the caller doesn't think it was cancelled by user code
                return new HttpException(msg, exception)
                {
                    IsTimedOut = true
                };
            }

            return exception;
        }
        private void EnsureSuccessStatusCode(HttpClientInfo client, HttpWebResponse response, HttpRequestOptions options)
        {
            var statusCode = response.StatusCode;

            var isSuccessful = statusCode >= HttpStatusCode.OK && statusCode <= (HttpStatusCode)299;

            if (!isSuccessful)
            {
                if (options.LogErrorResponseBody)
                {
                    try
                    {
                        using (var stream = response.GetResponseStream())
                        {
                            if (stream != null)
                            {
                                using (var reader = new StreamReader(stream))
                                {
                                    var msg = reader.ReadToEnd();

                                }
                            }
                        }
                    }
                    catch
                    {

                    }
                }
                throw new HttpException(response.StatusDescription)
                {
                    StatusCode = response.StatusCode
                };
            }
        }
        private Exception GetException(Exception ex, HttpRequestOptions options, HttpClientInfo client)
        {
            if (ex is HttpException)
            {
                return ex;
            }

            var webException = ex as WebException
                ?? ex.InnerException as WebException;

            if (webException != null)
            {
                if (options.LogErrors)
                {
                }

                var exception = new HttpException(ex.Message, ex);

                var response = webException.Response as HttpWebResponse;
                if (response != null)
                {
                    exception.StatusCode = response.StatusCode;

                    if ((int)response.StatusCode == 429)
                    {
                        client.LastTimeout = DateTime.UtcNow;
                    }
                }

                return exception;
            }

            var operationCanceledException = ex as OperationCanceledException
                ?? ex.InnerException as OperationCanceledException;

            if (operationCanceledException != null)
            {
                return GetCancellationException(options, client, options.CancellationToken, operationCanceledException);
            }

            if (options.LogErrors)
            {
            }

            return ex;
        }
 private void ValidateParams(HttpRequestOptions options)
 {
     if (string.IsNullOrEmpty(options.Url))
     {
         throw new ArgumentNullException("options");
     }
 }
 public Task<HttpResponseInfo> Post(HttpRequestOptions options)
 {
     return SendAsync(options, "POST");
 }
        /// <summary>
        /// Performs a POST request
        /// </summary>
        /// <param name="options">The options.</param>
        /// <param name="postData">Params to add to the POST data.</param>
        /// <returns>stream on success, null on failure</returns>
        public async Task<Stream> Post(HttpRequestOptions options, Dictionary<string, string> postData)
        {
            options.SetPostData(postData);

            var response = await Post(options).ConfigureAwait(false);

            return response.Content;
        }
        private async Task<HttpResponseInfo> SendAsyncInternal(HttpRequestOptions options, string httpMethod)
        {
            ValidateParams(options);

            options.CancellationToken.ThrowIfCancellationRequested();

            var client = GetHttpClient(GetHostFromUrl(options.Url), options.EnableHttpCompression);

            if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < TimeoutSeconds)
            {
                throw new HttpException(string.Format("Cancelling connection to {0} due to a previous timeout.", options.Url))
                {
                    IsTimedOut = true
                };
            }

            var httpWebRequest = GetRequest(options, httpMethod, options.EnableHttpCompression);

            if (options.RequestContentBytes != null ||
                !string.IsNullOrEmpty(options.RequestContent) ||
                string.Equals(httpMethod, "post", StringComparison.OrdinalIgnoreCase))
            {
                var bytes = options.RequestContentBytes ??
                    Encoding.UTF8.GetBytes(options.RequestContent ?? string.Empty);

                httpWebRequest.ContentType = options.RequestContentType ?? "application/x-www-form-urlencoded";

                httpWebRequest.ContentLength = bytes.Length;
                httpWebRequest.GetRequestStream().Write(bytes, 0, bytes.Length);
            }

            if (options.ResourcePool != null)
            {
                await options.ResourcePool.WaitAsync(options.CancellationToken).ConfigureAwait(false);
            }

            if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < TimeoutSeconds)
            {
                if (options.ResourcePool != null)
                {
                    options.ResourcePool.Release();
                }

                throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true };
            }

            if (options.LogRequest)
            {
            }

            try
            {
                options.CancellationToken.ThrowIfCancellationRequested();

                if (!options.BufferContent)
                {
                    var response = await GetResponseAsync(httpWebRequest, TimeSpan.FromMilliseconds(options.TimeoutMs)).ConfigureAwait(false);

                    var httpResponse = (HttpWebResponse)response;

                    EnsureSuccessStatusCode(client, httpResponse, options);

                    options.CancellationToken.ThrowIfCancellationRequested();

                    return GetResponseInfo(httpResponse, httpResponse.GetResponseStream(), GetContentLength(httpResponse), httpResponse);
                }

                using (var response = await GetResponseAsync(httpWebRequest, TimeSpan.FromMilliseconds(options.TimeoutMs)).ConfigureAwait(false))
                {
                    var httpResponse = (HttpWebResponse)response;

                    EnsureSuccessStatusCode(client, httpResponse, options);

                    options.CancellationToken.ThrowIfCancellationRequested();

                    using (var stream = httpResponse.GetResponseStream())
                    {
                        var memoryStream = new MemoryStream();

                        await stream.CopyToAsync(memoryStream).ConfigureAwait(false);

                        memoryStream.Position = 0;

                        return GetResponseInfo(httpResponse, memoryStream, memoryStream.Length, null);
                    }
                }
            }
            catch (OperationCanceledException ex)
            {
                throw GetCancellationException(options, client, options.CancellationToken, ex);
            }
            catch (Exception ex)
            {
                throw GetException(ex, options, client);
            }
            finally
            {
                if (options.ResourcePool != null)
                {
                    options.ResourcePool.Release();
                }
            }
        }
        /// <summary>
        /// send as an asynchronous operation.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <param name="httpMethod">The HTTP method.</param>
        /// <returns>Task{HttpResponseInfo}.</returns>
        /// <exception cref="HttpException">
        /// </exception>
        public async Task<HttpResponseInfo> SendAsync(HttpRequestOptions options, string httpMethod)
        {
            HttpResponseInfo response;

            if (options.CacheMode == CacheMode.None)
            {
                response = await SendAsyncInternal(options, httpMethod).ConfigureAwait(false);
                return response;
            }

            response = await SendAsyncInternal(options, httpMethod).ConfigureAwait(false);

            return response;
        }
        /// <summary>
        /// Performs a GET request and returns the resulting stream
        /// </summary>
        /// <param name="options">The options.</param>
        /// <returns>Task{Stream}.</returns>
        public async Task<Stream> Get(HttpRequestOptions options)
        {
            var response = await GetResponse(options).ConfigureAwait(false);

            return response.Content;
        }
 /// <summary>
 /// Gets the response internal.
 /// </summary>
 /// <param name="options">The options.</param>
 /// <returns>Task{HttpResponseInfo}.</returns>
 public Task<HttpResponseInfo> GetResponse(HttpRequestOptions options)
 {
     return SendAsync(options, "GET");
 }
 private void AddRequestHeaders(HttpWebRequest request, HttpRequestOptions options)
 {
     foreach (var header in options.RequestHeaders.ToList())
     {
         if (string.Equals(header.Key, "Accept", StringComparison.OrdinalIgnoreCase))
         {
             request.Accept = header.Value;
         }
         else if (string.Equals(header.Key, "User-Agent", StringComparison.OrdinalIgnoreCase))
         {
             request.UserAgent = header.Value;
         }
         else
         {
             request.Headers.Set(header.Key, header.Value);
         }
     }
 }