@@ -104,7 +104,7 @@ public async Task XForwardedForFirstValueIsInvalid(int limit, string header, str
104
104
[ InlineData ( 2 , "13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345" , "12.112.112.12" , 23456 , "13.113.113.13:34567" , true ) ]
105
105
[ InlineData ( 3 , "13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345" , "13.113.113.13" , 34567 , "" , false ) ]
106
106
[ InlineData ( 3 , "13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345" , "13.113.113.13" , 34567 , "" , true ) ]
107
- public async Task XForwardedForForwardLimit ( int limit , string header , string expectedIp , int expectedPort , string remainingHeader , bool requireSymmetry )
107
+ public async Task XForwardedForForwardLimit_Obsolete ( int limit , string header , string expectedIp , int expectedPort , string remainingHeader , bool requireSymmetry )
108
108
{
109
109
using var host = new HostBuilder ( )
110
110
. ConfigureWebHost ( webHostBuilder =>
@@ -123,6 +123,61 @@ public async Task XForwardedForForwardLimit(int limit, string header, string exp
123
123
#pragma warning disable ASPDEPR005 // KnownNetworks is obsolete
124
124
options . KnownNetworks . Clear ( ) ;
125
125
#pragma warning restore ASPDEPR005 // KnownNetworks is obsolete
126
+ app . UseForwardedHeaders ( options ) ;
127
+ } ) ;
128
+ } ) . Build ( ) ;
129
+
130
+ await host . StartAsync ( ) ;
131
+
132
+ var server = host . GetTestServer ( ) ;
133
+
134
+ var context = await server . SendAsync ( c =>
135
+ {
136
+ c . Request . Headers [ "X-Forwarded-For" ] = header ;
137
+ c . Connection . RemoteIpAddress = IPAddress . Parse ( "10.0.0.1" ) ;
138
+ c . Connection . RemotePort = 99 ;
139
+ } ) ;
140
+
141
+ Assert . Equal ( expectedIp , context . Connection . RemoteIpAddress . ToString ( ) ) ;
142
+ Assert . Equal ( expectedPort , context . Connection . RemotePort ) ;
143
+ Assert . Equal ( remainingHeader , context . Request . Headers [ "X-Forwarded-For" ] . ToString ( ) ) ;
144
+ }
145
+
146
+ [ Theory ]
147
+ [ InlineData ( 1 , "11.111.111.11:12345" , "11.111.111.11" , 12345 , "" , false ) ]
148
+ [ InlineData ( 1 , "11.111.111.11:12345" , "11.111.111.11" , 12345 , "" , true ) ]
149
+ [ InlineData ( 10 , "11.111.111.11:12345" , "11.111.111.11" , 12345 , "" , false ) ]
150
+ [ InlineData ( 10 , "11.111.111.11:12345" , "11.111.111.11" , 12345 , "" , true ) ]
151
+ [ InlineData ( 1 , "12.112.112.12:23456, 11.111.111.11:12345" , "11.111.111.11" , 12345 , "12.112.112.12:23456" , false ) ]
152
+ [ InlineData ( 1 , "12.112.112.12:23456, 11.111.111.11:12345" , "11.111.111.11" , 12345 , "12.112.112.12:23456" , true ) ]
153
+ [ InlineData ( 2 , "12.112.112.12:23456, 11.111.111.11:12345" , "12.112.112.12" , 23456 , "" , false ) ]
154
+ [ InlineData ( 2 , "12.112.112.12:23456, 11.111.111.11:12345" , "12.112.112.12" , 23456 , "" , true ) ]
155
+ [ InlineData ( 10 , "12.112.112.12:23456, 11.111.111.11:12345" , "12.112.112.12" , 23456 , "" , false ) ]
156
+ [ InlineData ( 10 , "12.112.112.12:23456, 11.111.111.11:12345" , "12.112.112.12" , 23456 , "" , true ) ]
157
+ [ InlineData ( 10 , "12.112.112.12.23456, 11.111.111.11:12345" , "11.111.111.11" , 12345 , "12.112.112.12.23456" , false ) ] // Invalid 2nd value
158
+ [ InlineData ( 10 , "12.112.112.12.23456, 11.111.111.11:12345" , "11.111.111.11" , 12345 , "12.112.112.12.23456" , true ) ] // Invalid 2nd value
159
+ [ InlineData ( 10 , "13.113.113.13:34567, 12.112.112.12.23456, 11.111.111.11:12345" , "11.111.111.11" , 12345 , "13.113.113.13:34567,12.112.112.12.23456" , false ) ] // Invalid 2nd value
160
+ [ InlineData ( 10 , "13.113.113.13:34567, 12.112.112.12.23456, 11.111.111.11:12345" , "11.111.111.11" , 12345 , "13.113.113.13:34567,12.112.112.12.23456" , true ) ] // Invalid 2nd value
161
+ [ InlineData ( 2 , "13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345" , "12.112.112.12" , 23456 , "13.113.113.13:34567" , false ) ]
162
+ [ InlineData ( 2 , "13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345" , "12.112.112.12" , 23456 , "13.113.113.13:34567" , true ) ]
163
+ [ InlineData ( 3 , "13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345" , "13.113.113.13" , 34567 , "" , false ) ]
164
+ [ InlineData ( 3 , "13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345" , "13.113.113.13" , 34567 , "" , true ) ]
165
+ public async Task XForwardedForForwardLimit ( int limit , string header , string expectedIp , int expectedPort , string remainingHeader , bool requireSymmetry )
166
+ {
167
+ using var host = new HostBuilder ( )
168
+ . ConfigureWebHost ( webHostBuilder =>
169
+ {
170
+ webHostBuilder
171
+ . UseTestServer ( )
172
+ . Configure ( app =>
173
+ {
174
+ var options = new ForwardedHeadersOptions
175
+ {
176
+ ForwardedHeaders = ForwardedHeaders . XForwardedFor ,
177
+ RequireHeaderSymmetry = requireSymmetry ,
178
+ ForwardLimit = limit ,
179
+ } ;
180
+ options . KnownProxies . Clear ( ) ;
126
181
options . KnownIPNetworks . Clear ( ) ;
127
182
app . UseForwardedHeaders ( options ) ;
128
183
} ) ;
@@ -847,7 +902,7 @@ public async Task XForwardedProtoOverrideCanBeIndependentOfXForwardedForCount(in
847
902
[ InlineData ( "h2, h1" , "" , "::1" , true , "http" ) ]
848
903
[ InlineData ( "h2, h1" , "F::, D::" , "::1" , true , "h1" ) ]
849
904
[ InlineData ( "h2, h1" , "E::, D::" , "F::" , true , "http" ) ]
850
- public async Task XForwardedProtoOverrideLimitedByLoopback ( string protoHeader , string forHeader , string remoteIp , bool loopback , string expected )
905
+ public async Task XForwardedProtoOverrideLimitedByLoopback_Obsolete ( string protoHeader , string forHeader , string remoteIp , bool loopback , string expected )
851
906
{
852
907
using var host = new HostBuilder ( )
853
908
. ConfigureWebHost ( webHostBuilder =>
@@ -867,6 +922,56 @@ public async Task XForwardedProtoOverrideLimitedByLoopback(string protoHeader, s
867
922
#pragma warning disable ASPDEPR005 // KnownNetworks is obsolete
868
923
options . KnownNetworks . Clear ( ) ;
869
924
#pragma warning restore ASPDEPR005 // KnownNetworks is obsolete
925
+ options . KnownProxies . Clear ( ) ;
926
+ }
927
+ app . UseForwardedHeaders ( options ) ;
928
+ } ) ;
929
+ } ) . Build ( ) ;
930
+
931
+ await host . StartAsync ( ) ;
932
+
933
+ var server = host . GetTestServer ( ) ;
934
+
935
+ var context = await server . SendAsync ( c =>
936
+ {
937
+ c . Request . Headers [ "X-Forwarded-Proto" ] = protoHeader ;
938
+ c . Request . Headers [ "X-Forwarded-For" ] = forHeader ;
939
+ c . Connection . RemoteIpAddress = IPAddress . Parse ( remoteIp ) ;
940
+ } ) ;
941
+
942
+ Assert . Equal ( expected , context . Request . Scheme ) ;
943
+ }
944
+
945
+ [ Theory ]
946
+ [ InlineData ( "" , "" , "::1" , false , "http" ) ]
947
+ [ InlineData ( "h1" , "" , "::1" , false , "http" ) ]
948
+ [ InlineData ( "h1" , "F::" , "::1" , false , "h1" ) ]
949
+ [ InlineData ( "h1" , "F::" , "E::" , false , "h1" ) ]
950
+ [ InlineData ( "" , "" , "::1" , true , "http" ) ]
951
+ [ InlineData ( "h1" , "" , "::1" , true , "http" ) ]
952
+ [ InlineData ( "h1" , "F::" , "::1" , true , "h1" ) ]
953
+ [ InlineData ( "h1" , "" , "F::" , true , "http" ) ]
954
+ [ InlineData ( "h1" , "E::" , "F::" , true , "http" ) ]
955
+ [ InlineData ( "h2, h1" , "" , "::1" , true , "http" ) ]
956
+ [ InlineData ( "h2, h1" , "F::, D::" , "::1" , true , "h1" ) ]
957
+ [ InlineData ( "h2, h1" , "E::, D::" , "F::" , true , "http" ) ]
958
+ public async Task XForwardedProtoOverrideLimitedByLoopback ( string protoHeader , string forHeader , string remoteIp , bool loopback , string expected )
959
+ {
960
+ using var host = new HostBuilder ( )
961
+ . ConfigureWebHost ( webHostBuilder =>
962
+ {
963
+ webHostBuilder
964
+ . UseTestServer ( )
965
+ . Configure ( app =>
966
+ {
967
+ var options = new ForwardedHeadersOptions
968
+ {
969
+ ForwardedHeaders = ForwardedHeaders . XForwardedProto | ForwardedHeaders . XForwardedFor ,
970
+ RequireHeaderSymmetry = true ,
971
+ ForwardLimit = 5 ,
972
+ } ;
973
+ if ( ! loopback )
974
+ {
870
975
options . KnownIPNetworks . Clear ( ) ;
871
976
options . KnownProxies . Clear ( ) ;
872
977
}
@@ -1127,7 +1232,7 @@ public async Task XForwardForIPv4ToIPv6Mapping(string forHeader, string knownPro
1127
1232
[ Theory ]
1128
1233
[ InlineData ( 1 , "httpa, httpb, httpc" , "httpc" , "httpa,httpb" ) ]
1129
1234
[ InlineData ( 2 , "httpa, httpb, httpc" , "httpb" , "httpa" ) ]
1130
- public async Task ForwardersWithDIOptionsRunsOnce ( int limit , string header , string expectedScheme , string remainingHeader )
1235
+ public async Task ForwardersWithDIOptionsRunsOnce_Obsolete ( int limit , string header , string expectedScheme , string remainingHeader )
1131
1236
{
1132
1237
using var host = new HostBuilder ( )
1133
1238
. ConfigureWebHost ( webHostBuilder =>
@@ -1143,6 +1248,45 @@ public async Task ForwardersWithDIOptionsRunsOnce(int limit, string header, stri
1143
1248
#pragma warning disable ASPDEPR005 // KnownNetworks is obsolete
1144
1249
options . KnownNetworks . Clear ( ) ;
1145
1250
#pragma warning restore ASPDEPR005 // KnownNetworks is obsolete
1251
+ options . ForwardLimit = limit ;
1252
+ } ) ;
1253
+ } )
1254
+ . Configure ( app =>
1255
+ {
1256
+ app . UseForwardedHeaders ( ) ;
1257
+ app . UseForwardedHeaders ( ) ;
1258
+ } ) ;
1259
+ } ) . Build ( ) ;
1260
+
1261
+ await host . StartAsync ( ) ;
1262
+
1263
+ var server = host . GetTestServer ( ) ;
1264
+
1265
+ var context = await server . SendAsync ( c =>
1266
+ {
1267
+ c . Request . Headers [ "X-Forwarded-Proto" ] = header ;
1268
+ } ) ;
1269
+
1270
+ Assert . Equal ( expectedScheme , context . Request . Scheme ) ;
1271
+ Assert . Equal ( remainingHeader , context . Request . Headers [ "X-Forwarded-Proto" ] . ToString ( ) ) ;
1272
+ }
1273
+
1274
+ [ Theory ]
1275
+ [ InlineData ( 1 , "httpa, httpb, httpc" , "httpc" , "httpa,httpb" ) ]
1276
+ [ InlineData ( 2 , "httpa, httpb, httpc" , "httpb" , "httpa" ) ]
1277
+ public async Task ForwardersWithDIOptionsRunsOnce ( int limit , string header , string expectedScheme , string remainingHeader )
1278
+ {
1279
+ using var host = new HostBuilder ( )
1280
+ . ConfigureWebHost ( webHostBuilder =>
1281
+ {
1282
+ webHostBuilder
1283
+ . UseTestServer ( )
1284
+ . ConfigureServices ( services =>
1285
+ {
1286
+ services . Configure < ForwardedHeadersOptions > ( options =>
1287
+ {
1288
+ options . ForwardedHeaders = ForwardedHeaders . XForwardedProto ;
1289
+ options . KnownProxies . Clear ( ) ;
1146
1290
options . KnownIPNetworks . Clear ( ) ;
1147
1291
options . ForwardLimit = limit ;
1148
1292
} ) ;
@@ -1170,7 +1314,7 @@ public async Task ForwardersWithDIOptionsRunsOnce(int limit, string header, stri
1170
1314
[ Theory ]
1171
1315
[ InlineData ( 1 , "httpa, httpb, httpc" , "httpb" , "httpa" ) ]
1172
1316
[ InlineData ( 2 , "httpa, httpb, httpc" , "httpa" , "" ) ]
1173
- public async Task ForwardersWithDirectOptionsRunsTwice ( int limit , string header , string expectedScheme , string remainingHeader )
1317
+ public async Task ForwardersWithDirectOptionsRunsTwice_Obsolete ( int limit , string header , string expectedScheme , string remainingHeader )
1174
1318
{
1175
1319
using var host = new HostBuilder ( )
1176
1320
. ConfigureWebHost ( webHostBuilder =>
@@ -1188,6 +1332,42 @@ public async Task ForwardersWithDirectOptionsRunsTwice(int limit, string header,
1188
1332
#pragma warning disable ASPDEPR005 // KnownNetworks is obsolete
1189
1333
options . KnownNetworks . Clear ( ) ;
1190
1334
#pragma warning restore ASPDEPR005 // KnownNetworks is obsolete
1335
+ app . UseForwardedHeaders ( options ) ;
1336
+ app . UseForwardedHeaders ( options ) ;
1337
+ } ) ;
1338
+ } ) . Build ( ) ;
1339
+
1340
+ await host . StartAsync ( ) ;
1341
+
1342
+ var server = host . GetTestServer ( ) ;
1343
+
1344
+ var context = await server . SendAsync ( c =>
1345
+ {
1346
+ c . Request . Headers [ "X-Forwarded-Proto" ] = header ;
1347
+ } ) ;
1348
+
1349
+ Assert . Equal ( expectedScheme , context . Request . Scheme ) ;
1350
+ Assert . Equal ( remainingHeader , context . Request . Headers [ "X-Forwarded-Proto" ] . ToString ( ) ) ;
1351
+ }
1352
+
1353
+ [ Theory ]
1354
+ [ InlineData ( 1 , "httpa, httpb, httpc" , "httpb" , "httpa" ) ]
1355
+ [ InlineData ( 2 , "httpa, httpb, httpc" , "httpa" , "" ) ]
1356
+ public async Task ForwardersWithDirectOptionsRunsTwice ( int limit , string header , string expectedScheme , string remainingHeader )
1357
+ {
1358
+ using var host = new HostBuilder ( )
1359
+ . ConfigureWebHost ( webHostBuilder =>
1360
+ {
1361
+ webHostBuilder
1362
+ . UseTestServer ( )
1363
+ . Configure ( app =>
1364
+ {
1365
+ var options = new ForwardedHeadersOptions
1366
+ {
1367
+ ForwardedHeaders = ForwardedHeaders . XForwardedProto ,
1368
+ ForwardLimit = limit ,
1369
+ } ;
1370
+ options . KnownProxies . Clear ( ) ;
1191
1371
options . KnownIPNetworks . Clear ( ) ;
1192
1372
app . UseForwardedHeaders ( options ) ;
1193
1373
app . UseForwardedHeaders ( options ) ;
0 commit comments