app.ts 1.6 KB
Newer Older
A
Asher 已提交
1 2 3 4 5 6
import { logger } from "@coder/logger"
import express, { Express } from "express"
import { promises as fs } from "fs"
import http from "http"
import * as httpolyglot from "httpolyglot"
import { DefaultedArgs } from "./cli"
A
Asher 已提交
7
import { handleUpgrade } from "./http"
A
Asher 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

/**
 * Create an Express app and an HTTP/S server to serve it.
 */
export const createApp = async (args: DefaultedArgs): Promise<[Express, http.Server]> => {
  const app = express()

  const server = args.cert
    ? httpolyglot.createServer(
        {
          cert: args.cert && (await fs.readFile(args.cert.value)),
          key: args["cert-key"] && (await fs.readFile(args["cert-key"])),
        },
        app,
      )
    : http.createServer(app)

  await new Promise<http.Server>(async (resolve, reject) => {
    server.on("error", reject)
    if (args.socket) {
      try {
        await fs.unlink(args.socket)
      } catch (error) {
        if (error.code !== "ENOENT") {
          logger.error(error.message)
        }
      }
      server.listen(args.socket, resolve)
    } else {
      // [] is the correct format when using :: but Node errors with them.
      server.listen(args.port, args.host.replace(/^\[|\]$/g, ""), resolve)
    }
  })

A
Asher 已提交
42 43
  handleUpgrade(app, server)

A
Asher 已提交
44 45 46 47
  return [app, server]
}

/**
A
Asher 已提交
48
 * Get the address of a server as a string (protocol *is* included) while
A
Asher 已提交
49 50 51 52 53 54 55 56
 * ensuring there is one (will throw if there isn't).
 */
export const ensureAddress = (server: http.Server): string => {
  const addr = server.address()
  if (!addr) {
    throw new Error("server has no address")
  }
  if (typeof addr !== "string") {
A
Asher 已提交
57
    return `http://${addr.address}:${addr.port}`
A
Asher 已提交
58 59 60
  }
  return addr
}