@@ -494,12 +494,10 @@ describe('Validation Utils', () => {
494494 expect ( secured . headers . get ( 'forwarded' ) ) . toBe ( 'host=proxy.com;proto=https' ) ;
495495 } ) ;
496496
497- it ( 'should not tee request body and should preserve abort signal when removing unallowed headers' , async ( ) => {
498- const controller = new AbortController ( ) ;
497+ it ( 'should transfer request body without teeing when removing unallowed headers' , async ( ) => {
499498 const req = new Request ( 'http://example.com' , {
500499 method : 'POST' ,
501500 body : 'test body' ,
502- signal : controller . signal ,
503501 headers : {
504502 'host' : 'example.com' ,
505503 'x-forwarded-host' : 'evil.com' ,
@@ -508,8 +506,24 @@ describe('Validation Utils', () => {
508506
509507 const secured = sanitizeRequestHeaders ( req , normalizeTrustProxyHeaders ( undefined ) ) ;
510508
509+ // In the Fetch specification, calling `request.clone()` tees the body stream and leaves
510+ // `req.bodyUsed` as `false`. Passing `req` directly to `new Request(req, ...)` transfers the
511+ // underlying stream without teeing, immediately marking `req.bodyUsed` as `true`.
511512 expect ( req . bodyUsed ) . toBeTrue ( ) ;
512513 expect ( await secured . text ( ) ) . toBe ( 'test body' ) ;
514+ } ) ;
515+
516+ it ( 'should preserve abort signal when removing unallowed headers' , ( ) => {
517+ const controller = new AbortController ( ) ;
518+ const req = new Request ( 'http://example.com' , {
519+ signal : controller . signal ,
520+ headers : {
521+ 'host' : 'example.com' ,
522+ 'x-forwarded-host' : 'evil.com' ,
523+ } ,
524+ } ) ;
525+
526+ const secured = sanitizeRequestHeaders ( req , normalizeTrustProxyHeaders ( undefined ) ) ;
513527
514528 controller . abort ( ) ;
515529 expect ( secured . signal . aborted ) . toBeTrue ( ) ;
0 commit comments