@@ -287,3 +287,80 @@ Deno.test({
287287 ) ;
288288 } ,
289289} ) ;
290+
291+ Deno . test ( {
292+ name : "request.x-forwarded-for - splits, trims, and orders correctly" ,
293+ fn ( ) {
294+ const request = new Request (
295+ createMockNativeRequest ( "https://example.com/index.html" , {
296+ headers : {
297+ "x-forwarded-host" : "example.com" ,
298+ "x-forwarded-proto" : "http" ,
299+ "x-forwarded-for" : " 10.10.10.10 , 192.168.1.1 , [::1] " ,
300+ } ,
301+ } ) ,
302+ { proxy : true , secure : true } ,
303+ ) ;
304+ assertEquals ( request . ips , [ "10.10.10.10" , "192.168.1.1" , "[::1]" ] ) ;
305+ assertEquals ( request . ip , "10.10.10.10" ) ;
306+ } ,
307+ } ) ;
308+
309+ Deno . test ( {
310+ name : "request.x-forwarded-for - caps entries and is performant" ,
311+ fn ( ) {
312+ const manyIps = Array . from ( { length : 1000 } , ( _ , i ) => `10.0.0.${ i } ` ) . join ( ", " ) ;
313+ const request = new Request (
314+ createMockNativeRequest ( "https://example.com/index.html" , {
315+ headers : {
316+ "x-forwarded-host" : "example.com" ,
317+ "x-forwarded-proto" : "http" ,
318+ // also prepend some whitespace noise to mimic worst-case patterns
319+ "x-forwarded-for" : ` \t ${ manyIps } \t ` ,
320+ } ,
321+ } ) ,
322+ { proxy : true , secure : true } ,
323+ ) ;
324+ performance . mark ( "start-xff" ) ;
325+ const ips = request . ips ;
326+ const measure = performance . measure ( "xff" , { start : "start-xff" } ) ;
327+ // Hard upper bound; the operation should be very fast
328+ assert ( measure . duration < 20 ) ;
329+ // Ensure we cap the number of parsed IPs (implementation caps at 100)
330+ assertEquals ( ips . length , 100 ) ;
331+ assertEquals ( ips [ 0 ] , "10.0.0.0" ) ;
332+ } ,
333+ } ) ;
334+
335+ Deno . test ( {
336+ name : "request.x-forwarded-proto - normalizes and allowlists http/https" ,
337+ fn ( ) {
338+ const request = new Request (
339+ createMockNativeRequest ( "http://example.com/index.html" , {
340+ headers : {
341+ "x-forwarded-host" : "example.com" ,
342+ "x-forwarded-proto" : " HTTPS , http " ,
343+ } ,
344+ } ) ,
345+ { proxy : true } ,
346+ ) ;
347+ assertEquals ( request . url . protocol , "https:" ) ;
348+ } ,
349+ } ) ;
350+
351+ Deno . test ( {
352+ name : "request.x-forwarded-proto - invalid values fall back to http" ,
353+ fn ( ) {
354+ const request = new Request (
355+ createMockNativeRequest ( "http://example.com/index.html" , {
356+ headers : {
357+ "x-forwarded-host" : "example.com" ,
358+ // first token invalid, second valid, we only honor the first
359+ "x-forwarded-proto" : "javascript, https" ,
360+ } ,
361+ } ) ,
362+ { proxy : true } ,
363+ ) ;
364+ assertEquals ( request . url . protocol , "http:" ) ;
365+ } ,
366+ } ) ;
0 commit comments