The Deno website has an example at: https://deno.land/manual@v1.36.4/runtime/http_server_apis#inspecting-the-incoming-request
I have shortened it to the following code:
const abortController = new AbortController();
Deno.addSignalListener('SIGINT', () => {
abortController.abort();
});
Deno.serve(
{
port:3000,
signal: abortController.signal
},
async (req) => {
if (req.body) {
try {
console.log('Start');
const body = await req.formData();
for (const key of body.keys()) {
console.log(key);
}
console.log('Never reached, when user abort.');
} catch {
// Will not be triggered on abort.
console.log('Error on await req.formData()');
}
}
return new Response("Hello, World!");
}
);
There is the note below it: Be aware that the req.text() call can fail if the user hangs up the connection before the body is fully received. Make sure to handle this case.
However, I have not found how to catch such a case. Can Deno detect that the connection has been terminated?
By the way, I added the "AbortHandler" for the test. If await req.formData()
passes successfully, the server can be terminated with Ctrl + C in the terminal (Linux Mint). If the user cancels the "upload", after the Ctrl + C command is still running a process until I close the terminal.
I think that is why Deno writes on the website, you have to catch this case. How to do this?
From Deno version 1.37 onwards, if a client closes the connection while the body is being consumed (using methods like .json
, .arrayBuffer
, .text
, etc.), the promise will now appropriately reject.
OLD ANSWER
You can test that case with the following snippet.
const body = new ReadableStream({
start(controller) {
controller.enqueue(new Uint8Array([97]));
}
});
const abort = new AbortController();
setTimeout(() => abort.abort(), 1500);
const res = await fetch('http://localhost:3000', {
body,
method: 'POST',
signal: abort.signal
});
console.log(res.status);
console.log(await res.text());
Unfortunately Deno does not detect connection drops, see: https://github.com/denoland/deno/issues/16246
Deno.serve(
{
port:3000,
},
async (req) => {
console.log(req.body);
if (req.body) {
try {
for await(const chunk of req.body) {
console.log(chunk);
}
console.log('Never reached, when user abort.');
} catch {
// Will not be triggered on abort.
console.log('never reached, bug in Deno');
}
}
return new Response("Hello, World!");
}
);
You can see that the first chunk is logged, but there's no error at all when the connection is dropped.
ReadableStream { locked: false }
Uint8Array(1) [ 97 ]
You can see more about this here: Deno connection close event