Skip to content

Commit

Permalink
http: add serveTLS and listenAndServeTLS (denoland/deno#3257)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinkassimo authored and denobot committed Feb 1, 2021
1 parent 1abe6fe commit 63f2f98
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 1 deletion.
57 changes: 56 additions & 1 deletion http/server.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
Expand Down
51 changes: 51 additions & 0 deletions http/server_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
16 changes: 16 additions & 0 deletions http/testdata/simple_https_server.ts
Original file line number Diff line number Diff line change
@@ -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 });
}
1 change: 1 addition & 0 deletions http/testdata/tls

0 comments on commit 63f2f98

Please sign in to comment.