Skip to content

Commit f43a466

Browse files
committed
Added timeout tests
1 parent 3cacefe commit f43a466

File tree

7 files changed

+334
-173
lines changed

7 files changed

+334
-173
lines changed

lib/http2/http2Agent.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,10 @@ export class Http2Agent extends EventEmitter {
6161

6262
connection.once('connect', () => {
6363
// start the timeout only when the connection is in ready state, otherwise the connection closes early
64-
connection.setTimeout(options?.timeout ?? 30000, () => {
64+
connection.setTimeout(options?.timeout ?? 5000, () => {
6565
// @ts-expect-error
6666
if (connection.refCount === 0) {
67-
connection.close(() => {
68-
connection.destroy()
69-
})
67+
connection.close()
7068
delete this.connections[name]
7169
}
7270
})
@@ -157,5 +155,4 @@ export class Http2Agent extends EventEmitter {
157155
}
158156
}
159157

160-
// export const
161158
export const globalAgent = new Http2Agent({})

lib/http2/request.ts

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import * as http from 'http'
33
import * as http2 from 'http2'
44
import { EventEmitter } from 'events'
55
import type * as https from 'https'
6-
import { type Http2Agent, HTTP2ClientRequestOptions, globalAgent } from './http2Agent'
6+
import { HTTP2ClientRequestOptions, globalAgent } from './http2Agent'
7+
import * as tls from "tls";
78

89
export interface RequestOptions extends Omit<https.RequestOptions, 'agent' | 'createConnection' | 'protocol'> {
910
agent?: {
@@ -22,6 +23,8 @@ export class Http2Request extends EventEmitter {
2223
stream: http2.ClientHttp2Stream
2324
private readonly _client: http2.ClientHttp2Session
2425
requestHeaders: http2.OutgoingHttpHeaders = {};
26+
connectionHeaders = ['connection', 'host']
27+
socket: tls.TLSSocket
2528

2629
constructor (options: RequestOptions) {
2730
super()
@@ -51,12 +54,16 @@ export class Http2Request extends EventEmitter {
5154
[http2.constants.HTTP2_HEADER_AUTHORITY]: newoptions.host,
5255
...headers
5356
}
57+
this.socket = this._client.socket as tls.TLSSocket;
5458

55-
this.requestHeaders = Object.fromEntries(Object.entries(this.requestHeaders).filter(([key]) => !(options.blacklistHeaders ?? []).includes(key.toLowerCase())))
56-
57-
// Remove blacklisted http/1 headers
58-
delete this.requestHeaders.Connection
59-
delete this.requestHeaders.Host
59+
this.requestHeaders = Object.fromEntries(
60+
Object.entries(this.requestHeaders)
61+
.map(([key, value])=>([key.toLowerCase(), value]))
62+
// @ts-ignore
63+
.filter(([key]) => !(options.blacklistHeaders ?? []).includes(key))
64+
// @ts-ignore
65+
.filter(([key])=> !this.connectionHeaders.includes(key))
66+
)
6067

6168
this.stream = this._client.request(this.requestHeaders)
6269
this.registerListeners()
@@ -80,20 +87,14 @@ export class Http2Request extends EventEmitter {
8087
this.stream.on('close', (...args) => {
8188
this.emit('close', ...args)
8289
})
83-
this.stream.on('socket', () => this.emit('socket', this._client.socket))
90+
8491
this._client.once('error', this.onError)
8592
this.stream.on('response', (response) => {
8693
this.emit('response', new ResponseProxy(response, this))
87-
88-
// HTTP response events returns a readable stream which has data event that consumers listen on to get the response body
89-
// With HTTP2 the response object is a header object and the body is streamed via the data event.
90-
// To maintain compatibilty with the HTTP API, we need to emit the data after the response event is emitted
91-
// And wait for the data listeners to be attached
9294
})
93-
//
95+
9496
this.stream.on('end', () => {
9597
this._client.off('error', this.onError)
96-
this.emit('end')
9798
})
9899
}
99100

@@ -120,7 +121,7 @@ export class Http2Request extends EventEmitter {
120121

121122
on (eventName: string | symbol, listener: (...args: any[]) => void): this {
122123
if (eventName === 'socket') {
123-
listener(this._client.socket)
124+
listener(this.socket)
124125
return this
125126
}
126127

@@ -164,7 +165,6 @@ class ResponseProxy extends EventEmitter {
164165
}
165166

166167
registerRequestListeners () {
167-
this.req.stream.on('end', () => this.emit('end'))
168168
this.req.stream.on('error', (e) => this.emit('error', e))
169169
this.req.stream.on('close', () => {
170170
this.emit('close')
@@ -183,6 +183,10 @@ class ResponseProxy extends EventEmitter {
183183
this.emit('data', chunk)
184184
})
185185
}
186+
187+
if(eventName === 'end'){
188+
this.req.stream.on('end', listener)
189+
}
186190
return this
187191
}
188192

@@ -209,6 +213,7 @@ class ResponseProxy extends EventEmitter {
209213
}
210214

211215
pause () {
216+
console.log(performance.now(), 'pausing')
212217
this.req.stream.pause()
213218
}
214219

@@ -223,4 +228,8 @@ class ResponseProxy extends EventEmitter {
223228
setEncoding (encoding: BufferEncoding) {
224229
this.req.stream.setEncoding(encoding)
225230
}
231+
232+
destroy(){
233+
this.req.stream.destroy();
234+
}
226235
}

lib/redirect.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,10 @@ Redirect.prototype.onResponse = function (response) {
212212

213213
options.protocolVersion = this.request.protocolVersion
214214

215-
request.init(options)
215+
// Wait for request to end before firing redirect request
216+
request.once('finish', () => {
217+
request.init(options);
218+
})
216219

217220
return true
218221
}

request.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ Request.prototype.start = function () {
922922
// at the _exact_ same time, they should be close enough to be able to calculate
923923
// high-resolution, monotonically non-decreasing timestamps relative to startTime.
924924
var startTime = new Date().getTime()
925-
var startTimeNow = now()
925+
var startTimeNow = performance.now()
926926
}
927927

928928
if (self._aborted) {
@@ -1212,13 +1212,13 @@ Request.prototype.onRequestResponse = function (response) {
12121212
var self = this
12131213

12141214
if (self.timing) {
1215-
self.timings.response = now() - self.startTimeNow
1215+
self.timings.response = performance.now() - self.startTimeNow
12161216
}
12171217

12181218
debug('onRequestResponse', self.uri.href, response.statusCode, response.headers)
12191219
response.on('end', function () {
12201220
if (self.timing) {
1221-
self.timings.end = now() - self.startTimeNow
1221+
self.timings.end = performance.now() - self.startTimeNow
12221222
response.timingStart = self.startTime
12231223
response.timingStartTimer = self.startTimeNow
12241224

@@ -1269,6 +1269,10 @@ Request.prototype.onRequestResponse = function (response) {
12691269
}
12701270

12711271
debug('response end', self.uri.href, response.statusCode, response.headers)
1272+
1273+
// Only consumed by redirects for now, in order to wait for current request to finish processing and then move onto
1274+
// the next one
1275+
self.emit('finish')
12721276
})
12731277

12741278
if (self._aborted) {

0 commit comments

Comments
 (0)