summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin (Kun) "Kassimo" Qian <kevinkassimo@gmail.com>2019-11-04 13:45:29 -0500
committerRy Dahl <ry@tinyclouds.org>2019-11-04 13:45:29 -0500
commit0644f9c1a6fd85831dac459f50306781ac2b08e3 (patch)
tree677ed1199280db6c1b5b7535883055ededd9a0a8
parent0049d4e50c9dd945f25f69b08b08fbf492001f96 (diff)
std/http: add serveTLS and listenAndServeTLS (#3257)
-rw-r--r--std/http/server.ts57
-rw-r--r--std/http/server_test.ts51
-rw-r--r--std/http/testdata/simple_https_server.ts16
l---------std/http/testdata/tls1
4 files changed, 124 insertions, 1 deletions
diff --git a/std/http/server.ts b/std/http/server.ts
index f1ced0577..9e2184351 100644
--- a/std/http/server.ts
+++ b/std/http/server.ts
@@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-const { listen, copy, toAsyncIterator } = Deno;
+const { listen, listenTLS, copy, toAsyncIterator } = Deno;
type Listener = Deno.Listener;
type Conn = Deno.Conn;
type Reader = Deno.Reader;
@@ -401,6 +401,61 @@ export async function listenAndServe(
}
}
+/** Options for creating an HTTPS server. */
+export type HTTPSOptions = Omit<Deno.ListenTLSOptions, "transport">;
+
+/**
+ * Create an HTTPS server with given options
+ * @param options Server configuration
+ * @return Async iterable server instance for incoming requests
+ *
+ * const body = new TextEncoder().encode("Hello HTTPS");
+ * const options = {
+ * hostname: "localhost",
+ * port: 443,
+ * certFile: "./path/to/localhost.crt",
+ * keyFile: "./path/to/localhost.key",
+ * };
+ * for await (const req of serveTLS(options)) {
+ * req.respond({ body });
+ * }
+ */
+export function serveTLS(options: HTTPSOptions): Server {
+ const tlsOptions: Deno.ListenTLSOptions = {
+ ...options,
+ transport: "tcp"
+ };
+ const listener = listenTLS(tlsOptions);
+ return new Server(listener);
+}
+
+/**
+ * Create an HTTPS server with given options and request handler
+ * @param options Server configuration
+ * @param handler Request handler
+ *
+ * const body = new TextEncoder().encode("Hello HTTPS");
+ * const options = {
+ * hostname: "localhost",
+ * port: 443,
+ * certFile: "./path/to/localhost.crt",
+ * keyFile: "./path/to/localhost.key",
+ * };
+ * listenAndServeTLS(options, (req) => {
+ * req.respond({ body });
+ * });
+ */
+export async function listenAndServeTLS(
+ options: HTTPSOptions,
+ handler: (req: ServerRequest) => void
+): Promise<void> {
+ const server = serveTLS(options);
+
+ for await (const request of server) {
+ handler(request);
+ }
+}
+
export interface Response {
status?: number;
headers?: Headers;
diff --git a/std/http/server_test.ts b/std/http/server_test.ts
index 7917aeddd..5baeaa144 100644
--- a/std/http/server_test.ts
+++ b/std/http/server_test.ts
@@ -529,4 +529,55 @@ test({
}
});
+test({
+ name: "[http] serveTLS",
+ async fn(): Promise<void> {
+ // Runs a simple server as another process
+ const p = Deno.run({
+ args: [
+ Deno.execPath(),
+ "http/testdata/simple_https_server.ts",
+ "--allow-net",
+ "--allow-read"
+ ],
+ 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;
+ }
+ )
+ .catch((_): void => {}); // Ignores the error when closing the process.
+
+ // Requests to the server and immediately closes the connection
+ const conn = await Deno.dialTLS({
+ hostname: "localhost",
+ port: 4503,
+ certFile: "http/testdata/tls/RootCA.pem"
+ });
+ await Deno.writeAll(
+ conn,
+ new TextEncoder().encode("GET / HTTP/1.0\r\n\r\n")
+ );
+ const res = new Uint8Array(100);
+ const nread = assertNotEOF(await conn.read(res));
+ conn.close();
+ const resStr = new TextDecoder().decode(res.subarray(0, nread));
+ assert(resStr.includes("Hello HTTPS"));
+ assert(serverIsRunning);
+ } finally {
+ // Stops the sever.
+ p.close();
+ }
+ }
+});
+
runIfMain(import.meta);
diff --git a/std/http/testdata/simple_https_server.ts b/std/http/testdata/simple_https_server.ts
new file mode 100644
index 000000000..655457c94
--- /dev/null
+++ b/std/http/testdata/simple_https_server.ts
@@ -0,0 +1,16 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+// This is an example of a https server
+import { serveTLS } from "../server.ts";
+
+const tlsOptions = {
+ hostname: "localhost",
+ port: 4503,
+ certFile: "./http/testdata/tls/localhost.crt",
+ keyFile: "./http/testdata/tls/localhost.key",
+};
+const s = serveTLS(tlsOptions);
+console.log(`Simple HTTPS server listening on ${tlsOptions.hostname}:${tlsOptions.port}`);
+const body = new TextEncoder().encode("Hello HTTPS");
+for await (const req of s) {
+ req.respond({ body });
+}
diff --git a/std/http/testdata/tls b/std/http/testdata/tls
new file mode 120000
index 000000000..f6fd22ed8
--- /dev/null
+++ b/std/http/testdata/tls
@@ -0,0 +1 @@
+../../../cli/tests/tls \ No newline at end of file