public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { if (_response.IsFinished) { throw new InvalidOperationException("The response is already finished and no new data can be written"); } CancellationTokenSource linkedToken = null; if (cancellationToken != CancellationToken.None) { linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _requestCancellationToken); cancellationToken = linkedToken.Token; } using (linkedToken) { cancellationToken.ThrowIfCancellationRequested(); if (!_response.HasStarted) { if (!_response.IsCompleted && !_isCompressionEnabled && !_isFinalPackage) { if (_request.GetTypedHeaders().AcceptEncoding ?.Contains(new StringWithQualityHeaderValue("gzip")) == true) { _isCompressionEnabled = true; _response.Headers.Add("Content-Encoding", "gzip"); //if the response has not been completed, we compress the body var bodyStream = (BufferingWriteStream)_response.Body; var newPackagingStream = new BufferingWriteStream(this, _packageBufferSize); var gzipStream = new GZipStream(newPackagingStream, CompressionLevel.Fastest, false); bodyStream.SetInnerStream(gzipStream); bodyStream.FlushCallback = () => newPackagingStream.FlushAsync(); await gzipStream.WriteAsync(buffer, offset, count, cancellationToken); return; } } _response.StartResponse(); if (!_response.Headers.ContainsKey(MazeHeaders.MazeSocketRequestIdHeader)) //automatically set { throw new InvalidOperationException( $"Response must have the header {MazeHeaders.MazeSocketRequestIdHeader}"); } var sendBuffer = ArrayPool <byte> .Shared.Rent(count + _maxHeaderSize); var headerOffset = HttpFormatter.FormatResponse(_response, new ArraySegment <byte>(sendBuffer)); if (headerOffset > _maxHeaderSize) { throw new InvalidOperationException( $"The header size {headerOffset}B exceeds the maximum allowed header size ({_maxHeaderSize}B)"); } if (count > 0) { Buffer.BlockCopy(buffer, offset, sendBuffer, headerOffset, count); } Logger.LogDataPackage("Send HTTP Response", sendBuffer, 0, headerOffset + count); await SendData(new ArraySegment <byte>(sendBuffer, 0, headerOffset + count)); } else { var sendBuffer = ArrayPool <byte> .Shared.Rent(count + 4); Buffer.BlockCopy(buffer, offset, sendBuffer, 4, count); BinaryUtils.WriteInt32(ref sendBuffer, 0, _response.RequestId); await SendData(new ArraySegment <byte>(sendBuffer, 0, count + 4)); } } }
public PackagingBufferStreamTests() { _stream = new BufferingWriteStream(new DelegatingWriteStream(SendPackageDelegate), DataSize, ArrayPool <byte> .Shared); }