| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | using Google.Apis.Core.Util; |
| | using System; |
| | using System.IO; |
| | using System.Net.Http; |
| | using System.Threading; |
| | using System.Threading.Tasks; |
| |
|
| | namespace Google.Apis.Http |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | internal sealed class StreamInterceptionHandler : DelegatingHandler |
| | { |
| | internal StreamInterceptionHandler(HttpMessageHandler handler) : base(handler) |
| | { |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) |
| | { |
| | var responseTask = base.SendAsync(request, cancellationToken); |
| | var provider = GetInterceptorProvider(request); |
| | return provider == null ? responseTask : ReplaceAsync(responseTask, provider); |
| | } |
| |
|
| | private async Task<HttpResponseMessage> ReplaceAsync(Task<HttpResponseMessage> responseTask, Func<HttpResponseMessage, StreamInterceptor> interceptorProvider) |
| | { |
| | var response = await responseTask.ConfigureAwait(false); |
| | var interceptor = interceptorProvider(response); |
| | if (interceptor != null) |
| | { |
| | response.Content = new StreamReplacingHttpContent(response.Content, stream => new InterceptingStream(stream, interceptor)); |
| | } |
| | return response; |
| | } |
| |
|
| | internal static Func<HttpResponseMessage, StreamInterceptor> GetInterceptorProvider(HttpRequestMessage request) |
| | { |
| | |
| | Func<HttpResponseMessage, StreamInterceptor> interceptorProvider = null; |
| | request.TryGetOption(ConfigurableMessageHandler.ResponseStreamInterceptorProviderKey, out interceptorProvider); |
| | return interceptorProvider; |
| | } |
| |
|
| | private sealed class InterceptingStream : Stream |
| | { |
| | private readonly Stream _original; |
| | private readonly StreamInterceptor _interceptor; |
| |
|
| | |
| | public override bool CanRead => true; |
| | public override bool CanSeek => false; |
| | public override bool CanWrite => false; |
| |
|
| | |
| | |
| | public override long Length => _original.Length; |
| | public override long Position { get => _original.Position; set => throw new NotSupportedException(); } |
| |
|
| | internal InterceptingStream(Stream original, StreamInterceptor interceptor) |
| | { |
| | _original = original; |
| | _interceptor = interceptor; |
| | } |
| |
|
| | |
| | public override int Read(byte[] buffer, int offset, int count) |
| | { |
| | |
| | int ret = _original.Read(buffer, offset, count); |
| | _interceptor(buffer, offset, ret); |
| | return ret; |
| | } |
| |
|
| | public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) |
| | { |
| | |
| | var ret = await _original.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); |
| | _interceptor(buffer, offset, ret); |
| | return ret; |
| | } |
| |
|
| | |
| | protected override void Dispose(bool disposing) => _original.Dispose(); |
| |
|
| | |
| | public override void Flush() => _original.Flush(); |
| |
|
| | |
| | public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); |
| | public override void SetLength(long value) => throw new NotSupportedException(); |
| | public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); |
| | } |
| | } |
| | } |
| |
|