Пример #1
0
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var ctx = new HandlingContext
            {
                Request           = request,
                HandleAsync       = base.SendAsync,
                ResponsSource     = new TaskCompletionSource <HttpResponseMessage>(cancellationToken),
                CancellationToken = cancellationToken
            };

            try
            {
                await _dispather.AcceptThenDispatchAsync(ctx);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                ctx.ResponsSource.SetException(ex);
            }
            return(await ctx.ResponsSource.Task);
        }
Пример #2
0
        /// <returns>是否尝试了“下一个”上游服务端</returns>
        private async Task <bool> NextPeerAsync(
            HandlingContext handlingContext,
            UpstreamPeer peer,
            HttpResponseMessage response,
            Uri originUri,
            bool isTimeout = false)
        {
            if (peer == null)
            {
                return(false);
            }
            if (handlingContext.IsSingle)
            {
                return(false);
            }

            handlingContext.Start = handlingContext.Start ?? DateTime.Now;

            if (NextWhen.Never == (peer.NextWhen & NextWhen.Never))
            {
                return(false);
            }

            var request = handlingContext.Request;

            if (request.Method != HttpMethod.Get &&
                NextWhen.GetOnly == (peer.NextWhen & NextWhen.GetOnly))
            {
                return(false);
            }

            handlingContext.Tries = handlingContext.Tries ?? (peer.NextTries == 0 ? int.MaxValue : peer.NextTries);
            if (handlingContext.Tries == 0)
            {
                return(false);
            }

            var when = NextWhen.None;

            if (isTimeout)
            {
                when |= NextWhen.Timeout;
            }
            else if (response == null)
            {
                when |= NextWhen.Error;
            }
            else
            {
                if (response.IsSuccessStatusCode)
                {
                    return(false);
                }
                switch (response.StatusCode)
                {
                case HttpStatusCode.InternalServerError:
                    when |= NextWhen.Http500;
                    break;

                case HttpStatusCode.BadGateway:
                    when |= NextWhen.Http502;
                    break;

                case HttpStatusCode.ServiceUnavailable:
                    when |= NextWhen.Http503;
                    break;

                case HttpStatusCode.RequestTimeout:
                case HttpStatusCode.GatewayTimeout:
                    when |= NextWhen.Timeout;
                    break;

                case HttpStatusCode.Forbidden:
                    when |= NextWhen.Http403;
                    break;

                case HttpStatusCode.NotFound:
                    when |= NextWhen.Http404;
                    break;

                default:
                    return(false);
                }
            }

#if NETSTANDARD2_0
            if (request.Method == HttpMethod.Post || request.Method.Method == "PATCH")
#elif NETSTANDARD2_1
            if (request.Method == HttpMethod.Post || request.Method == HttpMethod.Patch)
#endif
            {
                when |= NextWhen.NonIdemponent;
            }

            if (when != (when & peer.NextWhen))
            {
                return(false);
            }

            if (DateTime.Now - handlingContext.Start >= peer.NextTimeout)
            {
                return(false);
            }

            handlingContext.Request = request.Clone(originUri);
            //保持上下文重试
            var next = await _dispatcher.AcceptThenDispatchAsync(handlingContext);

            handlingContext.Tries--;
            return(next);
        }