0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

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
This commit is contained in:
Levente Kurusa 2023-04-22 13:20:00 +02:00 committed by GitHub
parent 068228cb45
commit d137501a63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 2 deletions

View file

@ -351,6 +351,9 @@
"test-http-agent-getname.js", "test-http-agent-getname.js",
"test-http-client-get-url.js", "test-http-client-get-url.js",
"test-http-client-read-in-error.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-localaddress.js",
"test-http-outgoing-buffer.js", "test-http-outgoing-buffer.js",
"test-http-outgoing-internal-headernames-getter.js", "test-http-outgoing-internal-headernames-getter.js",

View file

@ -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 { constants, TCP } from "ext:deno_node/internal_binding/tcp_wrap.ts";
import * as denoHttp from "ext:deno_http/01_http.js"; import * as denoHttp from "ext:deno_http/01_http.js";
import * as httpRuntime from "ext:runtime/40_http.js"; import * as httpRuntime from "ext:runtime/40_http.js";
import { connResetException } from "ext:deno_node/internal/errors.ts";
enum STATUS_CODES { enum STATUS_CODES {
/** RFC 7231, 6.2.1 */ /** RFC 7231, 6.2.1 */
@ -259,16 +260,21 @@ class ClientRequest extends NodeWritable {
method: this.opts.method, method: this.opts.method,
client, client,
headers: this.opts.headers, headers: this.opts.headers,
signal: this.opts.signal ?? undefined,
}; };
const mayResponse = fetch(this._createUrlStrFromOptions(this.opts), opts) const mayResponse = fetch(this._createUrlStrFromOptions(this.opts), opts)
.catch((e) => { .catch((e) => {
if (e.message.includes("connection closed before message completed")) { if (e.message.includes("connection closed before message completed")) {
// Node.js seems ignoring this error // 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 { } else {
this.emit("error", e); this.emit("error", e);
} }
return undefined; return undefined;
}); });
const res = new IncomingMessageForClient( const res = new IncomingMessageForClient(
await mayResponse, await mayResponse,
this._createSocket(), this._createSocket(),
@ -279,6 +285,10 @@ class ClientRequest extends NodeWritable {
client.close(); client.close();
}); });
} }
if (this.opts.timeout != undefined) {
clearTimeout(this.opts.timeout);
this.opts.timeout = undefined;
}
this.cb?.(res); this.cb?.(res);
} }
@ -340,8 +350,19 @@ class ClientRequest extends NodeWritable {
}${path}`; }${path}`;
} }
setTimeout() { setTimeout(timeout: number, callback?: () => void) {
console.log("not implemented: ClientRequest.setTimeout"); const controller = new AbortController();
this.opts.signal = controller.signal;
this.opts.timeout = setTimeout(() => {
controller.abort();
this.emit("timeout");
if (callback !== undefined) {
callback();
}
}, timeout);
} }
} }