Skip to content

Commit d137501

Browse files
authored
feat(node/http): implement ClientRequest.setTimeout() (#18783)
- implement setTimeout with matching semantics of Node - add the test from Node but leave it turned off because ClientRequest has no underlying socket
1 parent 068228c commit d137501

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

cli/tests/node_compat/config.jsonc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@
351351
"test-http-agent-getname.js",
352352
"test-http-client-get-url.js",
353353
"test-http-client-read-in-error.js",
354+
// TODO(lev): ClientRequest.socket is not polyfilled so this test keeps
355+
// failing
356+
//"test-http-client-set-timeout.js",
354357
"test-http-localaddress.js",
355358
"test-http-outgoing-buffer.js",
356359
"test-http-outgoing-internal-headernames-getter.js",

ext/node/polyfills/http.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { urlToHttpOptions } from "ext:deno_node/internal/url.ts";
1818
import { constants, TCP } from "ext:deno_node/internal_binding/tcp_wrap.ts";
1919
import * as denoHttp from "ext:deno_http/01_http.js";
2020
import * as httpRuntime from "ext:runtime/40_http.js";
21+
import { connResetException } from "ext:deno_node/internal/errors.ts";
2122

2223
enum STATUS_CODES {
2324
/** RFC 7231, 6.2.1 */
@@ -259,16 +260,21 @@ class ClientRequest extends NodeWritable {
259260
method: this.opts.method,
260261
client,
261262
headers: this.opts.headers,
263+
signal: this.opts.signal ?? undefined,
262264
};
263265
const mayResponse = fetch(this._createUrlStrFromOptions(this.opts), opts)
264266
.catch((e) => {
265267
if (e.message.includes("connection closed before message completed")) {
266268
// Node.js seems ignoring this error
269+
} else if (e.message.includes("The signal has been aborted")) {
270+
// Remap this error
271+
this.emit("error", connResetException("socket hang up"));
267272
} else {
268273
this.emit("error", e);
269274
}
270275
return undefined;
271276
});
277+
272278
const res = new IncomingMessageForClient(
273279
await mayResponse,
274280
this._createSocket(),
@@ -279,6 +285,10 @@ class ClientRequest extends NodeWritable {
279285
client.close();
280286
});
281287
}
288+
if (this.opts.timeout != undefined) {
289+
clearTimeout(this.opts.timeout);
290+
this.opts.timeout = undefined;
291+
}
282292
this.cb?.(res);
283293
}
284294

@@ -340,8 +350,19 @@ class ClientRequest extends NodeWritable {
340350
}${path}`;
341351
}
342352

343-
setTimeout() {
344-
console.log("not implemented: ClientRequest.setTimeout");
353+
setTimeout(timeout: number, callback?: () => void) {
354+
const controller = new AbortController();
355+
this.opts.signal = controller.signal;
356+
357+
this.opts.timeout = setTimeout(() => {
358+
controller.abort();
359+
360+
this.emit("timeout");
361+
362+
if (callback !== undefined) {
363+
callback();
364+
}
365+
}, timeout);
345366
}
346367
}
347368

0 commit comments

Comments
 (0)