mirror of
https://github.com/denoland/deno.git
synced 2024-12-12 02:27:46 -05:00
wip: abort request when destroy() is invoked
Yoshiya Hinosawa <stibium121@gmail.com>
This commit is contained in:
parent
122cefaed4
commit
2c60a4352d
2 changed files with 64 additions and 14 deletions
|
@ -144,6 +144,17 @@ class FakeSocket extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
function emitErrorEvent(request, error) {
|
||||
// TODO: enable this when we implement dc for ClientRequest
|
||||
// if (onClientRequestErrorChannel.hasSubscribers) {
|
||||
// onClientRequestErrorChannel.publish({
|
||||
// request,
|
||||
// error,
|
||||
// });
|
||||
// }
|
||||
request.emit("error", error);
|
||||
}
|
||||
|
||||
/** ClientRequest represents the http(s) request from the client */
|
||||
class ClientRequest extends OutgoingMessage {
|
||||
defaultProtocol = "http:";
|
||||
|
@ -566,9 +577,40 @@ class ClientRequest extends OutgoingMessage {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
// TODO(bartlomieju): handle error
|
||||
onSocket(socket, _err) {
|
||||
onSocket(socket, err) {
|
||||
nextTick(() => {
|
||||
const req = this;
|
||||
if (req.destroyed || err) {
|
||||
req.destroyed = true;
|
||||
|
||||
function _destroy(req, err) {
|
||||
if (!req.aborted && !err) {
|
||||
err = new connResetException("socket hang up");
|
||||
}
|
||||
if (err) {
|
||||
emitErrorEvent(req, err);
|
||||
}
|
||||
req._closed = true;
|
||||
req.emit("close");
|
||||
}
|
||||
|
||||
if (socket) {
|
||||
if (!err && req.agent && !socket.destroyed) {
|
||||
socket.emit("free");
|
||||
} else {
|
||||
finished(socket.destroy(err || req[kError]), (er) => {
|
||||
if (er?.code === "ERR_STREAM_PREMATURE_CLOSE") {
|
||||
er = null;
|
||||
}
|
||||
_destroy(req, er || err);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_destroy(req, err || req[kError]);
|
||||
} else {
|
||||
// Note: this code is specific to deno to initiate a request.
|
||||
socket.on("connect", () => {
|
||||
// Flush the internal buffers once socket is ready.
|
||||
// Note: the order is important, as the headers flush
|
||||
|
@ -580,6 +622,9 @@ class ClientRequest extends OutgoingMessage {
|
|||
});
|
||||
this.socket = socket;
|
||||
this.emit("socket", socket);
|
||||
// tickOnSocket(req, socket);
|
||||
// req._flush();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -501,6 +501,7 @@ Deno.test("[node/http] send request with non-chunked body", {
|
|||
socket.destroy();
|
||||
socket.setTimeout(100);
|
||||
});
|
||||
// this data can be huge and can't be buffered
|
||||
req.write("hello ");
|
||||
req.write("world");
|
||||
req.end();
|
||||
|
@ -1037,11 +1038,15 @@ Deno.test("[node/http] destroyed requests should not be sent", {
|
|||
receivedRequest = true;
|
||||
return new Response(null);
|
||||
});
|
||||
let receivedError = null
|
||||
const request = http.request(`http://localhost:${server.addr.port}/`);
|
||||
request.destroy();
|
||||
request.end("hello");
|
||||
|
||||
request.on("error", (err) => {
|
||||
receivedError = err;
|
||||
});
|
||||
await new Promise((r) => setTimeout(r, 500));
|
||||
assert(receivedError!.toString().contains("socket hung up"));
|
||||
assertEquals(receivedRequest, false);
|
||||
await server.shutdown();
|
||||
});
|
||||
|
@ -1353,7 +1358,7 @@ Deno.test("[node/http] client closing a streaming response doesn't terminate ser
|
|||
clearInterval(interval!);
|
||||
});
|
||||
|
||||
Deno.test("[node/http] client closing a streaming request doesn't terminate server", async () => {
|
||||
Deno.test("[node/http] client closing a streaming request doesn't terminate server", { ignore: true }, async () => {
|
||||
let interval: number;
|
||||
let uploadedData = "";
|
||||
let requestError: Error | null = null;
|
||||
|
|
Loading…
Reference in a new issue