Пример #1
0
        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;
            }
        }
Пример #2
0
        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());
        }
Пример #3
0
        /// <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);
            }
        }
Пример #4
0
 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&lt;T&gt;()</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);
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
 /// <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();
         }
     }
 }
Пример #8
0
        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&lt;T&gt;()</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));
                }
            }
        }
Пример #10
0
 private static string BuildMessage(HttpCall call)
 {
     return($"Call timed out: {call}");
 }
Пример #11
0
 /// <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;
 }
Пример #12
0
 /// <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)
 {
 }
Пример #13
0
 /// <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();
 }
Пример #14
0
 /// <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));
 }
Пример #15
0
 private static string BuildMessage(HttpCall call)
 {
     return(string.Format("Request to {0} timed out.", call));
 }
Пример #16
0
 private static void SetUserAgentHeader(HttpCall call)
 {
     foreach (var userAgent in Configuration.UserAgents)
     {
         call.Request.Headers.UserAgent.Add(userAgent);
     }
 }
Пример #17
0
 private static string BuildMessage(HttpCall call)
 {
     return($"{call} timed out.");
 }
Пример #18
0
 public FlurlHttpException(HttpCall call, string message, Exception inner)
     : base(message, inner)
 {
     this.Call = call;
 }
Пример #19
0
 /// <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)
 {
 }
Пример #20
0
 public FlurlHttpException(HttpCall call, Exception inner)
     : this(call, BuildMessage(call, inner), inner)
 {
 }
Пример #21
0
 /// <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)
 {
 }
Пример #22
0
 /// <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;
 }
Пример #23
0
 public FlurlHttpException(HttpCall call)
     : this(call, BuildMessage(call, null), null)
 {
 }
Пример #24
0
 private static string BuildMessage(HttpCall call)
 {
     return string.Format("Request to {0} timed out.", call);
 }
Пример #25
0
 public FlurlHttpTimeoutException(HttpCall call, Exception inner)
     : base(call, BuildMessage(call), inner)
 {
 }
Пример #26
0
 private static string BuildMessage(HttpCall call, string expectedFormat)
 {
     return($"Response could not be deserialized to {expectedFormat}: {call}");
 }
Пример #27
0
 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);
 }
Пример #28
0
 /// <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;
 }
Пример #29
0
        /// <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);
            }
        }
Пример #30
0
 /// <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)
 {
 }
Пример #31
0
 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));
 }