public async Task It_Reads_Asynchronously() { // ARRANGE var buffer = Encoding.ASCII.GetBytes("foobarbaz"); var innerStream = new MemoryStream(Encoding.ASCII.GetBytes("FOOBAR")); var stream = new PartiallyBufferedStream(buffer, 3, 3, innerStream); // ACT var content = await new StreamReader(stream, Encoding.ASCII).ReadToEndAsync(); // ASSERT content.Should().Be("barFOOBAR"); }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // add content encodings to the request var acceptEncoding = ContentEncodings .Where(p => AutomaticDecompression.HasFlag(p.Key)) .Where(p => request.Headers.AcceptEncoding.All(c => c.Value.Equals(p.Value, StringComparison.OrdinalIgnoreCase))) .OrderBy(p => p.Key) .Select(p => p.Value); foreach (var encoding in acceptEncoding) { request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue(encoding)); } // get the response var response = await base.SendAsync(request, cancellationToken); // immediately return when the response body is empty or not compressed if (response.Content == null || !response.Content.Headers.ContentEncoding.Any()) { return response; } // read the header var responseStream = await response.Content.ReadAsStreamAsync(); var header = new byte[2]; var headerLength = await responseStream.ReadAsync(header, 0, 2, cancellationToken); if (headerLength == 1) { headerLength += await responseStream.ReadAsync(header, 1, 2, cancellationToken); } if (headerLength < 2) { return response; } // include the header in the stream that gets decompressed var encodedStream = new PartiallyBufferedStream(header, 0, 2, responseStream); // try to decode the response Stream decodeStream = null; var contentEncoding = response.Content.Headers.ContentEncoding.First(); if (AutomaticDecompression.HasFlag(DecompressionMethods.GZip) && contentEncoding.Equals(ContentEncodings[DecompressionMethods.GZip], StringComparison.OrdinalIgnoreCase)) { // let gzip compress the stream, and exclude the Content-Encoding header decodeStream = new GZipStream(encodedStream, CompressionMode.Decompress); } else if (AutomaticDecompression.HasFlag(DecompressionMethods.Deflate) && contentEncoding.Equals(ContentEncodings[DecompressionMethods.Deflate], StringComparison.OrdinalIgnoreCase)) { // decompress the stream as raw DEFLATE or zlib, depending on the header var noHeader = header[0] != ValidZlibCmfByte || !ValidZlibFlgBytes.Contains(header[1]); decodeStream = noHeader ? new DeflateStream(encodedStream, CompressionMode.Decompress) : new DeflateStream(responseStream, CompressionMode.Decompress); } if (decodeStream != null) { var decompressedContent = new StreamContent(decodeStream); foreach (var pair in response.Content.Headers) { if (pair.Key.Equals("Content-Encoding", StringComparison.OrdinalIgnoreCase)) { continue; } decompressedContent.Headers.TryAddWithoutValidation(pair.Key, pair.Value); } response.Content = decompressedContent; } return response; }