10
10
using Microsoft . AspNetCore . Http . Headers ;
11
11
using Microsoft . AspNetCore . ResponseCaching . Internal ;
12
12
using Microsoft . Extensions . Internal ;
13
- using Microsoft . Extensions . ObjectPool ;
13
+ using Microsoft . Extensions . Logging ;
14
14
using Microsoft . Extensions . Options ;
15
15
using Microsoft . Extensions . Primitives ;
16
16
using Microsoft . Net . Http . Headers ;
@@ -22,15 +22,17 @@ public class ResponseCacheMiddleware
22
22
private static readonly TimeSpan DefaultExpirationTimeSpan = TimeSpan . FromSeconds ( 10 ) ;
23
23
24
24
private readonly RequestDelegate _next ;
25
- private readonly IResponseCacheStore _store ;
26
25
private readonly ResponseCacheOptions _options ;
26
+ private readonly ILogger _logger ;
27
27
private readonly IResponseCachePolicyProvider _policyProvider ;
28
+ private readonly IResponseCacheStore _store ;
28
29
private readonly IResponseCacheKeyProvider _keyProvider ;
29
30
private readonly Func < object , Task > _onStartingCallback ;
30
31
31
32
public ResponseCacheMiddleware (
32
33
RequestDelegate next ,
33
34
IOptions < ResponseCacheOptions > options ,
35
+ ILoggerFactory loggerFactory ,
34
36
IResponseCachePolicyProvider policyProvider ,
35
37
IResponseCacheStore store ,
36
38
IResponseCacheKeyProvider keyProvider )
@@ -39,34 +41,39 @@ public ResponseCacheMiddleware(
39
41
{
40
42
throw new ArgumentNullException ( nameof ( next ) ) ;
41
43
}
42
- if ( store == null )
43
- {
44
- throw new ArgumentNullException ( nameof ( store ) ) ;
45
- }
46
44
if ( options == null )
47
45
{
48
46
throw new ArgumentNullException ( nameof ( options ) ) ;
49
47
}
48
+ if ( loggerFactory == null )
49
+ {
50
+ throw new ArgumentNullException ( nameof ( loggerFactory ) ) ;
51
+ }
50
52
if ( policyProvider == null )
51
53
{
52
54
throw new ArgumentNullException ( nameof ( policyProvider ) ) ;
53
55
}
56
+ if ( store == null )
57
+ {
58
+ throw new ArgumentNullException ( nameof ( store ) ) ;
59
+ }
54
60
if ( keyProvider == null )
55
61
{
56
62
throw new ArgumentNullException ( nameof ( keyProvider ) ) ;
57
63
}
58
64
59
65
_next = next ;
60
- _store = store ;
61
66
_options = options . Value ;
67
+ _logger = loggerFactory . CreateLogger < ResponseCacheMiddleware > ( ) ;
62
68
_policyProvider = policyProvider ;
69
+ _store = store ;
63
70
_keyProvider = keyProvider ;
64
71
_onStartingCallback = state => OnResponseStartingAsync ( ( ResponseCacheContext ) state ) ;
65
72
}
66
73
67
74
public async Task Invoke ( HttpContext httpContext )
68
75
{
69
- var context = new ResponseCacheContext ( httpContext ) ;
76
+ var context = new ResponseCacheContext ( httpContext , _logger ) ;
70
77
71
78
// Should we attempt any caching logic?
72
79
if ( _policyProvider . IsRequestCacheable ( context ) )
@@ -115,8 +122,9 @@ internal async Task<bool> TryServeCachedResponseAsync(ResponseCacheContext conte
115
122
if ( _policyProvider . IsCachedEntryFresh ( context ) )
116
123
{
117
124
// Check conditional request rules
118
- if ( ConditionalRequestSatisfied ( context ) )
125
+ if ( ContentIsNotModified ( context ) )
119
126
{
127
+ _logger . LogNotModifiedServed ( ) ;
120
128
context . HttpContext . Response . StatusCode = StatusCodes . Status304NotModified ;
121
129
}
122
130
else
@@ -150,8 +158,8 @@ internal async Task<bool> TryServeCachedResponseAsync(ResponseCacheContext conte
150
158
context . HttpContext . Abort ( ) ;
151
159
}
152
160
}
161
+ _logger . LogCachedResponseServed ( ) ;
153
162
}
154
-
155
163
return true ;
156
164
}
157
165
@@ -183,13 +191,14 @@ internal async Task<bool> TryServeFromCacheAsync(ResponseCacheContext context)
183
191
return true ;
184
192
}
185
193
186
-
187
194
if ( context . RequestCacheControlHeaderValue . OnlyIfCached )
188
195
{
196
+ _logger . LogGatewayTimeoutServed ( ) ;
189
197
context . HttpContext . Response . StatusCode = StatusCodes . Status504GatewayTimeout ;
190
198
return true ;
191
199
}
192
200
201
+ _logger . LogNoResponseServed ( ) ;
193
202
return false ;
194
203
}
195
204
@@ -229,6 +238,7 @@ internal async Task FinalizeCacheHeadersAsync(ResponseCacheContext context)
229
238
}
230
239
231
240
// Always overwrite the CachedVaryByRules to update the expiry information
241
+ _logger . LogVaryByRulesUpdated ( normalizedVaryHeaders , normalizedVaryQueryKeys ) ;
232
242
await _store . SetAsync ( context . BaseKey , context . CachedVaryByRules , context . CachedResponseValidFor ) ;
233
243
234
244
context . StorageVaryKey = _keyProvider . CreateStorageVaryByKey ( context ) ;
@@ -272,8 +282,17 @@ internal async Task FinalizeCacheBodyAsync(ResponseCacheContext context)
272
282
if ( ! contentLength . HasValue || contentLength == bufferStream . Length )
273
283
{
274
284
context . CachedResponse . Body = bufferStream ;
285
+ _logger . LogResponseCached ( ) ;
275
286
await _store . SetAsync ( context . StorageVaryKey ?? context . BaseKey , context . CachedResponse , context . CachedResponseValidFor ) ;
276
287
}
288
+ else
289
+ {
290
+ _logger . LogResponseContentLengthMismatchNotCached ( ) ;
291
+ }
292
+ }
293
+ else
294
+ {
295
+ _logger . LogResponseNotCached ( ) ;
277
296
}
278
297
}
279
298
@@ -320,7 +339,7 @@ internal static void UnshimResponseStream(ResponseCacheContext context)
320
339
context . HttpContext . RemoveResponseCacheFeature ( ) ;
321
340
}
322
341
323
- internal static bool ConditionalRequestSatisfied ( ResponseCacheContext context )
342
+ internal static bool ContentIsNotModified ( ResponseCacheContext context )
324
343
{
325
344
var cachedResponseHeaders = context . CachedResponseHeaders ;
326
345
var ifNoneMatchHeader = context . TypedRequestHeaders . IfNoneMatch ;
@@ -329,6 +348,7 @@ internal static bool ConditionalRequestSatisfied(ResponseCacheContext context)
329
348
{
330
349
if ( ifNoneMatchHeader . Count == 1 && ifNoneMatchHeader [ 0 ] . Equals ( EntityTagHeaderValue . Any ) )
331
350
{
351
+ context . Logger . LogNotModifiedIfNoneMatchStar ( ) ;
332
352
return true ;
333
353
}
334
354
@@ -338,6 +358,7 @@ internal static bool ConditionalRequestSatisfied(ResponseCacheContext context)
338
358
{
339
359
if ( cachedResponseHeaders . ETag . Compare ( tag , useStrongComparison : false ) )
340
360
{
361
+ context . Logger . LogNotModifiedIfNoneMatchMatched ( tag ) ;
341
362
return true ;
342
363
}
343
364
}
@@ -346,9 +367,14 @@ internal static bool ConditionalRequestSatisfied(ResponseCacheContext context)
346
367
else
347
368
{
348
369
var ifUnmodifiedSince = context . TypedRequestHeaders . IfUnmodifiedSince ;
349
- if ( ifUnmodifiedSince != null && ( cachedResponseHeaders . LastModified ?? cachedResponseHeaders . Date ) <= ifUnmodifiedSince )
370
+ if ( ifUnmodifiedSince != null )
350
371
{
351
- return true ;
372
+ var lastModified = cachedResponseHeaders . LastModified ?? cachedResponseHeaders . Date ;
373
+ if ( lastModified <= ifUnmodifiedSince )
374
+ {
375
+ context . Logger . LogNotModifiedIfUnmodifiedSinceSatisfied ( lastModified . Value , ifUnmodifiedSince . Value ) ;
376
+ return true ;
377
+ }
352
378
}
353
379
}
354
380
0 commit comments