@@ -287,3 +287,82 @@ 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+ ", " ,
314+ ) ;
315+ const request = new Request (
316+ createMockNativeRequest ( "https://example.com/index.html" , {
317+ headers : {
318+ "x-forwarded-host" : "example.com" ,
319+ "x-forwarded-proto" : "http" ,
320+ // also prepend some whitespace noise to mimic worst-case patterns
321+ "x-forwarded-for" : ` \t ${ manyIps } \t ` ,
322+ } ,
323+ } ) ,
324+ { proxy : true , secure : true } ,
325+ ) ;
326+ performance . mark ( "start-xff" ) ;
327+ const ips = request . ips ;
328+ const measure = performance . measure ( "xff" , { start : "start-xff" } ) ;
329+ // Hard upper bound; the operation should be very fast
330+ assert ( measure . duration < 20 ) ;
331+ // Ensure we cap the number of parsed IPs (implementation caps at 100)
332+ assertEquals ( ips . length , 100 ) ;
333+ assertEquals ( ips [ 0 ] , "10.0.0.0" ) ;
334+ } ,
335+ } ) ;
336+
337+ Deno . test ( {
338+ name : "request.x-forwarded-proto - normalizes and allowlists http/https" ,
339+ fn ( ) {
340+ const request = new Request (
341+ createMockNativeRequest ( "http://example.com/index.html" , {
342+ headers : {
343+ "x-forwarded-host" : "example.com" ,
344+ "x-forwarded-proto" : " HTTPS , http " ,
345+ } ,
346+ } ) ,
347+ { proxy : true } ,
348+ ) ;
349+ assertEquals ( request . url . protocol , "https:" ) ;
350+ } ,
351+ } ) ;
352+
353+ Deno . test ( {
354+ name : "request.x-forwarded-proto - invalid values fall back to http" ,
355+ fn ( ) {
356+ const request = new Request (
357+ createMockNativeRequest ( "http://example.com/index.html" , {
358+ headers : {
359+ "x-forwarded-host" : "example.com" ,
360+ // first token invalid, second valid, we only honor the first
361+ "x-forwarded-proto" : "javascript, https" ,
362+ } ,
363+ } ) ,
364+ { proxy : true } ,
365+ ) ;
366+ assertEquals ( request . url . protocol , "http:" ) ;
367+ } ,
368+ } ) ;
0 commit comments