Skip to content

Commit e659b55

Browse files
committed
ResponseCaching: started conversion to pipes
1 parent f854b56 commit e659b55

File tree

9 files changed

+66
-534
lines changed

9 files changed

+66
-534
lines changed

src/Middleware/ResponseCaching/src/CacheEntry/CachedResponse.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.IO;
65
using Microsoft.AspNetCore.Http;
76

87
namespace Microsoft.AspNetCore.ResponseCaching
@@ -15,6 +14,6 @@ internal class CachedResponse : IResponseCacheEntry
1514

1615
public IHeaderDictionary Headers { get; set; }
1716

18-
public Stream Body { get; set; }
17+
public CachedResponseBody Body { get; set; }
1918
}
2019
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO.Pipelines;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
10+
namespace Microsoft.AspNetCore.ResponseCaching
11+
{
12+
internal class CachedResponseBody
13+
{
14+
public CachedResponseBody(List<byte[]> segments, long length)
15+
{
16+
Segments = segments;
17+
Length = length;
18+
}
19+
20+
public List<byte[]> Segments { get; }
21+
22+
public long Length { get; }
23+
24+
public async Task CopyToAsync(PipeWriter destination, CancellationToken cancellationToken)
25+
{
26+
if (destination == null)
27+
{
28+
throw new ArgumentNullException(nameof(destination));
29+
}
30+
31+
for (var segmentIndex = 0; segmentIndex < Segments.Count; segmentIndex++)
32+
{
33+
cancellationToken.ThrowIfCancellationRequested();
34+
var segmentLength = Segments[segmentIndex].Length;
35+
36+
var memory = destination.GetMemory(segmentLength);
37+
Segments[segmentIndex].AsMemory().CopyTo(memory);
38+
39+
destination.Advance(segmentLength);
40+
41+
await destination.FlushAsync();
42+
}
43+
44+
await destination.CompleteAsync();
45+
}
46+
}
47+
}

src/Middleware/ResponseCaching/src/MemoryCachedResponse.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -15,8 +15,6 @@ internal class MemoryCachedResponse
1515

1616
public IHeaderDictionary Headers { get; set; } = new HeaderDictionary();
1717

18-
public List<byte[]> BodySegments { get; set; }
19-
20-
public long BodyLength { get; set; }
18+
public CachedResponseBody Body { get; set; }
2119
}
2220
}

src/Middleware/ResponseCaching/src/MemoryResponseCache.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Buffers;
56
using System.Threading.Tasks;
67
using Microsoft.Extensions.Caching.Memory;
78

@@ -27,7 +28,7 @@ public IResponseCacheEntry Get(string key)
2728
Created = memoryCachedResponse.Created,
2829
StatusCode = memoryCachedResponse.StatusCode,
2930
Headers = memoryCachedResponse.Headers,
30-
Body = new SegmentReadStream(memoryCachedResponse.BodySegments, memoryCachedResponse.BodyLength)
31+
Body = memoryCachedResponse.Body
3132
};
3233
}
3334
else
@@ -40,18 +41,14 @@ public void Set(string key, IResponseCacheEntry entry, TimeSpan validFor)
4041
{
4142
if (entry is CachedResponse cachedResponse)
4243
{
43-
var segmentStream = new SegmentWriteStream(StreamUtilities.BodySegmentSize);
44-
cachedResponse.Body.CopyTo(segmentStream);
45-
4644
_cache.Set(
4745
key,
4846
new MemoryCachedResponse
4947
{
5048
Created = cachedResponse.Created,
5149
StatusCode = cachedResponse.StatusCode,
5250
Headers = cachedResponse.Headers,
53-
BodySegments = segmentStream.GetSegments(),
54-
BodyLength = segmentStream.Length
51+
Body = cachedResponse.Body
5552
},
5653
new MemoryCacheEntryOptions
5754
{

src/Middleware/ResponseCaching/src/ResponseCachingMiddleware.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,13 @@ internal async Task<bool> TryServeCachedResponseAsync(ResponseCachingContext con
193193
{
194194
try
195195
{
196-
await body.CopyToAsync(response.Body, StreamUtilities.BodySegmentSize, context.HttpContext.RequestAborted);
196+
await body.CopyToAsync(response.BodyWriter, context.HttpContext.RequestAborted);
197197
}
198-
catch (OperationCanceledException)
198+
catch (OperationCanceledException)
199199
{
200200
context.HttpContext.Abort();
201201
}
202-
}
202+
}
203203
_logger.CachedResponseServed();
204204
}
205205
return true;
@@ -344,17 +344,17 @@ internal void FinalizeCacheBody(ResponseCachingContext context)
344344
if (context.ShouldCacheResponse && context.ResponseCachingStream.BufferingEnabled)
345345
{
346346
var contentLength = context.HttpContext.Response.ContentLength;
347-
var bufferStream = context.ResponseCachingStream.GetBufferStream();
348-
if (!contentLength.HasValue || contentLength == bufferStream.Length)
347+
var cachedResponseBody = context.ResponseCachingStream.GetCachedResponseBody();
348+
if (!contentLength.HasValue || contentLength == cachedResponseBody.Length)
349349
{
350350
var response = context.HttpContext.Response;
351351
// Add a content-length if required
352352
if (!response.ContentLength.HasValue && StringValues.IsNullOrEmpty(response.Headers[HeaderNames.TransferEncoding]))
353353
{
354-
context.CachedResponse.Headers[HeaderNames.ContentLength] = HeaderUtilities.FormatNonNegativeInt64(bufferStream.Length);
354+
context.CachedResponse.Headers[HeaderNames.ContentLength] = HeaderUtilities.FormatNonNegativeInt64(cachedResponseBody.Length);
355355
}
356356

357-
context.CachedResponse.Body = bufferStream;
357+
context.CachedResponse.Body = cachedResponseBody;
358358
_logger.ResponseCached();
359359
_cache.Set(context.StorageVaryKey ?? context.BaseKey, context.CachedResponse, context.CachedResponseValidFor);
360360
}

src/Middleware/ResponseCaching/src/Streams/ResponseCachingStream.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ public override long Position
4545
}
4646
}
4747

48-
internal Stream GetBufferStream()
48+
internal CachedResponseBody GetCachedResponseBody()
4949
{
5050
if (!BufferingEnabled)
5151
{
5252
throw new InvalidOperationException("Buffer stream cannot be retrieved since buffering is disabled.");
5353
}
54-
return new SegmentReadStream(_segmentWriteStream.GetSegments(), _segmentWriteStream.Length);
54+
return new CachedResponseBody(_segmentWriteStream.GetSegments(), _segmentWriteStream.Length);
5555
}
5656

5757
internal void DisableBuffering()

src/Middleware/ResponseCaching/src/Streams/SegmentReadStream.cs

Lines changed: 0 additions & 225 deletions
This file was deleted.

0 commit comments

Comments
 (0)