コード例 #1
0
 public override void Process(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
 {
     ProcessAsync(message, pipeline, false).EnsureCompleted();
 }
コード例 #2
0
 public override async Task ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
 {
     await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
     await BufferResponse(message, true).ConfigureAwait(false);
 }
コード例 #3
0
 protected static async Task ProcessNextAsync(ReadOnlyMemory <HttpPipelinePolicy> pipeline, HttpPipelineMessage message)
 {
     if (pipeline.IsEmpty)
     {
         throw new InvalidOperationException("last policy in the pipeline must be a transport");
     }
     var next = pipeline.Span[0];
     await next.ProcessAsync(message, pipeline.Slice(1)).ConfigureAwait(false);
 }
コード例 #4
0
        public override Task ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
        {
            Debug.Assert(pipeline.IsEmpty);

            return(_transport.ProcessAsync(message));
        }
コード例 #5
0
 public override async ValueTask ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
 {
     await ProcessAsync(message, pipeline, true).ConfigureAwait(false);
 }
コード例 #6
0
 /// <summary>
 /// Applies the policy to the <see cref="message"/>. Implementers are expected to mutate <see cref="HttpPipelineMessage.Request"/> before calling <see cref="ProcessNextAsync"/> and observe the <see cref="HttpPipelineMessage.Response"/> changes after.
 /// Last policy in the pipeline is expected to set the <see cref="HttpPipelineMessage.Response"/>
 /// </summary>
 /// <param name="message">The <see cref="HttpPipelineMessage"/> this policy would be applied to.</param>
 /// <param name="pipeline">The set of <see cref="HttpPipelinePolicy"/> to execute after current one.</param>
 /// <returns></returns>
 public abstract Task ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline);
コード例 #7
0
 public abstract void Process(HttpPipelineMessage message);
コード例 #8
0
        private static async Task ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async)
        {
            if (!s_eventSource.IsEnabled())
            {
                if (async)
                {
                    await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
                }
                else
                {
                    ProcessNext(message, pipeline);
                }
                return;
            }

            s_eventSource.Request(message.Request);

            Encoding?requestTextEncoding = null;

            bool textRequest = message.Request.TryGetHeader(HttpHeader.Names.ContentType, out var contentType) &&
                               ContentTypeUtilities.TryGetTextEncoding(contentType, out requestTextEncoding);

            if (message.Request.Content != null)
            {
                if (textRequest)
                {
                    if (async)
                    {
                        await s_eventSource.RequestContentTextAsync(message.Request, requestTextEncoding !, message.CancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        s_eventSource.RequestContentText(message.Request, requestTextEncoding !, message.CancellationToken);
                    }
                }
                else
                {
                    if (async)
                    {
                        await s_eventSource.RequestContentAsync(message.Request, message.CancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        s_eventSource.RequestContent(message.Request, message.CancellationToken);
                    }
                }
            }

            var before = Stopwatch.GetTimestamp();

            if (async)
            {
                await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
            }
            else
            {
                ProcessNext(message, pipeline);
            }



            var after = Stopwatch.GetTimestamp();

            bool isError = message.ResponseClassifier.IsErrorResponse(message);

            var textResponse = ContentTypeUtilities.TryGetTextEncoding(message.Response.Headers.ContentType, out Encoding? responseTextEncoding);

            bool wrapResponseStream = message.Response.ContentStream != null && message.Response.ContentStream?.CanSeek == false && s_eventSource.ShouldLogContent(isError);

            if (wrapResponseStream)
            {
                message.Response.ContentStream = new LoggingStream(
                    message.Response.ClientRequestId, s_eventSource, message.Response.ContentStream !, isError, responseTextEncoding);
            }

            if (isError)
            {
                s_eventSource.ErrorResponse(message.Response);

                if (!wrapResponseStream && message.Response.ContentStream != null)
                {
                    if (textResponse)
                    {
                        if (async)
                        {
                            await s_eventSource.ErrorResponseContentTextAsync(message.Response, responseTextEncoding !, message.CancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            s_eventSource.ErrorResponseContentText(message.Response, responseTextEncoding !);
                        }
                    }
                    else
                    {
                        if (async)
                        {
                            await s_eventSource.ErrorResponseContentAsync(message.Response, message.CancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            s_eventSource.ErrorResponseContent(message.Response);
                        }
                    }
                }
            }

            s_eventSource.Response(message.Response);

            if (!wrapResponseStream && message.Response.ContentStream != null)
            {
                if (textResponse)
                {
                    if (async)
                    {
                        await s_eventSource.ResponseContentTextAsync(message.Response, responseTextEncoding !, message.CancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        s_eventSource.ResponseContentText(message.Response, responseTextEncoding !);
                    }
                }
                else
                {
                    if (async)
                    {
                        await s_eventSource.ResponseContentAsync(message.Response, message.CancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        s_eventSource.ResponseContent(message.Response);
                    }
                }
            }

            var elapsedMilliseconds = (after - before) * 1000 / s_frequency;

            if (elapsedMilliseconds > DelayWarningThreshold)
            {
                s_eventSource.ResponseDelay(message.Response, elapsedMilliseconds);
            }
        }
コード例 #9
0
        public override void Process(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
        {
            Debug.Assert(pipeline.IsEmpty);

            _transport.Process(message);
        }
コード例 #10
0
 internal HttpMessageOptions(HttpPipelineMessage message)
 => _message = message;
コード例 #11
0
        /// <summary>
        /// Specifies if the response is not successful but can be retried.
        /// </summary>
        public virtual bool IsErrorResponse(HttpPipelineMessage message)
        {
            var statusKind = message.Response.Status / 100;

            return(statusKind == 4 || statusKind == 5);
        }
コード例 #12
0
 /// <summary>
 /// Specifies if the response should terminate the pipeline and not be retried.
 /// </summary>
 public virtual bool IsRetriableResponse(HttpPipelineMessage message)
 {
     return(message.Response.Status == 429 || message.Response.Status == 503);
 }
コード例 #13
0
 public override void Process(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
 {
     ProcessNext(message, pipeline);
     BufferResponse(message, false).EnsureCompleted();
 }
コード例 #14
0
 /// <summary>
 /// Invokes the next <see cref="HttpPipelinePolicy"/> in the <see cref="pipeline"/>.
 /// </summary>
 /// <param name="message">The <see cref="HttpPipelineMessage"/> next policy would be applied to.</param>
 /// <param name="pipeline">The set of <see cref="HttpPipelinePolicy"/> to execute after next one.</param>
 /// <returns></returns>
 protected static Task ProcessNextAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
 {
     return(pipeline.Span[0].ProcessAsync(message, pipeline.Slice(1)));
 }
コード例 #15
0
 public abstract ValueTask ProcessAsync(HttpPipelineMessage message);
コード例 #16
0
 protected static void ProcessNext(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
 {
     pipeline.Span[0].Process(message, pipeline.Slice(1));
 }
コード例 #17
0
 public override void Process(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
 {
     OnSendingRequest(message);
     ProcessNext(message, pipeline);
     OnReceivedResponse(message);
 }
コード例 #18
0
        private async Task ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async)
        {
            int attempt = 0;
            List <Exception> exceptions = null;

            while (true)
            {
                Exception lastException = null;

                try
                {
                    if (async)
                    {
                        await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
                    }
                    else
                    {
                        ProcessNext(message, pipeline);
                    }
                }
                catch (Exception ex)
                {
                    if (exceptions == null)
                    {
                        exceptions = new List <Exception>();
                    }

                    exceptions.Add(ex);

                    lastException = ex;
                }

                TimeSpan delay;

                attempt++;

                var shouldRetry = attempt <= _maxRetries;

                if (lastException != null)
                {
                    if (shouldRetry && message.ResponseClassifier.IsRetriableException(lastException))
                    {
                        GetDelay(attempt, out delay);
                    }
                    else
                    {
                        // Rethrow a singular exception
                        if (exceptions.Count == 1)
                        {
                            ExceptionDispatchInfo.Capture(lastException).Throw();
                        }

                        throw new AggregateException($"Retry failed after {attempt} tries.", exceptions);
                    }
                }
                else if (message.ResponseClassifier.IsErrorResponse(message.Response))
                {
                    if (shouldRetry && message.ResponseClassifier.IsRetriableResponse(message.Response))
                    {
                        GetDelay(message, attempt, out delay);
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }

                if (delay > TimeSpan.Zero)
                {
                    if (async)
                    {
                        await WaitAsync(delay, message.CancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        Wait(delay, message.CancellationToken);
                    }
                }

                HttpPipelineEventSource.Singleton.RequestRetrying(message.Request, attempt);
            }
        }
コード例 #19
0
 public virtual void OnSendingRequest(HttpPipelineMessage message)
 {
 }
コード例 #20
0
        private async ValueTask ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async)
        {
            if (!s_eventSource.IsEnabled())
            {
                if (async)
                {
                    await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
                }
                else
                {
                    ProcessNext(message, pipeline);
                }
                return;
            }

            s_eventSource.Request(message.Request);

            Encoding?requestTextEncoding = null;

            if (message.Request.TryGetHeader(HttpHeader.Names.ContentType, out var contentType))
            {
                ContentTypeUtilities.TryGetTextEncoding(contentType, out requestTextEncoding);
            }

            var logWrapper = new ContentEventSourceWrapper(s_eventSource, _logContent, _maxLength, message.CancellationToken);

            await logWrapper.LogAsync(message.Request.ClientRequestId, message.Request.Content, requestTextEncoding, async).ConfigureAwait(false).EnsureCompleted(async);

            var before = Stopwatch.GetTimestamp();

            if (async)
            {
                await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
            }
            else
            {
                ProcessNext(message, pipeline);
            }

            var after = Stopwatch.GetTimestamp();

            bool isError = message.ResponseClassifier.IsErrorResponse(message);

            ContentTypeUtilities.TryGetTextEncoding(message.Response.Headers.ContentType, out Encoding? responseTextEncoding);

            bool wrapResponseContent = message.Response.ContentStream != null &&
                                       message.Response.ContentStream.CanSeek == false &&
                                       logWrapper.IsEnabled(isError);

            if (isError)
            {
                s_eventSource.ErrorResponse(message.Response);
            }
            else
            {
                s_eventSource.Response(message.Response);
            }

            if (wrapResponseContent)
            {
                message.Response.ContentStream = new LoggingStream(message.Response.ClientRequestId, logWrapper, _maxLength, message.Response.ContentStream !, isError, responseTextEncoding);
            }
            else
            {
                await logWrapper.LogAsync(message.Response.ClientRequestId, isError, message.Response.ContentStream, responseTextEncoding, async).ConfigureAwait(false).EnsureCompleted(async);
            }

            var elapsedMilliseconds = (after - before) * 1000 / Stopwatch.Frequency;

            if (elapsedMilliseconds > DelayWarningThreshold)
            {
                s_eventSource.ResponseDelay(message.Response, elapsedMilliseconds);
            }
        }
コード例 #21
0
 public virtual void OnReceivedResponse(HttpPipelineMessage message)
 {
 }
コード例 #22
0
 public abstract void Process(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline);
コード例 #23
0
 public override void Process(HttpPipelineMessage message)
 {
     // Intentionally blocking here
     ProcessAsync(message).GetAwaiter().GetResult();
 }
コード例 #24
0
 protected static void ProcessNext(ReadOnlyMemory <HttpPipelinePolicy> pipeline, HttpPipelineMessage message)
 {
     if (pipeline.IsEmpty)
     {
         throw new InvalidOperationException("last policy in the pipeline must be a transport");
     }
     pipeline.Span[0].Process(message, pipeline.Slice(1));
 }
コード例 #25
0
 public ValueTask SendAsync(HttpPipelineMessage message, CancellationToken cancellationToken)
 {
     message.CancellationToken = cancellationToken;
     return(_pipeline.Span[0].ProcessAsync(message, _pipeline.Slice(1)));
 }
コード例 #26
0
 public override ValueTask ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline)
 {
     return(ProcessAsync(message, pipeline, true));
 }
コード例 #27
0
 public void Send(HttpPipelineMessage message, CancellationToken cancellationToken)
 {
     message.CancellationToken = cancellationToken;
     _pipeline.Span[0].Process(message, _pipeline.Slice(1));
 }
コード例 #28
0
 public override void OnSendingRequest(HttpPipelineMessage message)
 {
     message.Request.Headers.Add(HttpHeader.Names.UserAgent, _header);
 }
コード例 #29
0
        private async ValueTask ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool isAsync)
        {
            if (!_isDistributedTracingEnabled)
            {
                if (isAsync)
                {
                    await ProcessNextAsync(message, pipeline, true).ConfigureAwait(false);
                }
                else
                {
                    ProcessNextAsync(message, pipeline, false).EnsureCompleted();
                }

                return;
            }

            if (!s_diagnosticSource.IsEnabled())
            {
                await ProcessNextAsync(message, pipeline, isAsync).ConfigureAwait(false);

                return;
            }

            var activity = new Activity("Azure.Core.Http.Request");

            activity.AddTag("http.method", message.Request.Method.Method);
            activity.AddTag("http.url", message.Request.Uri.ToString());
            activity.AddTag("requestId", message.Request.ClientRequestId);

            if (message.Request.Headers.TryGetValue("User-Agent", out string?userAgent))
            {
                activity.AddTag("http.user_agent", userAgent);
            }

            var diagnosticSourceActivityEnabled = s_diagnosticSource.IsEnabled(activity.OperationName, message);

            if (diagnosticSourceActivityEnabled)
            {
                s_diagnosticSource.StartActivity(activity, message);
            }
            else
            {
                activity.Start();
            }


            if (isAsync)
            {
                await ProcessNextAsync(message, pipeline, true).ConfigureAwait(false);
            }
            else
            {
                ProcessNextAsync(message, pipeline, false).EnsureCompleted();
            }

            activity.AddTag("http.status_code", message.Response.Status.ToString(CultureInfo.InvariantCulture));
            activity.AddTag("serviceRequestId", message.Response.Headers.RequestId);

            if (diagnosticSourceActivityEnabled)
            {
                s_diagnosticSource.StopActivity(activity, message);
            }
            else
            {
                activity.Stop();
            }
        }