这个页面主要记录了 Bun 的本地Bun.serve API。Bun 还实现了fetch和 Node.js 的http和https模块。
这些模块已经重新实现以使用 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对象并返回一个Response或Promise<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_ENV为production,否则开发模式是 启用的。
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.serve返回一个Server对象。要停止服务器,请调用.stop()方法。
const server = Bun.serve({
fetch() {
return new Response("Bun!");
},
});
server.stop();
TLS
Bun 默认支持 TLS(HTTPS),由BoringSSL提供支持。要启用 TLS,请在服务器配置中提供key和cert值。这两者都是启用 TLS 所必需的。
Bun.serve({
fetch(req) {
return new Response("Hello!!!");
},
+ tls: {
+ key: Bun.file("./key.pem"),
+ cert: Bun.file("./cert.pem"),
+ }
});
key和cert字段期望您的 TLS 密钥和证书的 内容,而不是路径。这可以是字符串、BunFile、TypedArray或Buffer。
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-Range和Content-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 |
参考
查看 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;
}