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); } } }