【Bun中文文档-API】HTTP server

586 阅读2分钟

这个页面主要记录了 Bun 的本地Bun.serve API。Bun 还实现了fetch和 Node.js 的httphttps模块。

这些模块已经重新实现以使用 Bun 的快速内部 HTTP 基础设施。您可以直接使用这些模块;依赖这些模块的框架(如Express)应该可以直接使用。有关详细的兼容性信息,请参阅运行时 > Node.js API

要启动一个高性能的 HTTP 服务器并拥有一个干净的 API,推荐使用Bun.serve

Bun.serve()

使用Bun.serve在 Bun 中启动 HTTP 服务器。

Bun.serve({
  fetch(req) {
    return new Response("Bun!");
  },
});

fetch处理程序处理传入的请求。它接收一个Request对象并返回一个ResponsePromise<Response>

Bun.serve({
  fetch(req) {
    const url = new URL(req.url);
    if (url.pathname === "/") return new Response("Home page!");
    if (url.pathname === "/blog") return new Response("Blog!");
    return new Response("404!");
  },
});

要配置服务器将监听的端口和主机名:

Bun.serve({
  port: 8080, // 默认为$BUN_PORT、$PORT、$NODE_PORT,否则为3000
  hostname: "mydomain.com", // 默认为"0.0.0.0"
  fetch(req) {
    return new Response("404!");
  },
});

要在Unix 域套接字上侦听:

Bun.serve({
  unix: "/tmp/my-socket.sock", // 套接字路径
  fetch(req) {
    return new Response(`404!`);
  },
});

错误处理

要激活开发模式,请设置development: true。默认情况下,除非NODE_ENVproduction,否则开发模式是 启用的

Bun.serve({
  development: true,
  fetch(req) {
    throw new Error("woops!");
  },
});

在开发模式下,Bun 将在浏览器中显示内置的错误页面。

{% image src="/images/exception_page.png" caption="Bun的内置500页" /%}

要处理服务器端错误,请实现一个error处理程序。此函数应返回在发生错误时提供给客户端的Response。在development模式下,此响应将覆盖 Bun 的默认错误页面。

Bun.serve({
  fetch(req) {
    throw new Error("woops!");
  },
  error(error) {
    return new Response(`<pre>${error}\n${error.stack}</pre>`, {
      headers: {
        "Content-Type": "text/html",
      },
    });
  },
});

了解有关 Bun 调试的更多信息

调用Bun.serve返回一个Server对象。要停止服务器,请调用.stop()方法。

const server = Bun.serve({
  fetch() {
    return new Response("Bun!");
  },
});

server.stop();

TLS

Bun 默认支持 TLS(HTTPS),由BoringSSL提供支持。要启用 TLS,请在服务器配置中提供keycert值。这两者都是启用 TLS 所必需的。

  Bun.serve({
    fetch(req) {
      return new Response("Hello!!!");
    },

+   tls: {
+     key: Bun.file("./key.pem"),
+     cert: Bun.file("./cert.pem"),
+   }
  });

keycert字段期望您的 TLS 密钥和证书的 内容,而不是路径。这可以是字符串、BunFileTypedArrayBuffer

Bun.serve({
  fetch() {},

  tls: {
    // BunFile
    key: Bun.file("./key.pem"),
    // Buffer
    key: fs.readFileSync("./key.pem"),
    // 字符串
    key: fs.readFileSync("./key.pem", "utf8"),
    // 上述的数组
    key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")],
  },
});

如果您的私钥使用密码短语加密,请提供passphrase值以解密它。

  Bun.serve({
    fetch(req) {
      return new Response("Hello!!!");
    },

    tls: {
      key: Bun.file("./key.pem"),
      cert: Bun.file("./cert.pem"),
+     passphrase: "my-secret-passphrase",
    }
  });

另外,您可以通过为ca指定值来覆盖可信 CA 证书。默认情况下,服务器将信任 Mozilla 策划的知名 CA 列表。当指定ca时,Mozilla 列表将被覆盖。

  Bun.serve({
    fetch(req) {
      return new Response("Hello!!!");
    },
    tls: {
      key: Bun.file("./key.pem"), // TLS密钥的路径
      cert: Bun.file("./cert.pem"), // TLS证书的路径
+     ca: Bun.file("./ca.pem"), // 根CA证书的路径
    }
  });

要覆盖 Diffie-Hellman 参数:

Bun.serve({
  // ...
  tls: {
    // 其他配置
    dhParamsFile: "/path/to/dhparams.pem", // Diffie-Hellman参数的路径
  },
});

对象语法

到目前为止,本页的示例已经使用了明确的Bun.serve API。Bun 还支持一种备用语法。



import {type Serve} from "bun";

export default {
  fetch(req) {
    return new Response("Bun!");
  },
} satisfies Serve;

不要将服务器选项传递给Bun.serve,而是将其export default。此文件可以直接执行;当 Bun 看到一个包含fetch处理程序的default导出的文件时,它会在底层将其传递给Bun.serve

流式文件

要流式传输文件,请返回一个带有BunFile对象作为主体的Response对象。

Bun.serve({
  fetch(req) {
    return new Response(Bun.file("./hello.txt"));
  },
});

⚡️ 速度 — Bun 在可能的情况下自动使用sendfile(2)系统调用,启用内核中的零拷贝文件传输,这是发送文件的最快方式。

您可以使用Bun.file对象上的slice(start, end)方法发送文件的一部分。这会自动在Response对象上设置Content-RangeContent-Length头。

Bun.serve({
  fetch(req) {
    // 解析`Range`头
    const [start = 0, end = Infinity] = req.headers
      .get("Range") // Range: bytes=0-100
      .split("=") // ["Range: bytes", "0-100"]
      .at(-1) // "0-100"
      .split("-") // ["0", "100"]
      .map(Number); // [0, 100]

    // 返回文件的一部分
    const bigFile = Bun.file("./big-video.mp4");
    return new Response(bigFile.slice(start, end));
  },
});

基准测试

以下是 Bun 和 Node.js 的简单 HTTP 服务器的实现,它们对每个传入的Request都会响应Bun!

Bun.serve({
  fetch(req: Request) {
    return new Response("Bun!");
  },
  port: 3000,
});
require("http")
  .createServer((req, res) => res.end("Bun!"))
  .listen(8080);

在 Linux 上,Bun.serve服务器可以处理大约 2.5 倍于 Node.js 的请求每秒。

运行时每秒请求数
Node 16~64,000
Bun~160,000

image

参考

查看 TypeScript 定义

interface Bun {
  serve(options: {
    fetch: (req: Request, server: Server) => Response | Promise<Response>;
    hostname?: string;
    port?: number;
    development?: boolean;
    error?: (error: Error) => Response | Promise<Response>;
    tls?: {
      key?:
        | string
        | TypedArray
        | BunFile
        | Array<string | TypedArray | BunFile>;
      cert?:
        | string
        | TypedArray
        | BunFile
        | Array<string | TypedArray | BunFile>;
      ca?: string | TypedArray | BunFile | Array<string | TypedArray | BunFile>;
      passphrase?: string;
      dhParamsFile?: string;
    };
    maxRequestBodySize?: number;
    lowMemoryMode?: boolean;
  }): Server;
}

interface Server {
  development: boolean;
  hostname: string;
  port: number;
  pendingRequests: number;
  stop(): void;
}