@@ -14,23 +14,25 @@ class MockHttpRequest : HttpRequestBase
1414 {
1515 public MockHttpRequest ( )
1616 {
17- this . QueryStringValue = new NameValueCollection ( ) ;
17+ QueryStringValue = new NameValueCollection ( ) ;
18+ HeadersValue = new NameValueCollection ( ) ;
1819 }
20+
1921 public HttpCookieCollection CookiesValue { get ; set ; }
2022 public string UserAgentValue { get ; set ; }
2123 public NameValueCollection QueryStringValue { get ; set ; }
2224 public Uri UrlValue { get ; set ; }
23- public override string UserAgent
24- {
25- get
26- {
27- return UserAgentValue ;
28- }
29- }
25+ public string UserHostAddressValue { get ; set ; }
26+ public NameValueCollection HeadersValue { get ; set ; }
27+
28+ public override string UserAgent => UserAgentValue ;
3029 public override HttpCookieCollection Cookies => this . CookiesValue ;
3130 public override NameValueCollection QueryString => QueryStringValue ;
3231 public override Uri Url => UrlValue ;
32+ public override string UserHostAddress => UserHostAddressValue ;
33+ public override NameValueCollection Headers => HeadersValue ;
3334 }
35+
3436 class MockHttpResponse : HttpResponseBase
3537 {
3638 public HttpCookieCollection CookiesValue { get ; set ; }
@@ -62,7 +64,7 @@ class UserInQueueServiceMock : IUserInQueueService
6264 public List < List < string > > validateQueueRequestCalls = new List < List < string > > ( ) ;
6365 public List < List < string > > extendQueueCookieCalls = new List < List < string > > ( ) ;
6466 public List < List < string > > cancelRequestCalls = new List < List < string > > ( ) ;
65-
67+
6668 public RequestValidationResult ValidateQueueRequest ( string targetUrl , string queueitToken , QueueEventConfig config , string customerId , string secretKey )
6769 {
6870 List < string > args = new List < string > ( ) ;
@@ -108,15 +110,37 @@ public RequestValidationResult ValidateCancelRequest(string targetUrl, CancelEve
108110 }
109111 }
110112
113+ private void AssertRequestCookieContent ( string [ ] cookieValues , params string [ ] expectedValues )
114+ {
115+ Assert . True ( cookieValues . Count ( v => v . StartsWith ( "ServerUtcTime=" ) ) == 1 ) ;
116+ Assert . True ( cookieValues . Count ( v => v . StartsWith ( "RequestIP=" ) ) == 1 ) ;
117+ Assert . True ( cookieValues . Count ( v => v . StartsWith ( "RequestHttpHeader_Via=" ) ) == 1 ) ;
118+ Assert . True ( cookieValues . Count ( v => v . StartsWith ( "RequestHttpHeader_Forwarded=" ) ) == 1 ) ;
119+ Assert . True ( cookieValues . Count ( v => v . StartsWith ( "RequestHttpHeader_XForwardedFor=" ) ) == 1 ) ;
120+ Assert . True ( cookieValues . Count ( v => v . StartsWith ( "RequestHttpHeader_XForwardedHost=" ) ) == 1 ) ;
121+ Assert . True ( cookieValues . Count ( v => v . StartsWith ( "RequestHttpHeader_XForwardedProto=" ) ) == 1 ) ;
122+
123+ var utcTimeInCookie = cookieValues . FirstOrDefault ( v => v . StartsWith ( "ServerUtcTime" ) ) . Split ( '=' ) [ 1 ] ;
124+ Assert . True ( string . Compare ( expectedValues [ 0 ] , utcTimeInCookie ) <= 0 ) ;
125+ Assert . True ( string . Compare ( DateTime . UtcNow . ToString ( "o" ) , utcTimeInCookie ) >= 0 ) ;
126+
127+ Assert . True ( cookieValues . Any ( v => v == $ "RequestIP={ expectedValues [ 1 ] } ") ) ;
128+ Assert . True ( cookieValues . Any ( v => v == $ "RequestHttpHeader_Via={ expectedValues [ 2 ] } ") ) ;
129+ Assert . True ( cookieValues . Any ( v => v == $ "RequestHttpHeader_Forwarded={ expectedValues [ 3 ] } ") ) ;
130+ Assert . True ( cookieValues . Any ( v => v == $ "RequestHttpHeader_XForwardedFor={ expectedValues [ 4 ] } ") ) ;
131+ Assert . True ( cookieValues . Any ( v => v == $ "RequestHttpHeader_XForwardedHost={ expectedValues [ 5 ] } ") ) ;
132+ Assert . True ( cookieValues . Any ( v => v == $ "RequestHttpHeader_XForwardedProto={ expectedValues [ 6 ] } ") ) ;
133+ }
134+
111135 [ Fact ]
112136 public void CancelRequestByLocalConfig_Test ( )
113137 {
114138 // Arrange
115139 UserInQueueServiceMock mock = new UserInQueueServiceMock ( ) ;
116140 KnownUser . _UserInQueueService = ( mock ) ;
117- var cancelEventConfig = new CancelEventConfig ( ) { CookieDomain = "cookiedomain" , EventId = "eventid" , QueueDomain = "queuedomain" , Version = 1 } ;
141+ var cancelEventConfig = new CancelEventConfig ( ) { CookieDomain = "cookiedomain" , EventId = "eventid" , QueueDomain = "queuedomain" , Version = 1 } ;
118142 // Act
119- KnownUser . CancelRequestByLocalConfig ( "url" , "queueitToken" , cancelEventConfig , "customerid" , "secretekey" ) ;
143+ KnownUser . CancelRequestByLocalConfig ( "url" , "queueitToken" , cancelEventConfig , "customerid" , "secretekey" ) ;
120144
121145 // Assert
122146 Assert . Equal ( "url" , mock . cancelRequestCalls [ 0 ] [ 0 ] ) ;
@@ -187,7 +211,7 @@ public void CancelRequestByLocalConfig_CancelEventConfigNull_Test()
187211 UserInQueueServiceMock mock = new UserInQueueServiceMock ( ) ;
188212 KnownUser . _UserInQueueService = ( mock ) ;
189213 bool exceptionWasThrown = false ;
190-
214+
191215 // Act
192216 try
193217 {
@@ -771,7 +795,7 @@ public void ValidateRequestByIntegrationConfig_CancelAction()
771795
772796 UserInQueueServiceMock mock = new UserInQueueServiceMock ( ) ;
773797 KnownUser . _UserInQueueService = ( mock ) ;
774- // Act
798+ // Act
775799 KnownUser . ValidateRequestByIntegrationConfig ( "http://test.com?event1=true" , "queueitToken" , customerIntegration , "customerid" , "secretkey" ) ;
776800
777801 // Assert
@@ -785,25 +809,39 @@ public void ValidateRequestByIntegrationConfig_CancelAction()
785809 public void ValidateRequestByIntegrationConfig_Debug ( )
786810 {
787811 // Arrange
812+ string requestIP = "80.35.35.34" ;
813+ string viaHeader = "1.1 example.com" ;
814+ string forwardedHeader = "for=192.0.2.60;proto=http;by=203.0.113.43" ;
815+ string xForwardedForHeader = "129.78.138.66, 129.78.64.103" ;
816+ string xForwardedHostHeader = "en.wikipedia.org:8080" ;
817+ string xForwardedProtoHeader = "https" ;
818+
788819 var httpContextMock = new HttpContextMock ( )
789820 {
790821 MockRequest = new MockHttpRequest ( )
791822 {
823+ HeadersValue = new NameValueCollection ( ) {
824+ { "Via" , viaHeader } ,
825+ { "Forwarded" , forwardedHeader } ,
826+ { "X-Forwarded-For" , xForwardedForHeader } ,
827+ { "X-Forwarded-Host" , xForwardedHostHeader } ,
828+ { "X-Forwarded-Proto" , xForwardedProtoHeader }
829+ } ,
830+ UserHostAddressValue = requestIP ,
792831 QueryStringValue = new NameValueCollection ( )
793832 {
794- { "queueittoken" , "queueittoken_value" } ,
795- { "queueitdebug" , "queueitdebug_value" }
796-
833+ { "queueittoken" , "queueittoken_value" } ,
834+ { "queueitdebug" , "queueitdebug_value" }
797835 } ,
798836 UrlValue = new Uri ( "http://test.com/?event1=true&queueittoken=queueittokenvalue" ) ,
799837 CookiesValue = new HttpCookieCollection ( )
800- }
801- ,
838+ } ,
802839 MockResponse = new MockHttpResponse ( )
803840 {
804841 CookiesValue = new HttpCookieCollection ( )
805842 }
806843 } ;
844+
807845 KnownUser . _HttpContextBase = httpContextMock ;
808846 UserInQueueServiceMock mock = new UserInQueueServiceMock ( ) ;
809847 KnownUser . _UserInQueueService = ( mock ) ;
@@ -816,8 +854,6 @@ public void ValidateRequestByIntegrationConfig_Debug()
816854 triggerPart1 . IsNegative = false ;
817855 triggerPart1 . IsIgnoreCase = true ;
818856
819-
820-
821857 TriggerModel trigger = new TriggerModel ( ) ;
822858 trigger . LogicalOperator = "And" ;
823859 trigger . TriggerParts = new TriggerPart [ ] { triggerPart1 } ;
@@ -841,11 +877,11 @@ public void ValidateRequestByIntegrationConfig_Debug()
841877 customerIntegration . Version = 3 ;
842878 var queueitToken = QueueITTokenGenerator . GenerateToken ( DateTime . UtcNow , "event1" ,
843879 Guid . NewGuid ( ) . ToString ( ) , true , null , "secretKey" , out var hash , "debug" ) ;
844-
880+
881+ var utcTimeBeforeActionWasPerformed = DateTime . UtcNow . ToString ( "o" ) ;
882+
845883 // Act
846- RequestValidationResult result = KnownUser
847- . ValidateRequestByIntegrationConfig ( $ "http://test.com?event1=true",
848- queueitToken , customerIntegration , "customerId" , "secretKey" ) ;
884+ RequestValidationResult result = KnownUser . ValidateRequestByIntegrationConfig ( $ "http://test.com?event1=true", queueitToken , customerIntegration , "customerId" , "secretKey" ) ;
849885
850886 // Assert
851887 var cookieValues = HttpUtility . UrlDecode ( httpContextMock . MockResponse . Cookies [ "queueitdebug" ] . Value ) . Split ( '|' ) ;
@@ -855,17 +891,35 @@ public void ValidateRequestByIntegrationConfig_Debug()
855891 Assert . True ( cookieValues . Any ( v => v == $ "QueueitToken={ queueitToken } ") ) ;
856892 Assert . True ( cookieValues . Any ( v => v == $ "OriginalUrl=http://test.com/?event1=true&queueittoken=queueittokenvalue") ) ;
857893 Assert . True ( cookieValues . Any ( v => v == $ "TargetUrl=http://test.com?event1=true") ) ;
858- Assert . True ( cookieValues . Any ( v => v == $ "QueueConfig=EventId:event1&Version:3&QueueDomain:knownusertest.queue-it.net&CookieDomain:.test.com&ExtendCookieValidity:True&CookieValidityMinute:20&LayoutName:Christmas Layout by Queue-it&Culture:da-DK") ) ;
859- }
894+ Assert . True ( cookieValues . Any ( v => v == $ "QueueConfig=EventId:event1&Version:3&QueueDomain:knownusertest.queue-it.net&CookieDomain:.test.com&ExtendCookieValidity:True&CookieValidityMinute:20&LayoutName:Christmas Layout by Queue-it&Culture:da-DK") ) ;
860895
896+ AssertRequestCookieContent ( cookieValues ,
897+ utcTimeBeforeActionWasPerformed , requestIP , viaHeader , forwardedHeader , xForwardedForHeader , xForwardedHostHeader , xForwardedProtoHeader ) ;
898+ }
899+
861900 [ Fact ]
862901 public void ValidateRequestByIntegrationConfig_Debug_WithoutMatch ( )
863902 {
864903 // Arrange
904+ string requestIP = "80.35.35.34" ;
905+ string viaHeader = "1.1 example.com" ;
906+ string forwardedHeader = "for=192.0.2.60;proto=http;by=203.0.113.43" ;
907+ string xForwardedForHeader = "129.78.138.66, 129.78.64.103" ;
908+ string xForwardedHostHeader = "en.wikipedia.org:8080" ;
909+ string xForwardedProtoHeader = "https" ;
910+
865911 var httpContextMock = new HttpContextMock ( )
866912 {
867913 MockRequest = new MockHttpRequest ( )
868914 {
915+ HeadersValue = new NameValueCollection ( ) {
916+ { "Via" , viaHeader } ,
917+ { "Forwarded" , forwardedHeader } ,
918+ { "X-Forwarded-For" , xForwardedForHeader } ,
919+ { "X-Forwarded-Host" , xForwardedHostHeader } ,
920+ { "X-Forwarded-Proto" , xForwardedProtoHeader }
921+ } ,
922+ UserHostAddressValue = requestIP ,
869923 QueryStringValue = new NameValueCollection ( )
870924 {
871925 { "queueittoken" , "queueittoken_value" } ,
@@ -891,6 +945,9 @@ public void ValidateRequestByIntegrationConfig_Debug_WithoutMatch()
891945
892946 var queueitToken = QueueITTokenGenerator . GenerateToken ( DateTime . UtcNow , "event1" ,
893947 Guid . NewGuid ( ) . ToString ( ) , true , null , "secretKey" , out var hash , "debug" ) ;
948+
949+ var utcTimeBeforeActionWasPerformed = DateTime . UtcNow . ToString ( "o" ) ;
950+
894951 // Act
895952 RequestValidationResult result = KnownUser
896953 . ValidateRequestByIntegrationConfig ( "http://test.com?event1=true" ,
@@ -903,6 +960,9 @@ public void ValidateRequestByIntegrationConfig_Debug_WithoutMatch()
903960 Assert . True ( cookieValues . Any ( v => v == $ "ConfigVersion=10") ) ;
904961 Assert . True ( cookieValues . Any ( v => v == $ "OriginalUrl=http://test.com/?event1=true&queueittoken=queueittokenvalue") ) ;
905962 Assert . True ( cookieValues . Any ( v => v == $ "MatchedConfig=NULL") ) ;
963+
964+ AssertRequestCookieContent ( cookieValues ,
965+ utcTimeBeforeActionWasPerformed , requestIP , viaHeader , forwardedHeader , xForwardedForHeader , xForwardedHostHeader , xForwardedProtoHeader ) ;
906966 }
907967
908968 [ Fact ]
@@ -942,18 +1002,34 @@ public void ValidateRequestByIntegrationConfig_Debug_WithoutMatch_NotValidHash()
9421002 // Act
9431003 RequestValidationResult result = KnownUser
9441004 . ValidateRequestByIntegrationConfig ( "http://test.com?event1=true" ,
945- queueitToken + "test" , customerIntegration , "customerId" , "secretKey" ) ;
1005+ queueitToken + "test" , customerIntegration , "customerId" , "secretKey" ) ;
9461006
9471007 Assert . True ( httpContextMock . MockResponse . Cookies . AllKeys . Length == 0 ) ;
9481008 }
1009+
9491010 [ Fact ]
9501011 public void ResolveQueueRequestByLocalConfig_Debug ( )
9511012 {
9521013 // Arrange
1014+ string requestIP = "80.35.35.34" ;
1015+ string viaHeader = "1.1 example.com" ;
1016+ string forwardedHeader = "for=192.0.2.60;proto=http;by=203.0.113.43" ;
1017+ string xForwardedForHeader = "129.78.138.66, 129.78.64.103" ;
1018+ string xForwardedHostHeader = "en.wikipedia.org:8080" ;
1019+ string xForwardedProtoHeader = "https" ;
1020+
9531021 var httpContextMock = new HttpContextMock ( )
9541022 {
9551023 MockRequest = new MockHttpRequest ( )
9561024 {
1025+ HeadersValue = new NameValueCollection ( ) {
1026+ { "Via" , viaHeader } ,
1027+ { "Forwarded" , forwardedHeader } ,
1028+ { "X-Forwarded-For" , xForwardedForHeader } ,
1029+ { "X-Forwarded-Host" , xForwardedHostHeader } ,
1030+ { "X-Forwarded-Proto" , xForwardedProtoHeader }
1031+ } ,
1032+ UserHostAddressValue = requestIP ,
9571033 QueryStringValue = new NameValueCollection ( )
9581034 {
9591035 { "queueittoken" , "queueittoken_value" } ,
@@ -986,27 +1062,45 @@ public void ResolveQueueRequestByLocalConfig_Debug()
9861062 var queueitToken = QueueITTokenGenerator . GenerateToken ( DateTime . UtcNow , "event1" ,
9871063 Guid . NewGuid ( ) . ToString ( ) , true , null , "secretKey" , out var hash , "debug" ) ;
9881064
1065+ var utcTimeBeforeActionWasPerformed = DateTime . UtcNow . ToString ( "o" ) ;
1066+
9891067 // Act
990- RequestValidationResult result = KnownUser
991- . ResolveQueueRequestByLocalConfig ( "http://test.com?event1=true" ,
992- queueitToken , eventConfig , "customerId" , "secretKey" ) ;
1068+ RequestValidationResult result = KnownUser . ResolveQueueRequestByLocalConfig ( "http://test.com?event1=true" , queueitToken , eventConfig , "customerId" , "secretKey" ) ;
9931069
9941070 // Assert
9951071 var cookieValues = HttpUtility . UrlDecode ( httpContextMock . MockResponse . Cookies [ "queueitdebug" ] . Value ) . Split ( '|' ) ;
9961072 Assert . True ( cookieValues . Any ( v => v == $ "QueueitToken={ queueitToken } ") ) ;
9971073 Assert . True ( cookieValues . Any ( v => v == $ "OriginalUrl=http://test.com/?event1=true&queueittoken=queueittokenvalue") ) ;
9981074 Assert . True ( cookieValues . Any ( v => v == $ "TargetUrl=http://test.com?event1=true") ) ;
999- Assert . True ( cookieValues . Any ( v => v == $ "QueueConfig=EventId:eventId&Version:12&QueueDomain:queueDomain&CookieDomain:cookieDomain&ExtendCookieValidity:True&CookieValidityMinute:10&LayoutName:layoutName&Culture:culture") ) ;
1075+ Assert . True ( cookieValues . Any ( v => v == $ "QueueConfig=EventId:eventId&Version:12&QueueDomain:queueDomain&CookieDomain:cookieDomain&ExtendCookieValidity:True&CookieValidityMinute:10&LayoutName:layoutName&Culture:culture") ) ;
1076+
1077+ AssertRequestCookieContent ( cookieValues ,
1078+ utcTimeBeforeActionWasPerformed , requestIP , viaHeader , forwardedHeader , xForwardedForHeader , xForwardedHostHeader , xForwardedProtoHeader ) ;
10001079 }
10011080
10021081 [ Fact ]
10031082 public void CancelRequestByLocalConfig_Debug ( )
10041083 {
10051084 // Arrange
1085+ string requestIP = "80.35.35.34" ;
1086+ string viaHeader = "1.1 example.com" ;
1087+ string forwardedHeader = "for=192.0.2.60;proto=http;by=203.0.113.43" ;
1088+ string xForwardedForHeader = "129.78.138.66, 129.78.64.103" ;
1089+ string xForwardedHostHeader = "en.wikipedia.org:8080" ;
1090+ string xForwardedProtoHeader = "https" ;
1091+
10061092 var httpContextMock = new HttpContextMock ( )
10071093 {
10081094 MockRequest = new MockHttpRequest ( )
10091095 {
1096+ HeadersValue = new NameValueCollection ( ) {
1097+ { "Via" , viaHeader } ,
1098+ { "Forwarded" , forwardedHeader } ,
1099+ { "X-Forwarded-For" , xForwardedForHeader } ,
1100+ { "X-Forwarded-Host" , xForwardedHostHeader } ,
1101+ { "X-Forwarded-Proto" , xForwardedProtoHeader }
1102+ } ,
1103+ UserHostAddressValue = requestIP ,
10101104 QueryStringValue = new NameValueCollection ( )
10111105 {
10121106 { "queueittoken" , "queueittoken_value" } ,
@@ -1036,17 +1130,20 @@ public void CancelRequestByLocalConfig_Debug()
10361130 var queueitToken = QueueITTokenGenerator . GenerateToken ( DateTime . UtcNow , "event1" ,
10371131 Guid . NewGuid ( ) . ToString ( ) , true , null , "secretKey" , out var hash , "debug" ) ;
10381132
1133+ var utcTimeBeforeActionWasPerformed = DateTime . UtcNow . ToString ( "o" ) ;
1134+
10391135 // Act
1040- RequestValidationResult result = KnownUser
1041- . CancelRequestByLocalConfig ( "http://test.com?event1=true" ,
1042- queueitToken , eventConfig , "customerId" , "secretKey" ) ;
1136+ RequestValidationResult result = KnownUser . CancelRequestByLocalConfig ( "http://test.com?event1=true" , queueitToken , eventConfig , "customerId" , "secretKey" ) ;
10431137
10441138 // Assert
10451139 var cookieValues = HttpUtility . UrlDecode ( httpContextMock . MockResponse . Cookies [ "queueitdebug" ] . Value ) . Split ( '|' ) ;
10461140 Assert . True ( cookieValues . Any ( v => v == $ "QueueitToken={ queueitToken } ") ) ;
10471141 Assert . True ( cookieValues . Any ( v => v == $ "OriginalUrl=http://test.com/?event1=true&queueittoken=queueittokenvalue") ) ;
10481142 Assert . True ( cookieValues . Any ( v => v == $ "TargetUrl=http://test.com?event1=true") ) ;
10491143 Assert . True ( cookieValues . Any ( v => v == $ "CancelConfig=EventId:eventId&Version:12&QueueDomain:queueDomain&CookieDomain:cookieDomain") ) ;
1144+
1145+ AssertRequestCookieContent ( cookieValues ,
1146+ utcTimeBeforeActionWasPerformed , requestIP , viaHeader , forwardedHeader , xForwardedForHeader , xForwardedHostHeader , xForwardedProtoHeader ) ;
10501147 }
10511148 }
10521149}
0 commit comments