File tree Expand file tree Collapse file tree 4 files changed +36
-4
lines changed
Expand file tree Collapse file tree 4 files changed +36
-4
lines changed Original file line number Diff line number Diff line change 11import type { IncomingMessage , ServerResponse , OutgoingHttpHeaders } from 'node:http'
22import type { Http2ServerRequest , Http2ServerResponse } from 'node:http2'
33import {
4- getAbortController ,
4+ abortControllerKey ,
55 newRequest ,
66 Request as LightweightRequest ,
77 toRequestError ,
@@ -187,10 +187,15 @@ export const getRequestListener = (
187187
188188 // Detect if request was aborted.
189189 outgoing . on ( 'close' , ( ) => {
190+ const abortController = req [ abortControllerKey ] as AbortController | undefined
191+ if ( ! abortController ) {
192+ return
193+ }
194+
190195 if ( incoming . errored ) {
191- req [ getAbortController ] ( ) . abort ( incoming . errored . toString ( ) )
196+ req [ abortControllerKey ] . abort ( incoming . errored . toString ( ) )
192197 } else if ( ! outgoing . writableFinished ) {
193- req [ getAbortController ] ( ) . abort ( 'Client connection prematurely closed.' )
198+ req [ abortControllerKey ] . abort ( 'Client connection prematurely closed.' )
194199 }
195200 } )
196201
Original file line number Diff line number Diff line change @@ -96,7 +96,7 @@ const getRequestCache = Symbol('getRequestCache')
9696const requestCache = Symbol ( 'requestCache' )
9797const incomingKey = Symbol ( 'incomingKey' )
9898const urlKey = Symbol ( 'urlKey' )
99- const abortControllerKey = Symbol ( 'abortControllerKey' )
99+ export const abortControllerKey = Symbol ( 'abortControllerKey' )
100100export const getAbortController = Symbol ( 'getAbortController' )
101101
102102const requestPrototype : Record < string | symbol , any > = {
Original file line number Diff line number Diff line change @@ -274,6 +274,17 @@ describe('Abort request', () => {
274274 }
275275 }
276276 )
277+
278+ it ( 'should handle request abort without requestCache' , async ( ) => {
279+ const fetchCallback = async ( ) => {
280+ // NOTE: we don't req.signal
281+ await new Promise ( ( ) => { } ) // never resolve
282+ }
283+ const requestListener = getRequestListener ( fetchCallback )
284+ const server = createServer ( requestListener )
285+ const req = request ( server ) . post ( '/abort' ) . timeout ( { deadline : 1 } )
286+ await expect ( req ) . rejects . toHaveProperty ( 'timeout' )
287+ } )
277288} )
278289
279290describe ( 'overrideGlobalObjects' , ( ) => {
Original file line number Diff line number Diff line change 55 Request as LightweightRequest ,
66 GlobalRequest ,
77 getAbortController ,
8+ abortControllerKey ,
89 RequestError ,
910} from '../src/request'
1011
@@ -81,6 +82,21 @@ describe('Request', () => {
8182 expect ( z ) . not . toBe ( y )
8283 } )
8384
85+ it ( 'should be able to safely check if an AbortController has been initialized by referencing the abortControllerKey' , async ( ) => {
86+ const req = newRequest ( {
87+ headers : {
88+ host : 'localhost' ,
89+ } ,
90+ rawHeaders : [ 'host' , 'localhost' ] ,
91+ url : '/foo.txt' ,
92+ } as IncomingMessage )
93+
94+ expect ( req [ abortControllerKey ] ) . toBeUndefined ( ) // not initialized, do not initialize internal request object automatically
95+
96+ expect ( req [ getAbortController ] ( ) ) . toBeDefined ( )
97+ expect ( req [ abortControllerKey ] ) . toBeDefined ( ) // initialized
98+ } )
99+
84100 it ( 'Should throw error if host header contains path' , async ( ) => {
85101 expect ( ( ) => {
86102 newRequest ( {
You can’t perform that action at this time.
0 commit comments