summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2018-11-08 15:03:45 -0500
committerRyan Dahl <ry@tinyclouds.org>2018-11-08 15:07:37 -0500
commit80b2067030abdf9f51b1d0eb9ceaaf76c2d09bfb (patch)
tree28ac74d66c66bbf9e418e926dfed978919b81fb8
parentfb0b99408b1ce0c8061d654e9dae3fd8221efa6f (diff)
Use async iterators for http server.
Original: https://github.com/denoland/deno_std/commit/9377d154c5079a732d76a36a6ec5892d8da43087
-rw-r--r--http.ts98
-rw-r--r--http_test.ts19
2 files changed, 64 insertions, 53 deletions
diff --git a/http.ts b/http.ts
index 4c209153a..c7ac88879 100644
--- a/http.ts
+++ b/http.ts
@@ -1,71 +1,67 @@
-import * as deno from "deno";
-import * as bufio from "./bufio.ts";
+import { listen, Conn } from "deno";
+import { BufReader, BufState } from "./bufio.ts";
import { TextProtoReader } from "./textproto.ts";
+import { Headers } from "./headers.ts";
-type Handler = (req: ServerRequest) => Promise<void>;
-
-class Server {
- _closing = false;
-
- constructor(readonly listener: deno.Listener) {}
-
- async serve(handler: Handler) {
- while (!this._closing) {
- const c = await this.listener.accept();
- const sc = new ServerConn(c);
- sc.serve(handler);
- }
+export async function* serve(addr: string) {
+ const listener = listen("tcp", addr);
+ while (true) {
+ const c = await listener.accept();
+ yield* serveConn(c);
}
+ listener.close();
+}
- close() {
- this._closing = true;
- this.listener.close();
+export async function* serveConn(c: Conn) {
+ let bufr = new BufReader(c);
+ try {
+ while (true) {
+ const req = await readRequest(bufr);
+ yield req;
+ }
+ } finally {
+ c.close();
}
}
-class ServerConn {
- constructor(readonly c: deno.Conn) {
- // TODO Use memory pool to obtain bufr and bufw.
- this.bufr = new bufio.Reader(c);
- this.bufw = new bufio.Writer(c);
- }
+interface Response {
+ status?: number;
+ body: string;
+}
- async serve(handler: Handler): Promise<void> {
- const buffer = new Uint8Array(1024);
- try {
- while (true) {
- const req = readRequest(this.bufr);
+class ServerRequest {
+ url: string;
+ method: string;
+ proto: string;
- /*
- const response = new TextEncoder().encode(
- "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n"
- );
- await this.c.write(response);
- */
- }
- } finally {
- this.c.close();
- }
+ respond(r: Response = { status: 200 }): Promise<void> {
+ throw Error("not implemented");
}
}
-function readRequest(b: bufio.Reader): ServerRequest {
+async function readRequest(b: BufReader): Promise<ServerRequest> {
const tp = new TextProtoReader(b);
const req = new ServerRequest();
// First line: GET /index.html HTTP/1.0
- const s = await tp.readLine();
- const [method, url, proto] = parseRequestLine(s);
- console.log("readRequest", method, url);
-}
+ let s: string;
+ let err: BufState;
+ [s, err] = await tp.readLine();
+ const { method, url, proto } = parseRequestLine(s);
+ req.method = method;
+ req.url = url;
+ req.proto = proto;
-// Returns [method, url, proto]
-function parseRequestLine(line: string): [string, string, string] {
- return line.split(" ", 3);
+ let headers: Headers;
+ [headers, err] = await tp.readMIMEHeader();
+
+ return req;
}
-export function listen(addr: string): Server {
- const listener = deno.listen("tcp", addr);
- const s = new Server(listener);
- return s;
+// Returns [method, url, proto]
+function parseRequestLine(
+ line: string
+): { method: string; url: string; proto: string } {
+ let [method, url, proto] = line.split(" ", 3);
+ return { method, url, proto };
}
diff --git a/http_test.ts b/http_test.ts
index 4a8867aba..1b16b0f0a 100644
--- a/http_test.ts
+++ b/http_test.ts
@@ -1,6 +1,21 @@
-//import { listen } from "./server.ts";
-import { test } from "https://deno.land/x/testing/testing.ts";
+import { serve } from "./http.ts";
+//import { test } from "https://deno.land/x/testing/testing.ts";
+const addr = "0.0.0.0:8000";
+const s = serve(addr);
+console.log(`listening on http://${addr}/`);
+
+async function main() {
+ for await (const req of s) {
+ console.log("Req", req);
+ req.respond({ body: "Hello World\n" });
+ }
+}
+
+main();
+
+/*
test(function basic() {
console.log("ok");
});
+ */