Skip to content
This repository was archived by the owner on Nov 22, 2018. It is now read-only.

Commit 8ea6f99

Browse files
committed
Minor fix and add tests
1 parent ba1bf80 commit 8ea6f99

File tree

2 files changed

+136
-1
lines changed

2 files changed

+136
-1
lines changed

src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ internal bool ConditionalRequestSatisfied(ResponseHeaders cachedResponseHeaders)
522522
}
523523
}
524524
}
525-
else if ((cachedResponseHeaders.LastModified ?? cachedResponseHeaders.Date) < RequestHeaders.IfUnmodifiedSince)
525+
else if ((cachedResponseHeaders.LastModified ?? cachedResponseHeaders.Date) <= RequestHeaders.IfUnmodifiedSince)
526526
{
527527
return true;
528528
}

test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachingContextTests.cs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Microsoft.Extensions.ObjectPool;
1313
using Microsoft.Net.Http.Headers;
1414
using Xunit;
15+
using System.Collections.Generic;
1516

1617
namespace Microsoft.AspNetCore.ResponseCaching.Tests
1718
{
@@ -692,6 +693,140 @@ public void EntryIsFresh_IgnoresRequestVerificationWhenSpecified()
692693
Assert.True(context.EntryIsFresh(httpContext.Response.GetTypedHeaders(), TimeSpan.FromSeconds(3), verifyAgainstRequest: false));
693694
}
694695

696+
[Fact]
697+
public void ConditionalRequestSatisfied_NotConditionalRequest_Fails()
698+
{
699+
var context = CreateTestContext(new DefaultHttpContext());
700+
var cachedHeaders = new ResponseHeaders(new HeaderDictionary());
701+
702+
Assert.False(context.ConditionalRequestSatisfied(cachedHeaders));
703+
}
704+
705+
[Fact]
706+
public void ConditionalRequestSatisfied_IfUnmodifiedSince_FallsbackToDateHeader()
707+
{
708+
var utcNow = DateTimeOffset.UtcNow;
709+
var cachedHeaders = new ResponseHeaders(new HeaderDictionary());
710+
var httpContext = new DefaultHttpContext();
711+
var context = CreateTestContext(httpContext);
712+
713+
httpContext.Request.GetTypedHeaders().IfUnmodifiedSince = utcNow;
714+
715+
// Verify modifications in the past succeeds
716+
cachedHeaders.Date = utcNow - TimeSpan.FromSeconds(10);
717+
Assert.True(context.ConditionalRequestSatisfied(cachedHeaders));
718+
719+
// Verify modifications at present succeeds
720+
cachedHeaders.Date = utcNow;
721+
Assert.True(context.ConditionalRequestSatisfied(cachedHeaders));
722+
723+
// Verify modifications in the future fails
724+
cachedHeaders.Date = utcNow + TimeSpan.FromSeconds(10);
725+
Assert.False(context.ConditionalRequestSatisfied(cachedHeaders));
726+
}
727+
728+
[Fact]
729+
public void ConditionalRequestSatisfied_IfUnmodifiedSince_LastModifiedOverridesDateHeader()
730+
{
731+
var utcNow = DateTimeOffset.UtcNow;
732+
var cachedHeaders = new ResponseHeaders(new HeaderDictionary());
733+
var httpContext = new DefaultHttpContext();
734+
var context = CreateTestContext(httpContext);
735+
736+
httpContext.Request.GetTypedHeaders().IfUnmodifiedSince = utcNow;
737+
738+
// Verify modifications in the past succeeds
739+
cachedHeaders.Date = utcNow + TimeSpan.FromSeconds(10);
740+
cachedHeaders.LastModified = utcNow - TimeSpan.FromSeconds(10);
741+
Assert.True(context.ConditionalRequestSatisfied(cachedHeaders));
742+
743+
// Verify modifications at present
744+
cachedHeaders.Date = utcNow + TimeSpan.FromSeconds(10);
745+
cachedHeaders.LastModified = utcNow;
746+
Assert.True(context.ConditionalRequestSatisfied(cachedHeaders));
747+
748+
// Verify modifications in the future fails
749+
cachedHeaders.Date = utcNow - TimeSpan.FromSeconds(10);
750+
cachedHeaders.LastModified = utcNow + TimeSpan.FromSeconds(10);
751+
Assert.False(context.ConditionalRequestSatisfied(cachedHeaders));
752+
}
753+
754+
[Fact]
755+
public void ConditionalRequestSatisfied_IfNoneMatch_Overrides_IfUnmodifiedSince_ToPass()
756+
{
757+
var utcNow = DateTimeOffset.UtcNow;
758+
var cachedHeaders = new ResponseHeaders(new HeaderDictionary());
759+
var httpContext = new DefaultHttpContext();
760+
var requestHeaders = httpContext.Request.GetTypedHeaders();
761+
var context = CreateTestContext(httpContext);
762+
763+
// This would fail the IfUnmodifiedSince checks
764+
requestHeaders.IfUnmodifiedSince = utcNow;
765+
cachedHeaders.LastModified = utcNow + TimeSpan.FromSeconds(10);
766+
767+
requestHeaders.IfNoneMatch = new List<EntityTagHeaderValue>(new[] { EntityTagHeaderValue.Any });
768+
Assert.True(context.ConditionalRequestSatisfied(cachedHeaders));
769+
}
770+
771+
[Fact]
772+
public void ConditionalRequestSatisfied_IfNoneMatch_Overrides_IfUnmodifiedSince_ToFail()
773+
{
774+
var utcNow = DateTimeOffset.UtcNow;
775+
var cachedHeaders = new ResponseHeaders(new HeaderDictionary());
776+
var httpContext = new DefaultHttpContext();
777+
var requestHeaders = httpContext.Request.GetTypedHeaders();
778+
var context = CreateTestContext(httpContext);
779+
780+
// This would pass the IfUnmodifiedSince checks
781+
requestHeaders.IfUnmodifiedSince = utcNow;
782+
cachedHeaders.LastModified = utcNow - TimeSpan.FromSeconds(10);
783+
784+
requestHeaders.IfNoneMatch = new List<EntityTagHeaderValue>(new[] { new EntityTagHeaderValue("\"E1\"") });
785+
Assert.False(context.ConditionalRequestSatisfied(cachedHeaders));
786+
}
787+
788+
[Fact]
789+
public void ConditionalRequestSatisfied_IfNoneMatch_AnyWithoutETagInResponse_Passes()
790+
{
791+
var cachedHeaders = new ResponseHeaders(new HeaderDictionary());
792+
var httpContext = new DefaultHttpContext();
793+
var context = CreateTestContext(httpContext);
794+
795+
httpContext.Request.GetTypedHeaders().IfNoneMatch = new List<EntityTagHeaderValue>(new[] { new EntityTagHeaderValue("\"E1\"") });
796+
797+
Assert.False(context.ConditionalRequestSatisfied(cachedHeaders));
798+
}
799+
800+
[Fact]
801+
public void ConditionalRequestSatisfied_IfNoneMatch_ExplicitWithMatch_Passes()
802+
{
803+
var cachedHeaders = new ResponseHeaders(new HeaderDictionary())
804+
{
805+
ETag = new EntityTagHeaderValue("\"E1\"")
806+
};
807+
var httpContext = new DefaultHttpContext();
808+
var context = CreateTestContext(httpContext);
809+
810+
httpContext.Request.GetTypedHeaders().IfNoneMatch = new List<EntityTagHeaderValue>(new[] { new EntityTagHeaderValue("\"E1\"") });
811+
812+
Assert.True(context.ConditionalRequestSatisfied(cachedHeaders));
813+
}
814+
815+
[Fact]
816+
public void ConditionalRequestSatisfied_IfNoneMatch_ExplicitWithoutMatch_Fails()
817+
{
818+
var cachedHeaders = new ResponseHeaders(new HeaderDictionary())
819+
{
820+
ETag = new EntityTagHeaderValue("\"E2\"")
821+
};
822+
var httpContext = new DefaultHttpContext();
823+
var context = CreateTestContext(httpContext);
824+
825+
httpContext.Request.GetTypedHeaders().IfNoneMatch = new List<EntityTagHeaderValue>(new[] { new EntityTagHeaderValue("\"E1\"") });
826+
827+
Assert.False(context.ConditionalRequestSatisfied(cachedHeaders));
828+
}
829+
695830
private static ResponseCachingContext CreateTestContext(HttpContext httpContext)
696831
{
697832
return CreateTestContext(

0 commit comments

Comments
 (0)