// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNetCore.Mvc.Internal { /// /// Stream that delegates to an inner stream. /// This Stream is present so that the inner stream is not closed /// even when Close() or Dispose() is called. /// public class NonDisposableStream : Stream { private readonly Stream _innerStream; /// /// Initializes a new . /// /// The stream which should not be closed or flushed. public NonDisposableStream(Stream innerStream) { if (innerStream == null) { throw new ArgumentNullException(nameof(innerStream)); } _innerStream = innerStream; } /// /// The inner stream this object delegates to. /// protected Stream InnerStream => _innerStream; /// public override bool CanRead => _innerStream.CanRead; /// public override bool CanSeek => _innerStream.CanSeek; /// public override bool CanWrite => _innerStream.CanWrite; /// public override long Length => _innerStream.Length; /// public override long Position { get { return _innerStream.Position; } set { _innerStream.Position = value; } } /// public override int ReadTimeout { get { return _innerStream.ReadTimeout; } set { _innerStream.ReadTimeout = value; } } /// public override bool CanTimeout => _innerStream.CanTimeout; /// public override int WriteTimeout { get { return _innerStream.WriteTimeout; } set { _innerStream.WriteTimeout = value; } } /// public override long Seek(long offset, SeekOrigin origin) { return _innerStream.Seek(offset, origin); } /// public override int Read(byte[] buffer, int offset, int count) { return _innerStream.Read(buffer, offset, count); } /// public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { return _innerStream.ReadAsync(buffer, offset, count, cancellationToken); } /// public override IAsyncResult BeginRead( byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return _innerStream.BeginRead(buffer, offset, count, callback, state); } /// public override int EndRead(IAsyncResult asyncResult) { return _innerStream.EndRead(asyncResult); } /// public override IAsyncResult BeginWrite( byte[] buffer, int offset, int count, AsyncCallback callback, object state) { return _innerStream.BeginWrite(buffer, offset, count, callback, state); } /// public override void EndWrite(IAsyncResult asyncResult) { _innerStream.EndWrite(asyncResult); } /// public override void Close() { } /// public override int ReadByte() { return _innerStream.ReadByte(); } /// public override void Flush() { // Do nothing, we want to explicitly avoid flush because it turns on Chunked encoding. } /// public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) { return _innerStream.CopyToAsync(destination, bufferSize, cancellationToken); } /// public override Task FlushAsync(CancellationToken cancellationToken) { return _innerStream.FlushAsync(cancellationToken); } /// public override void SetLength(long value) { _innerStream.SetLength(value); } /// public override void Write(byte[] buffer, int offset, int count) { _innerStream.Write(buffer, offset, count); } /// public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { return _innerStream.WriteAsync(buffer, offset, count, cancellationToken); } /// public override void WriteByte(byte value) { _innerStream.WriteByte(value); } /// protected override void Dispose(bool disposing) { // No-op. In CoreCLR this is equivalent to Close. // Given that we don't own the underlying stream, we never want to do anything interesting here. } } }