summaryrefslogtreecommitdiff
path: root/std/http/server.ts
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2020-03-19 16:04:26 +0100
committerGitHub <noreply@github.com>2020-03-19 16:04:26 +0100
commit3ef34673c9b92aa3c54dfccb37c06b82d6fb3eab (patch)
treecd0502d7ab1dd45b2e8dadd911916a18507fcda5 /std/http/server.ts
parent2f3de4b4252b933ac1161ba099feaed9103ab149 (diff)
std(http/server): close open connections on server close (#3679)
Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections. This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
Diffstat (limited to 'std/http/server.ts')
-rw-r--r--std/http/server.ts31
1 files changed, 30 insertions, 1 deletions
diff --git a/std/http/server.ts b/std/http/server.ts
index 34b17cc26..72bd1e5f3 100644
--- a/std/http/server.ts
+++ b/std/http/server.ts
@@ -124,12 +124,23 @@ export class ServerRequest {
export class Server implements AsyncIterable<ServerRequest> {
private closing = false;
+ private connections: Conn[] = [];
constructor(public listener: Listener) {}
close(): void {
this.closing = true;
this.listener.close();
+ for (const conn of this.connections) {
+ try {
+ conn.close();
+ } catch (e) {
+ // Connection might have been already closed
+ if (!(e instanceof Deno.errors.BadResource)) {
+ throw e;
+ }
+ }
+ }
}
// Yields all HTTP requests on a single TCP connection.
@@ -162,6 +173,7 @@ export class Server implements AsyncIterable<ServerRequest> {
// Something bad happened during response.
// (likely other side closed during pipelined req)
// req.done implies this connection already closed, so we can just return.
+ this.untrackConnection(req.conn);
return;
}
// Consume unread body and trailers if receiver didn't consume those data
@@ -186,7 +198,23 @@ export class Server implements AsyncIterable<ServerRequest> {
// TODO(ry): send a back a HTTP 503 Service Unavailable status.
}
- conn.close();
+ this.untrackConnection(conn);
+ try {
+ conn.close();
+ } catch (e) {
+ // might have been already closed
+ }
+ }
+
+ private trackConnection(conn: Conn): void {
+ this.connections.push(conn);
+ }
+
+ private untrackConnection(conn: Conn): void {
+ const index = this.connections.indexOf(conn);
+ if (index !== -1) {
+ this.connections.splice(index, 1);
+ }
}
// Accepts a new TCP connection and yields all HTTP requests that arrive on
@@ -207,6 +235,7 @@ export class Server implements AsyncIterable<ServerRequest> {
}
throw error;
}
+ this.trackConnection(conn);
// Try to accept another connection and add it to the multiplexer.
mux.add(this.acceptConnAndIterateHttpRequests(mux));
// Yield the requests that arrive on the just-accepted connection.