public static void HandleError(HttpCall call) { string errorMessage = GetErrorMessage(call); switch (call.HttpStatus) { case HttpStatusCode.Unauthorized: call.Exception = new System.UnauthorizedAccessException( errorMessage, call.Exception); break; case HttpStatusCode.BadRequest: call.Exception = new BadRequestException( errorMessage, call.Exception); break; case HttpStatusCode.NotFound: call.Exception = new NotFoundException( errorMessage, call.Exception); break; case HttpStatusCode.InternalServerError: call.Exception = new InternalServerErrorException( errorMessage, call.Exception, call.Response.Headers.RetryAfter); break; default: call.Exception = new SignhostRestApiClientException( errorMessage, call.Exception); break; } }
private static string BuildMessage(HttpCall call, Exception inner) { var sb = new StringBuilder(); if (call.Response != null && !call.Succeeded) { sb.AppendLine($"{call} failed with status code {(int)call.Response.StatusCode} ({call.Response.ReasonPhrase})."); } else if (inner != null) { sb.AppendLine($"{call} failed. {inner.Message}"); } else // in theory we should never get here. { sb.AppendLine($"{call} failed."); } if (!string.IsNullOrWhiteSpace(call.RequestBody)) { sb.AppendLine("Request body:").AppendLine(call.RequestBody); } if (!string.IsNullOrWhiteSpace(call.ErrorResponseBody)) { sb.AppendLine("Response body:").AppendLine(call.ErrorResponseBody); } return(sb.ToString().Trim()); }
/// <summary> /// Triggers the specified sync and async event handlers, usually defined on /// </summary> public static Task RaiseEventAsync(HttpRequestMessage request, FlurlEventType eventType) { var call = HttpCall.Get(request); var settings = call?.Settings; if (settings == null) { return(NoOpTask.Instance); } switch (eventType) { case FlurlEventType.BeforeCall: return(HandleEventAsync(settings.BeforeCall, settings.BeforeCallAsync, call)); case FlurlEventType.AfterCall: return(HandleEventAsync(settings.AfterCall, settings.AfterCallAsync, call)); case FlurlEventType.OnError: return(HandleEventAsync(settings.OnError, settings.OnErrorAsync, call)); default: return(NoOpTask.Instance); } }
private static string GetErrorMessage(HttpCall call) { string responseJson = call?.Response?.Content?.ReadAsStringAsync()?.Result; if (responseJson != null) { var error = JsonConvert.DeserializeAnonymousType(responseJson, new { Message = string.Empty }); return error.Message; } else { return "Unknown Signhost Error"; } }
/// <summary> /// Deserializes JSON-formatted HTTP response body to object of type T. Intended to chain off an async HTTP. /// </summary> /// <typeparam name="T">A type whose structure matches the expected JSON response.</typeparam> /// <returns>A Task whose result is an object containing data in the response body.</returns> /// <example>x = await url.PostAsync(data).ReceiveJson<T>()</example> public static async Task <T> ReceiveJson <T>(this Task <HttpResponseMessage> response) { var resp = await response.ConfigureAwait(false); var call = HttpCall.Get(resp.RequestMessage); try { using (var stream = await resp.Content.ReadAsStreamAsync().ConfigureAwait(false)) return(call.Settings.JsonSerializer.Deserialize <T>(stream)); } catch (Exception ex) { call.Exception = ex; throw new FlurlHttpException(call); } }
private static string BuildMessage(HttpCall call, Exception inner) { if (call.Response != null && !call.Response.IsSuccessStatusCode) { return string.Format("Request to {0} failed with status code {1} ({2}).", call.Request.RequestUri.AbsoluteUri, (int) call.Response.StatusCode, call.Response.ReasonPhrase); } else if (inner != null) { return string.Format("Request to {0} failed. {1}", call.Request.RequestUri.AbsoluteUri, inner.Message); } // in theory we should never get here. return string.Format("Request to {0} failed.", call.Request.RequestUri.AbsoluteUri); }
/// <summary> /// Creates and asynchronously sends an HttpRequestMethod, disposing HttpClient if AutoDispose it true. /// Mainly used to implement higher-level extension methods (GetJsonAsync, etc). /// </summary> /// <returns>A Task whose result is the received HttpResponseMessage.</returns> public async Task <HttpResponseMessage> SendAsync(HttpMethod verb, HttpContent content = null, CancellationToken?cancellationToken = null, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { try { var request = new HttpRequestMessage(verb, this.Url) { Content = content }; HttpCall.Set(request, this.Settings); return(await HttpClient.SendAsync(request, completionOption, cancellationToken ?? CancellationToken.None).ConfigureAwait(false)); } finally { if (AutoDispose) { Dispose(); } } }
private static string BuildMessage(HttpCall call, Exception inner) { if (call.Response != null && !call.Succeeded) { return(string.Format("Request to {0} failed with status code {1} ({2}).", call.Request.RequestUri.AbsoluteUri, (int)call.Response.StatusCode, call.Response.ReasonPhrase)); } if (inner != null) { return($"Request to {call.Request.RequestUri.AbsoluteUri} failed. {inner.Message}"); } // in theory we should never get here. return($"Request to {call.Request.RequestUri.AbsoluteUri} failed."); }
/// <summary> /// Deserializes JSON-formatted HTTP response body to object of type T. Intended to chain off an async HTTP. /// </summary> /// <typeparam name="T">A type whose structure matches the expected JSON response.</typeparam> /// <returns>A Task whose result is an object containing data in the response body.</returns> /// <example>x = await url.PostAsync(data).ReceiveJson<T>()</example> /// <exception cref="FlurlHttpException">Condition.</exception> public static async Task <T> ReceiveJson <T>(this Task <HttpResponseMessage> response) { var resp = await response.ConfigureAwait(false); if (resp == null) { return(default(T)); } var call = HttpCall.Get(resp.RequestMessage); using (var stream = await resp.Content.ReadAsStreamAsync().ConfigureAwait(false)) { try { return(call.FlurlRequest.Settings.JsonSerializer.Deserialize <T>(stream)); } catch (Exception ex) { call.Exception = new FlurlParsingException(call, "JSON", ex); await FlurlRequest.HandleExceptionAsync(call, call.Exception, CancellationToken.None).ConfigureAwait(false); return(default(T)); } } }
private static string BuildMessage(HttpCall call) { return($"Call timed out: {call}"); }
/// <summary> /// Initializes a new instance of the <see cref="FlurlHttpException"/> class. /// </summary> /// <param name="call">The call.</param> /// <param name="message">The message.</param> /// <param name="inner">The inner.</param> public FlurlHttpException(HttpCall call, string message, Exception inner) : base(message, inner) { Call = call; }
/// <summary> /// Initializes a new instance of the <see cref="FlurlHttpTimeoutException"/> class. /// </summary> /// <param name="call">The HttpCall instance.</param> /// <param name="inner">The inner exception.</param> public FlurlHttpTimeoutException(HttpCall call, Exception inner) : base(call, BuildMessage(call), inner) { }
/// <summary> /// Traces a failed HTTP request /// </summary> /// <param name="httpCall">The Flurl HTTP call instance, containing information about the request and response.</param> public static void TraceFailedHttpCall(HttpCall httpCall) { Http.TraceData(TraceEventType.Error, 0, JsonConvert.SerializeObject(httpCall, Formatting.Indented)); Http.Flush(); }
/// <summary> /// Traces an HTTP request /// </summary> /// <param name="httpCall">The Flurl HTTP call instance, containing information about the request and response.</param> public static void TraceHttpCall(HttpCall httpCall) { Http.TraceData(TraceEventType.Information, 0, JsonConvert.SerializeObject(httpCall, Formatting.Indented)); }
private static string BuildMessage(HttpCall call) { return(string.Format("Request to {0} timed out.", call)); }
private static void SetUserAgentHeader(HttpCall call) { foreach (var userAgent in Configuration.UserAgents) { call.Request.Headers.UserAgent.Add(userAgent); } }
private static string BuildMessage(HttpCall call) { return($"{call} timed out."); }
public FlurlHttpException(HttpCall call, string message, Exception inner) : base(message, inner) { this.Call = call; }
/// <summary> /// Initializes a new instance of the <see cref="FlurlHttpException"/> class. /// </summary> /// <param name="call">The call.</param> /// <param name="inner">The inner.</param> public FlurlHttpException(HttpCall call, Exception inner) : this(call, BuildMessage(call, inner), inner) { }
public FlurlHttpException(HttpCall call, Exception inner) : this(call, BuildMessage(call, inner), inner) { }
/// <summary> /// Initializes a new instance of the <see cref="FlurlHttpException"/> class. /// </summary> /// <param name="call">The call.</param> /// <param name="message">The message.</param> /// <param name="inner">The inner.</param> public FlurlHttpException(HttpCall call, string message, Exception inner) : this(call, message, null, inner) { }
/// <summary> /// Initializes a new instance of the <see cref="Flurl.Http.FlurlParsingException"/> class. /// </summary> /// <param name="call">The HttpCall instance.</param> /// <param name="expectedFormat">The format that could not be parsed to, i.e. JSON.</param> /// <param name="responseBody">The response body.</param> /// <param name="inner">The inner exception.</param> public FlurlParsingException(HttpCall call, string expectedFormat, string responseBody, Exception inner) : base(call, BuildMessage(call, expectedFormat), responseBody, inner) { ExpectedFormat = expectedFormat; }
public FlurlHttpException(HttpCall call) : this(call, BuildMessage(call, null), null) { }
private static string BuildMessage(HttpCall call) { return string.Format("Request to {0} timed out.", call); }
public FlurlHttpTimeoutException(HttpCall call, Exception inner) : base(call, BuildMessage(call), inner) { }
private static string BuildMessage(HttpCall call, string expectedFormat) { return($"Response could not be deserialized to {expectedFormat}: {call}"); }
private static Task HandleEventAsync(Action <HttpCall> syncHandler, Func <HttpCall, Task> asyncHandler, HttpCall call) { if (syncHandler != null) { syncHandler(call); } if (asyncHandler != null) { return(asyncHandler(call)); } return(NoOpTask.Instance); }
/// <summary> /// Initializes a new instance of the <see cref="FlurlHttpException"/> class. /// </summary> /// <param name="call">The call.</param> /// <param name="message">The message.</param> /// <param name="capturedResponseBody">The captured response body, if available.</param> /// <param name="inner">The inner.</param> public FlurlHttpException(HttpCall call, string message, string capturedResponseBody, Exception inner) : base(message, inner) { Call = call; _capturedResponseBody = capturedResponseBody; }
/// <summary> /// Creates and asynchronously sends an HttpRequestMessage. /// Mainly used to implement higher-level extension methods (GetJsonAsync, etc). /// </summary> /// <param name="verb">The HTTP method used to make the request.</param> /// <param name="content">Contents of the request body.</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation. Optional.</param> /// <param name="completionOption">The HttpCompletionOption used in the request. Optional.</param> /// <returns>A Task whose result is the received HttpResponseMessage.</returns> public async Task <HttpResponseMessage> SendAsync(HttpMethod verb, HttpContent content = null, CancellationToken?cancellationToken = null, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { var request = new HttpRequestMessage(verb, Url) { Content = content }; var call = new HttpCall(this, request); await HandleEventAsync(Settings.BeforeCall, Settings.BeforeCallAsync, call).ConfigureAwait(false); request.RequestUri = new Uri(Url); // in case it was modifed in the handler above var userToken = cancellationToken ?? CancellationToken.None; var token = userToken; if (Settings.Timeout.HasValue) { var cts = CancellationTokenSource.CreateLinkedTokenSource(userToken); cts.CancelAfter(Settings.Timeout.Value); token = cts.Token; } call.StartedUtc = DateTime.UtcNow; try { WriteHeaders(request); if (Settings.CookiesEnabled) { WriteRequestCookies(request); } if (Client.CheckAndRenewConnectionLease()) { request.Headers.ConnectionClose = true; } call.Response = await Client.HttpClient.SendAsync(request, completionOption, token).ConfigureAwait(false); call.Response.RequestMessage = request; if (call.Succeeded) { return(call.Response); } // response content is only awaited here if the call failed. if (call.Response.Content != null) { call.ErrorResponseBody = await call.Response.Content.StripCharsetQuotes().ReadAsStringAsync().ConfigureAwait(false); } throw new FlurlHttpException(call, null); } catch (Exception ex) { call.Exception = ex; await HandleEventAsync(Settings.OnError, Settings.OnErrorAsync, call).ConfigureAwait(false); if (call.ExceptionHandled) { return(call.Response); } if (ex is OperationCanceledException && !userToken.IsCancellationRequested) { throw new FlurlHttpTimeoutException(call, ex); } if (ex is FlurlHttpException) { throw; } throw new FlurlHttpException(call, ex); } finally { request.Dispose(); if (Settings.CookiesEnabled) { ReadResponseCookies(call.Response); } call.EndedUtc = DateTime.UtcNow; await HandleEventAsync(Settings.AfterCall, Settings.AfterCallAsync, call).ConfigureAwait(false); } }
/// <summary> /// Initializes a new instance of the <see cref="FlurlHttpException"/> class. /// </summary> /// <param name="call">The call.</param> public FlurlHttpException(HttpCall call) : this(call, BuildMessage(call, null), null) { }
private static Task HandleEventAsync(Action <HttpCall> syncHandler, Func <HttpCall, Task> asyncHandler, HttpCall call) { syncHandler?.Invoke(call); if (asyncHandler != null) { return(asyncHandler(call)); } return(Task.FromResult(0)); }