/// <summary> /// Add a header to this request. /// </summary> /// <param name="builder">The builder we're working on.</param> /// <param name="name">The header name to add to this request.</param> /// <param name="value">The header value (for <paramref name="name"/>) to add to this request.</param> /// <returns>The request builder for chaining.</returns> public static IRequestBuilder AddHeader(this IRequestBuilder builder, string name, string value) { if (!string.IsNullOrEmpty(name)) { try { builder.Message.Headers.Add(name, value); } catch (Exception e) { var wrapper = new HttpClientException("Unable to set header: " + name + " to '" + value + "'", builder.Message.RequestUri, e); builder.GetSettings().OnException(builder, new HttpExceptionArgs(builder, wrapper)); } } return(builder); }
/// <summary> /// Adds headers to this request. /// </summary> /// <param name="builder">The builder we're working on.</param> /// <param name="headers">The headers to add to this request.</param> /// <returns>The request builder for chaining.</returns> public static IRequestBuilder AddHeaders(this IRequestBuilder builder, IDictionary <string, string> headers) { if (headers == null) { return(builder); } var pHeaders = builder.Message.Headers; foreach (var kv in headers) { try { //pHeaders.Add(kv.Key, kv.Value); switch (kv.Key) { // certain headers must be accessed via the named property on the WebRequest case "Accept": pHeaders.Accept.ParseAdd(kv.Value); break; // case "Connection": break; // case "proxy-connection": break; // case "Proxy-Connection": break; // case "Content-Length": break; case "Content-Type": builder.Message.Content.Headers.ContentType = new MediaTypeHeaderValue(kv.Value); break; // case "Host": break; // case "If-Modified-Since": pHeaders.IfModifiedSince = DateTime.ParseExact(kv.Value, "R", CultureInfo.InvariantCulture); break; // case "Referer": pHeaders.Referrer = new Uri(kv.Value); break; // case "User-Agent": pHeaders.UserAgent.ParseAdd("Stack Exchange (Proxy)"); break; default: pHeaders.Add(kv.Key, kv.Value); break; } } catch (Exception e) { var wrapper = new HttpClientException("Unable to set header: " + kv.Key + " to '" + kv.Value + "'", builder.Message.RequestUri, e); builder.GetSettings().OnException(builder, new HttpExceptionArgs(builder, wrapper)); } } return(builder); }
internal static async Task <HttpCallResponse <T> > SendAsync <T>(IRequestBuilder <T> builder, HttpMethod method, CancellationToken cancellationToken = default) { // default to global settings var settings = builder.GetSettings(); settings.OnBeforeSend(builder, builder.Inner); var request = builder.Inner.Message; request.Method = method; Exception exception = null; HttpResponseMessage response = null; try { using (settings.ProfileRequest?.Invoke(request)) using (request) { // Get the pool var pool = builder.Inner.ClientPool ?? settings.ClientPool; var completionOption = builder.Inner.BufferResponse ? HttpCompletionOption.ResponseContentRead : HttpCompletionOption.ResponseHeadersRead; // Send the request using (response = await pool.Get(builder.Inner).SendAsync(request, completionOption, cancellationToken)) { // If we haven't ignored it, throw and we'll log below // This isn't ideal cntrol flow behavior, but it's the only way to get proper stacks if (!response.IsSuccessStatusCode && !builder.Inner.IgnoredResponseStatuses.Contains(response.StatusCode)) { exception = new HttpClientException($"Response code was {(int)response.StatusCode} ({response.StatusCode}) from {response.RequestMessage.RequestUri}: {response.ReasonPhrase}", response.StatusCode, response.RequestMessage.RequestUri); stackTraceString.SetValue(exception, new StackTrace(true).ToString()); } else { var data = await builder.Handler(response); return(HttpCallResponse.Create(response, data)); } } } } catch (OperationCanceledException ex) { exception = cancellationToken.IsCancellationRequested ? new HttpClientException("HttpClient request cancelled by token request.", builder.Inner.Message.RequestUri, ex) : new HttpClientException("HttpClient request timed out. Timeout: " + builder.Inner.Timeout.TotalMilliseconds.ToString("N0") + "ms", builder.Inner.Message.RequestUri, ex); } catch (Exception ex) { exception = ex; } // Use the response if we have it - request if not var result = response != null ? HttpCallResponse.Create <T>(response, exception) : HttpCallResponse.Create <T>(request, exception); // Add caller member bits to the exception data regardless of where it's eventually logged. (builder.Inner as HttpBuilder)?.AddExceptionData(exception); // If we're told not to log at all, don't log if (builder.Inner.LogErrors) { var args = new HttpExceptionArgs(builder.Inner, exception); builder.Inner.OnBeforeExceptionLog(args); if (!args.AbortLogging) { settings.OnException(builder, args); } } return(result); }