22// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33
44using System ;
5+ using Microsoft . AspNetCore . Http . Features ;
6+ using Microsoft . Extensions . DependencyInjection ;
7+ using Microsoft . Extensions . Logging ;
8+ using Microsoft . Extensions . Logging . Testing ;
59using Microsoft . Net . Http . Headers ;
610using Xunit ;
711
812namespace Microsoft . AspNetCore . Http . Tests
913{
1014 public class ResponseCookiesTest
1115 {
16+ private IFeatureCollection MakeFeatures ( IHeaderDictionary headers )
17+ {
18+ var responseFeature = new HttpResponseFeature ( )
19+ {
20+ Headers = headers
21+ } ;
22+ var features = new FeatureCollection ( ) ;
23+ features . Set < IHttpResponseFeature > ( responseFeature ) ;
24+ return features ;
25+ }
26+
27+ [ Fact ]
28+ public void AppendSameSiteNoneWithoutSecureLogsWarning ( )
29+ {
30+ var headers = new HeaderDictionary ( ) ;
31+ var features = MakeFeatures ( headers ) ;
32+ var services = new ServiceCollection ( ) ;
33+
34+ var sink = new TestSink ( TestSink . EnableWithTypeName < ResponseCookies > ) ;
35+ var loggerFactory = new TestLoggerFactory ( sink , enabled : true ) ;
36+ services . AddLogging ( ) ;
37+ services . AddSingleton < ILoggerFactory > ( loggerFactory ) ;
38+
39+ features . Set < IServiceProvidersFeature > ( new ServiceProvidersFeature ( ) { RequestServices = services . BuildServiceProvider ( ) } ) ;
40+
41+ var cookies = new ResponseCookies ( features ) ;
42+ var testCookie = "TestCookie" ;
43+
44+ cookies . Append ( testCookie , "value" , new CookieOptions ( )
45+ {
46+ SameSite = SameSiteMode . None ,
47+ } ) ;
48+
49+ var cookieHeaderValues = headers [ HeaderNames . SetCookie ] ;
50+ Assert . Single ( cookieHeaderValues ) ;
51+ Assert . StartsWith ( testCookie , cookieHeaderValues [ 0 ] ) ;
52+ Assert . Contains ( "path=/" , cookieHeaderValues [ 0 ] ) ;
53+ Assert . Contains ( "samesite=none" , cookieHeaderValues [ 0 ] ) ;
54+ Assert . DoesNotContain ( "secure" , cookieHeaderValues [ 0 ] ) ;
55+
56+ var writeContext = Assert . Single ( sink . Writes ) ;
57+ Assert . Equal ( "The cookie 'TestCookie' has set 'SameSite=None' and must also set 'Secure'." , writeContext . Message ) ;
58+ }
59+
1260 [ Fact ]
1361 public void DeleteCookieShouldSetDefaultPath ( )
1462 {
1563 var headers = new HeaderDictionary ( ) ;
16- var cookies = new ResponseCookies ( headers ) ;
64+ var features = MakeFeatures ( headers ) ;
65+ var cookies = new ResponseCookies ( features ) ;
1766 var testCookie = "TestCookie" ;
1867
1968 cookies . Delete ( testCookie ) ;
@@ -29,7 +78,8 @@ public void DeleteCookieShouldSetDefaultPath()
2978 public void DeleteCookieWithCookieOptionsShouldKeepPropertiesOfCookieOptions ( )
3079 {
3180 var headers = new HeaderDictionary ( ) ;
32- var cookies = new ResponseCookies ( headers ) ;
81+ var features = MakeFeatures ( headers ) ;
82+ var cookies = new ResponseCookies ( features ) ;
3383 var testCookie = "TestCookie" ;
3484 var time = new DateTimeOffset ( 2000 , 1 , 1 , 1 , 1 , 1 , 1 , TimeSpan . Zero ) ;
3585 var options = new CookieOptions
@@ -58,7 +108,8 @@ public void DeleteCookieWithCookieOptionsShouldKeepPropertiesOfCookieOptions()
58108 public void NoParamsDeleteRemovesCookieCreatedByAdd ( )
59109 {
60110 var headers = new HeaderDictionary ( ) ;
61- var cookies = new ResponseCookies ( headers ) ;
111+ var features = MakeFeatures ( headers ) ;
112+ var cookies = new ResponseCookies ( features ) ;
62113 var testCookie = "TestCookie" ;
63114
64115 cookies . Append ( testCookie , testCookie ) ;
@@ -75,7 +126,8 @@ public void NoParamsDeleteRemovesCookieCreatedByAdd()
75126 public void ProvidesMaxAgeWithCookieOptionsArgumentExpectMaxAgeToBeSet ( )
76127 {
77128 var headers = new HeaderDictionary ( ) ;
78- var cookies = new ResponseCookies ( headers ) ;
129+ var features = MakeFeatures ( headers ) ;
130+ var cookies = new ResponseCookies ( features ) ;
79131 var cookieOptions = new CookieOptions ( ) ;
80132 var maxAgeTime = TimeSpan . FromHours ( 1 ) ;
81133 cookieOptions . MaxAge = TimeSpan . FromHours ( 1 ) ;
@@ -96,7 +148,8 @@ public void ProvidesMaxAgeWithCookieOptionsArgumentExpectMaxAgeToBeSet()
96148 public void EscapesValuesBeforeSettingCookie ( string value , string expected )
97149 {
98150 var headers = new HeaderDictionary ( ) ;
99- var cookies = new ResponseCookies ( headers ) ;
151+ var features = MakeFeatures ( headers ) ;
152+ var cookies = new ResponseCookies ( features ) ;
100153
101154 cookies . Append ( "key" , value ) ;
102155
@@ -111,7 +164,8 @@ public void EscapesValuesBeforeSettingCookie(string value, string expected)
111164 public void InvalidKeysThrow ( string key )
112165 {
113166 var headers = new HeaderDictionary ( ) ;
114- var cookies = new ResponseCookies ( headers ) ;
167+ var features = MakeFeatures ( headers ) ;
168+ var cookies = new ResponseCookies ( features ) ;
115169
116170 Assert . Throws < ArgumentException > ( ( ) => cookies . Append ( key , "1" ) ) ;
117171 }
@@ -124,7 +178,8 @@ public void InvalidKeysThrow(string key)
124178 public void AppContextSwitchEscapesKeysAndValuesBeforeSettingCookie ( string key , string value , string expected )
125179 {
126180 var headers = new HeaderDictionary ( ) ;
127- var cookies = new ResponseCookies ( headers ) ;
181+ var features = MakeFeatures ( headers ) ;
182+ var cookies = new ResponseCookies ( features ) ;
128183 cookies . _enableCookieNameEncoding = true ;
129184
130185 cookies . Append ( key , value ) ;
0 commit comments