@@ -423,6 +423,138 @@ public async void ServesFreshContentIfInitialRequestContainsNoStore()
423
423
}
424
424
}
425
425
426
+ [ Fact ]
427
+ public async void Serves304_IfIfModifiedSince_Satisfied ( )
428
+ {
429
+ var builder = CreateBuilderWithResponseCaching ( async ( context ) =>
430
+ {
431
+ var uniqueId = Guid . NewGuid ( ) . ToString ( ) ;
432
+ var headers = context . Response . GetTypedHeaders ( ) ;
433
+ headers . CacheControl = new CacheControlHeaderValue ( )
434
+ {
435
+ Public = true ,
436
+ MaxAge = TimeSpan . FromSeconds ( 10 )
437
+ } ;
438
+ headers . Date = DateTimeOffset . UtcNow ;
439
+ headers . Headers [ "X-Value" ] = uniqueId ;
440
+ await context . Response . WriteAsync ( uniqueId ) ;
441
+ } ) ;
442
+
443
+ using ( var server = new TestServer ( builder ) )
444
+ {
445
+ var client = server . CreateClient ( ) ;
446
+ var initialResponse = await client . GetAsync ( "" ) ;
447
+ client . DefaultRequestHeaders . IfUnmodifiedSince = DateTimeOffset . MaxValue ;
448
+ var subsequentResponse = await client . GetAsync ( "" ) ;
449
+
450
+ initialResponse . EnsureSuccessStatusCode ( ) ;
451
+ Assert . Equal ( System . Net . HttpStatusCode . NotModified , subsequentResponse . StatusCode ) ;
452
+ }
453
+ }
454
+
455
+ [ Fact ]
456
+ public async void ServesCachedContent_IfIfModifiedSince_NotSatisfied ( )
457
+ {
458
+ var builder = CreateBuilderWithResponseCaching ( async ( context ) =>
459
+ {
460
+ var uniqueId = Guid . NewGuid ( ) . ToString ( ) ;
461
+ var headers = context . Response . GetTypedHeaders ( ) ;
462
+ headers . CacheControl = new CacheControlHeaderValue ( )
463
+ {
464
+ Public = true ,
465
+ MaxAge = TimeSpan . FromSeconds ( 10 )
466
+ } ;
467
+ headers . Date = DateTimeOffset . UtcNow ;
468
+ headers . Headers [ "X-Value" ] = uniqueId ;
469
+ await context . Response . WriteAsync ( uniqueId ) ;
470
+ } ) ;
471
+
472
+ using ( var server = new TestServer ( builder ) )
473
+ {
474
+ var client = server . CreateClient ( ) ;
475
+ var initialResponse = await client . GetAsync ( "" ) ;
476
+ client . DefaultRequestHeaders . IfUnmodifiedSince = DateTimeOffset . MinValue ;
477
+ var subsequentResponse = await client . GetAsync ( "" ) ;
478
+
479
+ initialResponse . EnsureSuccessStatusCode ( ) ;
480
+ subsequentResponse . EnsureSuccessStatusCode ( ) ;
481
+
482
+ foreach ( var header in initialResponse . Headers )
483
+ {
484
+ Assert . Equal ( initialResponse . Headers . GetValues ( header . Key ) , subsequentResponse . Headers . GetValues ( header . Key ) ) ;
485
+ }
486
+ Assert . True ( subsequentResponse . Headers . Contains ( HeaderNames . Age ) ) ;
487
+ Assert . Equal ( await initialResponse . Content . ReadAsStringAsync ( ) , await subsequentResponse . Content . ReadAsStringAsync ( ) ) ;
488
+ }
489
+ }
490
+
491
+ [ Fact ]
492
+ public async void Serves304_IfIfNoneMatch_Satisfied ( )
493
+ {
494
+ var builder = CreateBuilderWithResponseCaching ( async ( context ) =>
495
+ {
496
+ var uniqueId = Guid . NewGuid ( ) . ToString ( ) ;
497
+ var headers = context . Response . GetTypedHeaders ( ) ;
498
+ headers . CacheControl = new CacheControlHeaderValue ( )
499
+ {
500
+ Public = true ,
501
+ MaxAge = TimeSpan . FromSeconds ( 10 )
502
+ } ;
503
+ headers . Date = DateTimeOffset . UtcNow ;
504
+ headers . Headers [ "X-Value" ] = uniqueId ;
505
+ headers . ETag = new EntityTagHeaderValue ( "\" E1\" " ) ;
506
+ await context . Response . WriteAsync ( uniqueId ) ;
507
+ } ) ;
508
+
509
+ using ( var server = new TestServer ( builder ) )
510
+ {
511
+ var client = server . CreateClient ( ) ;
512
+ var initialResponse = await client . GetAsync ( "" ) ;
513
+ client . DefaultRequestHeaders . IfNoneMatch . Add ( new System . Net . Http . Headers . EntityTagHeaderValue ( "\" E1\" " ) ) ;
514
+ var subsequentResponse = await client . GetAsync ( "" ) ;
515
+
516
+ initialResponse . EnsureSuccessStatusCode ( ) ;
517
+ Assert . Equal ( System . Net . HttpStatusCode . NotModified , subsequentResponse . StatusCode ) ;
518
+ }
519
+ }
520
+
521
+ [ Fact ]
522
+ public async void ServesCachedContent_IfIfNoneMatch_NotSatisfied ( )
523
+ {
524
+ var builder = CreateBuilderWithResponseCaching ( async ( context ) =>
525
+ {
526
+ var uniqueId = Guid . NewGuid ( ) . ToString ( ) ;
527
+ var headers = context . Response . GetTypedHeaders ( ) ;
528
+ headers . CacheControl = new CacheControlHeaderValue ( )
529
+ {
530
+ Public = true ,
531
+ MaxAge = TimeSpan . FromSeconds ( 10 )
532
+ } ;
533
+ headers . Date = DateTimeOffset . UtcNow ;
534
+ headers . Headers [ "X-Value" ] = uniqueId ;
535
+ headers . ETag = new EntityTagHeaderValue ( "\" E1\" " ) ;
536
+ await context . Response . WriteAsync ( uniqueId ) ;
537
+ } ) ;
538
+
539
+ using ( var server = new TestServer ( builder ) )
540
+ {
541
+ var client = server . CreateClient ( ) ;
542
+ var initialResponse = await client . GetAsync ( "" ) ;
543
+ client . DefaultRequestHeaders . IfNoneMatch . Add ( new System . Net . Http . Headers . EntityTagHeaderValue ( "\" E2\" " ) ) ;
544
+ var subsequentResponse = await client . GetAsync ( "" ) ;
545
+
546
+ initialResponse . EnsureSuccessStatusCode ( ) ;
547
+ subsequentResponse . EnsureSuccessStatusCode ( ) ;
548
+
549
+ foreach ( var header in initialResponse . Headers )
550
+ {
551
+ Assert . Equal ( initialResponse . Headers . GetValues ( header . Key ) , subsequentResponse . Headers . GetValues ( header . Key ) ) ;
552
+ }
553
+ Assert . True ( subsequentResponse . Headers . Contains ( HeaderNames . Age ) ) ;
554
+ Assert . Equal ( await initialResponse . Content . ReadAsStringAsync ( ) , await subsequentResponse . Content . ReadAsStringAsync ( ) ) ;
555
+ }
556
+ }
557
+
426
558
private static IWebHostBuilder CreateBuilderWithResponseCaching ( RequestDelegate requestDelegate ) =>
427
559
CreateBuilderWithResponseCaching ( app => { } , requestDelegate ) ;
428
560
0 commit comments