Example #1
0
        private async Task <HttpResponse> ExecuteWithRetryAsync(
            Uri endpoint,
            IDictionary <string, string> headers,
            HttpContent body,
            HttpMethod method,
            ICoreLogger logger,
            bool doNotThrow = false,
            bool retry      = true)
        {
            Exception    timeoutException = null;
            bool         isRetryable      = false;
            bool         is5xxError       = false;
            HttpResponse response         = null;

            try
            {
                HttpContent clonedBody = body;
                if (body != null)
                {
                    // Since HttpContent would be disposed by underlying client.SendAsync(),
                    // we duplicate it so that we will have a copy in case we would need to retry
                    clonedBody = await CloneHttpContentAsync(body).ConfigureAwait(false);
                }

                response = await ExecuteAsync(endpoint, headers, clonedBody, method).ConfigureAwait(false);

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    return(response);
                }

                logger.Info(string.Format(CultureInfo.InvariantCulture,
                                          MsalErrorMessage.HttpRequestUnsuccessful,
                                          (int)response.StatusCode, response.StatusCode));


                is5xxError  = (int)response.StatusCode >= 500 && (int)response.StatusCode < 600;
                isRetryable = is5xxError && !HasRetryAfterHeader(response);
            }
            catch (TaskCanceledException exception)
            {
                logger.Error("The HTTP request failed or it was canceled. " + exception.Message);
                isRetryable      = true;
                timeoutException = exception;
            }

            if (isRetryable && retry)
            {
                logger.Info("Retrying one more time..");
                await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

                return(await ExecuteWithRetryAsync(
                           endpoint,
                           headers,
                           body,
                           method,
                           logger,
                           doNotThrow,
                           retry : false).ConfigureAwait(false));
            }

            logger.Warning("Request retry failed.");
            if (timeoutException != null)
            {
                throw new MsalServiceException(
                          MsalError.RequestTimeout,
                          "Request to the endpoint timed out.",
                          timeoutException);
            }

            if (doNotThrow)
            {
                return(response);
            }

            if (is5xxError)
            {
                throw MsalServiceExceptionFactory.FromHttpResponse(
                          MsalError.ServiceNotAvailable,
                          "Service is unavailable to process the request",
                          response);
            }

            return(response);
        }