summaryrefslogtreecommitdiff
path: root/http
diff options
context:
space:
mode:
authorYusuke Sakurai <kerokerokerop@gmail.com>2019-02-11 08:45:24 +0900
committerRyan Dahl <ry@tinyclouds.org>2019-02-10 18:45:24 -0500
commited20bda6ec324b8143c6210024647d2692232c26 (patch)
treebff7ec730f156d1f4b7041cfe1e2651f513349c3 /http
parent52e047138a32e8366369737dc54198f1a5baa1cb (diff)
refactor: make acceptWebSocket independent from ServerRequest (denoland/deno_std#178)
Original: https://github.com/denoland/deno_std/commit/88ddd5677dec9a8281c4d86ba27b0c9047189740
Diffstat (limited to 'http')
-rw-r--r--http/server.ts104
-rw-r--r--http/server_test.ts11
2 files changed, 59 insertions, 56 deletions
diff --git a/http/server.ts b/http/server.ts
index 723a34523..400171fc5 100644
--- a/http/server.ts
+++ b/http/server.ts
@@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-import { listen, Conn, toAsyncIterator, Reader, copy } from "deno";
+import { listen, Conn, toAsyncIterator, Reader, Writer, copy } from "deno";
import { BufReader, BufState, BufWriter } from "../io/bufio.ts";
import { TextProtoReader } from "../textproto/mod.ts";
import { STATUS_TEXT } from "./http_status.ts";
@@ -40,6 +40,7 @@ interface ServeEnv {
function serveConn(env: ServeEnv, conn: Conn, bufr?: BufReader) {
readRequest(conn, bufr).then(maybeHandleReq.bind(null, env, conn));
}
+
function maybeHandleReq(env: ServeEnv, conn: Conn, maybeReq: any) {
const [req, _err] = maybeReq;
if (_err) {
@@ -210,68 +211,75 @@ export class ServerRequest {
return readAllIterator(this.bodyStream());
}
- private async _streamBody(body: Reader, bodyLength: number) {
- const n = await copy(this.w, body);
- assert(n == bodyLength);
+ async respond(r: Response): Promise<void> {
+ return writeResponse(this.w, r);
}
+}
- private async _streamChunkedBody(body: Reader) {
- const encoder = new TextEncoder();
-
- for await (const chunk of toAsyncIterator(body)) {
- const start = encoder.encode(`${chunk.byteLength.toString(16)}\r\n`);
- const end = encoder.encode("\r\n");
- await this.w.write(start);
- await this.w.write(chunk);
- await this.w.write(end);
- }
-
- const endChunk = encoder.encode("0\r\n\r\n");
- await this.w.write(endChunk);
+function bufWriter(w: Writer): BufWriter {
+ if (w instanceof BufWriter) {
+ return w;
+ } else {
+ return new BufWriter(w);
}
+}
- async respond(r: Response): Promise<void> {
- const protoMajor = 1;
- const protoMinor = 1;
- const statusCode = r.status || 200;
- const statusText = STATUS_TEXT.get(statusCode);
- if (!statusText) {
- throw Error("bad status code");
- }
+export async function writeResponse(w: Writer, r: Response): Promise<void> {
+ const protoMajor = 1;
+ const protoMinor = 1;
+ const statusCode = r.status || 200;
+ const statusText = STATUS_TEXT.get(statusCode);
+ const writer = bufWriter(w);
+ if (!statusText) {
+ throw Error("bad status code");
+ }
- let out = `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r\n`;
+ let out = `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r\n`;
- setContentLength(r);
+ setContentLength(r);
- if (r.headers) {
- for (const [key, value] of r.headers) {
- out += `${key}: ${value}\r\n`;
- }
+ if (r.headers) {
+ for (const [key, value] of r.headers) {
+ out += `${key}: ${value}\r\n`;
}
- out += "\r\n";
+ }
+ out += "\r\n";
- const header = new TextEncoder().encode(out);
- let n = await this.w.write(header);
- assert(header.byteLength == n);
+ const header = new TextEncoder().encode(out);
+ let n = await writer.write(header);
+ assert(header.byteLength == n);
- if (r.body) {
- if (r.body instanceof Uint8Array) {
- n = await this.w.write(r.body);
- assert(r.body.byteLength == n);
+ if (r.body) {
+ if (r.body instanceof Uint8Array) {
+ n = await writer.write(r.body);
+ assert(r.body.byteLength == n);
+ } else {
+ if (r.headers.has("content-length")) {
+ const bodyLength = parseInt(r.headers.get("content-length"));
+ const n = await copy(writer, r.body);
+ assert(n == bodyLength);
} else {
- if (r.headers.has("content-length")) {
- await this._streamBody(
- r.body,
- parseInt(r.headers.get("content-length"))
- );
- } else {
- await this._streamChunkedBody(r.body);
- }
+ await writeChunkedBody(writer, r.body);
}
}
+ }
+ await writer.flush();
+}
- await this.w.flush();
+async function writeChunkedBody(w: Writer, r: Reader) {
+ const writer = bufWriter(w);
+ const encoder = new TextEncoder();
+
+ for await (const chunk of toAsyncIterator(r)) {
+ const start = encoder.encode(`${chunk.byteLength.toString(16)}\r\n`);
+ const end = encoder.encode("\r\n");
+ await writer.write(start);
+ await writer.write(chunk);
+ await writer.write(end);
}
+
+ const endChunk = encoder.encode("0\r\n\r\n");
+ await writer.write(endChunk);
}
async function readRequest(
diff --git a/http/server_test.ts b/http/server_test.ts
index 5fdb63ceb..099547d0c 100644
--- a/http/server_test.ts
+++ b/http/server_test.ts
@@ -6,14 +6,9 @@
// https://github.com/golang/go/blob/master/src/net/http/responsewrite_test.go
import { Buffer } from "deno";
-import { test, assert, assertEqual } from "../testing/mod.ts";
-import {
- listenAndServe,
- ServerRequest,
- setContentLength,
- Response
-} from "./server.ts";
-import { BufWriter, BufReader } from "../io/bufio.ts";
+import { assertEqual, test } from "../testing/mod.ts";
+import { Response, ServerRequest } from "./server.ts";
+import { BufReader, BufWriter } from "../io/bufio.ts";
interface ResponseTest {
response: Response;