mirror of
https://github.com/denoland/deno.git
synced 2024-10-30 09:08:00 -04:00
Ignore error of writing responses to aborted requests (denoland/deno_std#546)
Original: 826deb1012
This commit is contained in:
parent
ad6360edf9
commit
44efefbda6
6 changed files with 78 additions and 10 deletions
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||||
import { serve, ServerRequest } from "./server.ts";
|
import { serve, ServerRequest } from "./server.ts";
|
||||||
|
import { delay } from "../util/async.ts";
|
||||||
|
|
||||||
const addr = Deno.args[1] || "127.0.0.1:4501";
|
const addr = Deno.args[1] || "127.0.0.1:4501";
|
||||||
const server = serve(addr);
|
const server = serve(addr);
|
||||||
|
@ -7,12 +8,8 @@ const server = serve(addr);
|
||||||
const body = new TextEncoder().encode("Hello 1\n");
|
const body = new TextEncoder().encode("Hello 1\n");
|
||||||
const body4 = new TextEncoder().encode("World 4\n");
|
const body4 = new TextEncoder().encode("World 4\n");
|
||||||
|
|
||||||
function sleep(ms: number): Promise<void> {
|
|
||||||
return new Promise((res): number => setTimeout(res, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function delayedRespond(request: ServerRequest): Promise<void> {
|
async function delayedRespond(request: ServerRequest): Promise<void> {
|
||||||
await sleep(3000);
|
await delay(3000);
|
||||||
await request.respond({ status: 200, body });
|
await request.respond({ status: 200, body });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ async function startServer(): Promise<void> {
|
||||||
args: ["deno", "run", "-A", "http/racing_server.ts"],
|
args: ["deno", "run", "-A", "http/racing_server.ts"],
|
||||||
stdout: "piped"
|
stdout: "piped"
|
||||||
});
|
});
|
||||||
// Once fileServer is ready it will write to its stdout.
|
// Once racing server is ready it will write to its stdout.
|
||||||
const r = new TextProtoReader(new BufReader(server.stdout!));
|
const r = new TextProtoReader(new BufReader(server.stdout!));
|
||||||
const s = await r.readLine();
|
const s = await r.readLine();
|
||||||
assert(s !== Deno.EOF && s.includes("Racing server listening..."));
|
assert(s !== Deno.EOF && s.includes("Racing server listening..."));
|
||||||
|
|
|
@ -342,10 +342,15 @@ export class Server implements AsyncIterable<ServerRequest> {
|
||||||
// The connection was gracefully closed.
|
// The connection was gracefully closed.
|
||||||
} else if (err) {
|
} else if (err) {
|
||||||
// An error was thrown while parsing request headers.
|
// An error was thrown while parsing request headers.
|
||||||
await writeResponse(req!.w, {
|
try {
|
||||||
status: 400,
|
await writeResponse(req!.w, {
|
||||||
body: new TextEncoder().encode(`${err.message}\r\n\r\n`)
|
status: 400,
|
||||||
});
|
body: new TextEncoder().encode(`${err.message}\r\n\r\n`)
|
||||||
|
});
|
||||||
|
} catch (_) {
|
||||||
|
// The connection is destroyed.
|
||||||
|
// Ignores the error.
|
||||||
|
}
|
||||||
} else if (this.closing) {
|
} else if (this.closing) {
|
||||||
// There are more requests incoming but the server is closing.
|
// There are more requests incoming but the server is closing.
|
||||||
// TODO(ry): send a back a HTTP 503 Service Unavailable status.
|
// TODO(ry): send a back a HTTP 503 Service Unavailable status.
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
// https://github.com/golang/go/blob/master/src/net/http/responsewrite_test.go
|
// https://github.com/golang/go/blob/master/src/net/http/responsewrite_test.go
|
||||||
|
|
||||||
const { Buffer } = Deno;
|
const { Buffer } = Deno;
|
||||||
|
import { TextProtoReader } from "../textproto/mod.ts";
|
||||||
import { test, runIfMain } from "../testing/mod.ts";
|
import { test, runIfMain } from "../testing/mod.ts";
|
||||||
import { assert, assertEquals, assertNotEquals } from "../testing/asserts.ts";
|
import { assert, assertEquals, assertNotEquals } from "../testing/asserts.ts";
|
||||||
import {
|
import {
|
||||||
|
@ -15,6 +16,7 @@ import {
|
||||||
readRequest,
|
readRequest,
|
||||||
parseHTTPVersion
|
parseHTTPVersion
|
||||||
} from "./server.ts";
|
} from "./server.ts";
|
||||||
|
import { delay } from "../util/async.ts";
|
||||||
import {
|
import {
|
||||||
BufReader,
|
BufReader,
|
||||||
BufWriter,
|
BufWriter,
|
||||||
|
@ -456,4 +458,47 @@ test({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test({
|
||||||
|
name: "[http] destroyed connection",
|
||||||
|
async fn(): Promise<void> {
|
||||||
|
// TODO: don't skip on windows when process.kill is implemented on windows.
|
||||||
|
if (Deno.build.os === "win") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Runs a simple server as another process
|
||||||
|
const p = Deno.run({
|
||||||
|
args: [Deno.execPath, "http/testdata/simple_server.ts", "--allow-net"],
|
||||||
|
stdout: "piped"
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const r = new TextProtoReader(new BufReader(p.stdout!));
|
||||||
|
const s = await r.readLine();
|
||||||
|
assert(s !== Deno.EOF && s.includes("server listening"));
|
||||||
|
|
||||||
|
let serverIsRunning = true;
|
||||||
|
p.status().then(
|
||||||
|
(): void => {
|
||||||
|
serverIsRunning = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await delay(100);
|
||||||
|
|
||||||
|
// Reqeusts to the server and immediately closes the connection
|
||||||
|
const conn = await Deno.dial("tcp", "127.0.0.1:4502");
|
||||||
|
await conn.write(new TextEncoder().encode("GET / HTTP/1.0\n\n"));
|
||||||
|
conn.close();
|
||||||
|
|
||||||
|
// Waits for the server to handle the above (broken) request
|
||||||
|
await delay(100);
|
||||||
|
|
||||||
|
assert(serverIsRunning);
|
||||||
|
} finally {
|
||||||
|
// Stops the sever.
|
||||||
|
p.kill(Deno.Signal.SIGINT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
runIfMain(import.meta);
|
runIfMain(import.meta);
|
||||||
|
|
11
http/testdata/simple_server.ts
vendored
Normal file
11
http/testdata/simple_server.ts
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// This is an example of a server that responds with an empty body
|
||||||
|
import { serve } from "../server.ts";
|
||||||
|
|
||||||
|
window.onload = async function main() {
|
||||||
|
const addr = "0.0.0.0:4502";
|
||||||
|
console.log(`Simple server listening on ${addr}`);
|
||||||
|
for await (let req of serve(addr)) {
|
||||||
|
req.respond({});
|
||||||
|
}
|
||||||
|
}
|
|
@ -108,3 +108,13 @@ export async function collectUint8Arrays(
|
||||||
}
|
}
|
||||||
return collected;
|
return collected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delays the given milliseconds and resolves.
|
||||||
|
export function delay(ms: number): Promise<void> {
|
||||||
|
return new Promise(
|
||||||
|
(res): number =>
|
||||||
|
setTimeout((): void => {
|
||||||
|
res();
|
||||||
|
}, ms)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue