Creating a Deno https server
Asked Answered
A

7

15

I am looking for an example of creating a https server in Deno. I have seen examples of Deno http server but not https.

I have tried searching in google but found no results

Anopheles answered 30/4, 2019 at 1:31 Comment(3)
Deno currently does not have SSL bindings yet. There is ongoing work adding such bindings so you could expect it to land in the coming 2 months.Pansophy
As above, there's currently no way to do so in Deno. A good alternative is to setup a reverse proxy like nginx which will forward https requests to your http server.Travail
Small update: we just implemented Deno.listenTLS(). We will be introducing serveTLS or similar for https very soon in Deno standard modules.Pansophy
P
12

Using Deno.serve:

As shown in the Deno.serve documentation:

const options = {
  port: 443,
  cert: await Deno.readTextFile("./cert.pem"),
  key: await Deno.readTextFile("./key.pem"),
};

Deno.serve(options, (request) => {
  const body = `Your user-agent is: ${request.headers.get("user-agent")}`;
  return new Response(body, { status: 200 });
});

You can generate the cert and key files like this on Linux, for example:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'

Old Answer (Deprecated):

serveTLS has landed along with Deno 0.23.0:

Sample usage:

import { serveTLS } from "https://deno.land/std/http/server.ts";

const body = new TextEncoder().encode("Hello HTTPS");
const options = {
  hostname: "localhost",
  port: 443,
  certFile: "./path/to/localhost.crt",
  keyFile: "./path/to/localhost.key",
};
// Top-level await supported
for await (const req of serveTLS(options)) {
  req.respond({ body });
}
Pansophy answered 9/11, 2019 at 22:39 Comment(0)
E
1

With Deno 1.9+ you could use the native server. It provides the ability to use HTTPS.

It is a good bit faster faster than older implementations of std/http. However, as of version 0.107.0 the native server is used for std/http as well.

Example:

const server = Deno.listenTls({
  port: 443,
  certFile: "./my-ca-certificate.pem",
  keyFile: "./my-key.pem"
});

for await (const conn of server) {
  handle(conn);
}

async function handle(conn: Deno.Conn) {
  const httpConn = Deno.serveHttp(conn);
  
  for await (const requestEvent of httpConn) {
    try {
      const response = new Response("Hello World!");
      await requestEvent.respondWith(response);
    } 
    catch (error) {
      console.error(error);
    }
  }
}
Enrico answered 15/8, 2021 at 19:14 Comment(0)
P
0

Now TLS binding is supported by Deno. Below are ways to create https server:

import { serveTLS } from "https://deno.land/std/http/server.ts";

    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 });
}

serveTLS

Arguments options: any

return :Server

With listenAndServeTLS

listenAndServeTLS(options, (req) => {
   req.respond({ body });
 });

listenAndServeTLS

Arguments

  • options: any

  • handler: (req: ServerRequest) => void

return:any

For more details see official docs:

Pansie answered 11/12, 2019 at 21:2 Comment(2)
do you know how to make it work with self signed certificates, it does not seems to be working with it!Chime
Yes, I am getting this error: Uncaught InvalidData: received fatal alert: BadCertificate, same cert-key works on node express setup!Chime
F
0

How about using deno oak framework?

https://github.com/oakserver/oak

I think the project is the most stable web framework in Deno. And you also get the much information from that you want to learn about it.

Fleck answered 16/5, 2020 at 6:8 Comment(0)
O
0

First of all, it is possible to create an HTTPS server with DENO std library. But in my case, I used the OAK library for my app. More about the oak library can be found here. Step-1: Have the certificate file and key file ready(assuming they are produced for whatever domain name you like. It could just be localhost). If you have no idea what this means, read this article.. Step-2: It's time to configure your app's listening options. You can copy the below line of code and change the paths to the certFile and keyFile options as necessary. More explanation given below.

await app.listen({ port: port, secure: true, certFile: "<path-to-file>/<file-name>.pem", keyFile: "<path-to-file>/<file-name>-key.pem" });

In case you want to know what's happening in the above line:

  1. Oak's Application's listen method accepts options to be configured and these options is of type ListenOptions which can either be ListenOptionsBase or ListenOptionsTls which are inherited from Deno.ListenOptions and Deno.ListenTlsOptions respectively. If you check the Deno.ListenTlsOptions there are two options which are certFile and keyFile which accepts paths to your certificate and key for the certificate respectively, which are both .pem files.
Originality answered 10/6, 2021 at 8:7 Comment(0)
L
0

bro, I run into some situations when I code like as follow:

/** @format */
const cert = Deno.readTextFileSync('./cert.pem')
const key = Deno.readTextFileSync('./private.pem')

const listener = Deno.listenTls({
  cert,
  key,
  hostname: 'localhost',
  port: 8080,
})

console.log('Server running on https://localhost:8080/')

for await (const conn of listener) {
  handleConn(conn)
}

async function handleConn(conn: Deno.TlsConn) {
  const httpConn = Deno.serveHttp(conn)

  for await (const req of httpConn) {
    const url = new URL(req.request.url)
    if (url.pathname === '/favicon.ico') continue
    const path = url.pathname === '/' ? '/welcome.html' : url.pathname
    const ext = path.split('.').pop()

    const file = (await Deno.open(`./http/example${path}`)).readable
    let res: Response | null = null
    switch (ext) {
      case 'html' || 'css':
        res = resBuilder(file, `text/${ext}`)
        break
      case 'js':
        res = resBuilder(file, 'text/javascript')
        break
      case 'png' || 'jpg' || 'ico':
        res = resBuilder(file, `image/${ext}`)
        break
      default:
        res = resBuilder(file, '*/*')
    }
    req.respondWith(res!)
  }
}

function resBuilder(data: ReadableStream<Uint8Array>, contentType: string) {
  return new Response(data, {
    headers: new Headers({ 'content-type': contentType }),
  })
}

When I opened it in the browser, an error occurred:

error: Uncaught (in promise) Http: error writing a body to connection: tls handshake eof: tls handshake eof
  for await (const req of httpConn) {
                   ^
    at async HttpConn.nextRequest (ext:deno_http/01_http.js:101:21)
    at async Object.next (ext:deno_http/01_http.js:184:24)
    at async handleConn (file:///Users/feiwu/Project/node/coding_and_nas/http/example/http.ts:24:20)
Lilybel answered 31/8, 2023 at 17:4 Comment(0)
S
-2

Have you checked DENO ABC? It is better framework to create web applications. Read more at https://deno.land/x/abc/README.md.

import { abc } from "https://deno.sh/abc/mod.ts";
const app = abc();
app
  .get("/hello", c => {
    return "Hello, Abc!";
  })
  .start("0.0.0.0:8080");
Soutine answered 1/10, 2019 at 8:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.