2
2
3
3
const assert = require ( 'node:assert' )
4
4
const { Readable } = require ( './readable' )
5
- const { InvalidArgumentError } = require ( '../core/errors' )
5
+ const { InvalidArgumentError, RequestAbortedError } = require ( '../core/errors' )
6
6
const util = require ( '../core/util' )
7
7
const { getResolveErrorBodyCallback } = require ( './util' )
8
8
const { AsyncResource } = require ( 'node:async_hooks' )
9
- const { addSignal, removeSignal } = require ( './abort-signal' )
10
9
11
10
class RequestHandler extends AsyncResource {
12
11
constructor ( opts , callback ) {
@@ -56,14 +55,33 @@ class RequestHandler extends AsyncResource {
56
55
this . onInfo = onInfo || null
57
56
this . throwOnError = throwOnError
58
57
this . highWaterMark = highWaterMark
58
+ this . signal = signal
59
+ this . reason = null
60
+ this . removeAbortListener = null
59
61
60
62
if ( util . isStream ( body ) ) {
61
63
body . on ( 'error' , ( err ) => {
62
64
this . onError ( err )
63
65
} )
64
66
}
65
67
66
- addSignal ( this , signal )
68
+ if ( this . signal ) {
69
+ if ( this . signal . aborted ) {
70
+ this . reason = this . signal . reason ?? new RequestAbortedError ( )
71
+ } else {
72
+ this . removeAbortListener = util . addAbortListener ( this . signal , ( ) => {
73
+ this . removeAbortListener ?. ( )
74
+ this . removeAbortListener = null
75
+
76
+ this . reason = this . signal . reason ?? new RequestAbortedError ( )
77
+ if ( this . res ) {
78
+ util . destroy ( this . res , this . reason )
79
+ } else if ( this . abort ) {
80
+ this . abort ( this . reason )
81
+ }
82
+ } )
83
+ }
84
+ }
67
85
}
68
86
69
87
onConnect ( abort , context ) {
@@ -95,6 +113,13 @@ class RequestHandler extends AsyncResource {
95
113
const contentLength = parsedHeaders [ 'content-length' ]
96
114
const body = new Readable ( { resume, abort, contentType, contentLength, highWaterMark } )
97
115
116
+ if ( this . removeAbortListener ) {
117
+ // TODO (fix): 'close' is sufficient but breaks tests.
118
+ body
119
+ . on ( 'end' , this . removeAbortListener )
120
+ . on ( 'error' , this . removeAbortListener )
121
+ }
122
+
98
123
this . callback = null
99
124
this . res = body
100
125
if ( callback !== null ) {
@@ -123,8 +148,6 @@ class RequestHandler extends AsyncResource {
123
148
onComplete ( trailers ) {
124
149
const { res } = this
125
150
126
- removeSignal ( this )
127
-
128
151
util . parseHeaders ( trailers , this . trailers )
129
152
130
153
res . push ( null )
@@ -133,7 +156,8 @@ class RequestHandler extends AsyncResource {
133
156
onError ( err ) {
134
157
const { res, callback, body, opaque } = this
135
158
136
- removeSignal ( this )
159
+ this . removeAbortListener ?. ( )
160
+ this . removeAbortListener = null
137
161
138
162
if ( callback ) {
139
163
// TODO: Does this need queueMicrotask?
0 commit comments