summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLevente Kurusa <lkurusa@kernelstuff.org>2023-04-22 13:20:00 +0200
committerGitHub <noreply@github.com>2023-04-22 13:20:00 +0200
commitd137501a639cb315772866f6775fcd9f43e28f5b (patch)
treedb2458400416f26f57138b8b90079bf4f1e098f6
parent068228cb454d14a6f5943061a5a6569b9e395e23 (diff)
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
-rw-r--r--cli/tests/node_compat/config.jsonc3
-rw-r--r--ext/node/polyfills/http.ts25
2 files changed, 26 insertions, 2 deletions
diff --git a/cli/tests/node_compat/config.jsonc b/cli/tests/node_compat/config.jsonc
index ddbdf458f..ce1cf3a08 100644
--- a/cli/tests/node_compat/config.jsonc
+++ b/cli/tests/node_compat/config.jsonc
@@ -351,6 +351,9 @@
"test-http-agent-getname.js",
"test-http-client-get-url.js",
"test-http-client-read-in-error.js",
+ // TODO(lev): ClientRequest.socket is not polyfilled so this test keeps
+ // failing
+ //"test-http-client-set-timeout.js",
"test-http-localaddress.js",
"test-http-outgoing-buffer.js",
"test-http-outgoing-internal-headernames-getter.js",
diff --git a/ext/node/polyfills/http.ts b/ext/node/polyfills/http.ts
index 9104183ca..d8ec7650b 100644
--- a/ext/node/polyfills/http.ts
+++ b/ext/node/polyfills/http.ts
@@ -18,6 +18,7 @@ import { urlToHttpOptions } from "ext:deno_node/internal/url.ts";
import { constants, TCP } from "ext:deno_node/internal_binding/tcp_wrap.ts";
import * as denoHttp from "ext:deno_http/01_http.js";
import * as httpRuntime from "ext:runtime/40_http.js";
+import { connResetException } from "ext:deno_node/internal/errors.ts";
enum STATUS_CODES {
/** RFC 7231, 6.2.1 */
@@ -259,16 +260,21 @@ class ClientRequest extends NodeWritable {
method: this.opts.method,
client,
headers: this.opts.headers,
+ signal: this.opts.signal ?? undefined,
};
const mayResponse = fetch(this._createUrlStrFromOptions(this.opts), opts)
.catch((e) => {
if (e.message.includes("connection closed before message completed")) {
// Node.js seems ignoring this error
+ } else if (e.message.includes("The signal has been aborted")) {
+ // Remap this error
+ this.emit("error", connResetException("socket hang up"));
} else {
this.emit("error", e);
}
return undefined;
});
+
const res = new IncomingMessageForClient(
await mayResponse,
this._createSocket(),
@@ -279,6 +285,10 @@ class ClientRequest extends NodeWritable {
client.close();
});
}
+ if (this.opts.timeout != undefined) {
+ clearTimeout(this.opts.timeout);
+ this.opts.timeout = undefined;
+ }
this.cb?.(res);
}
@@ -340,8 +350,19 @@ class ClientRequest extends NodeWritable {
}${path}`;
}
- setTimeout() {
- console.log("not implemented: ClientRequest.setTimeout");
+ setTimeout(timeout: number, callback?: () => void) {
+ const controller = new AbortController();
+ this.opts.signal = controller.signal;
+
+ this.opts.timeout = setTimeout(() => {
+ controller.abort();
+
+ this.emit("timeout");
+
+ if (callback !== undefined) {
+ callback();
+ }
+ }, timeout);
}
}