Skip to main content
Bun 实现了 WHATWG fetch 标准,并添加了一些扩展以满足服务端 JavaScript 的需求。 Bun 也实现了 node:http,但通常推荐使用 fetch

发送 HTTP 请求

要发送 HTTP 请求,使用 fetch
fetch 也支持 HTTPS URL。
你也可以向 fetch 传递一个 Request 对象。

发送 POST 请求

要发送 POST 请求,传递一个 method 属性为 "POST" 的对象。
body 可以是字符串、FormData 对象、ArrayBufferBlob,或其他列在 MDN 文档中的主体类型。

代理请求

要代理请求,传递一个 proxy 属性为 URL 字符串、URL 实例,或一个包含 url 属性的对象:
要向代理服务器发送自定义头部,传递一个对象:
headers 会直接发送给代理——在 CONNECT 请求(针对 HTTPS 目标)或代理请求(针对 HTTP 目标)中。如果你提供了 Proxy-Authorization 头部,它会覆盖代理 URL 中的任何凭据。

自定义头部

要设置自定义头部,传递一个 headers 属性为对象的参数。
你也可以使用 Headers 对象来设置头部。

响应体

要读取响应体,使用以下方法之一:
  • response.text(): Promise<string>:返回一个 Promise,解析为字符串格式的响应体。
  • response.json(): Promise<any>:返回一个 Promise,解析为 JSON 对象的响应体。
  • response.formData(): Promise<FormData>:返回一个 Promise,解析为 FormData 对象的响应体。
  • response.bytes(): Promise<Uint8Array>:返回一个 Promise,解析为 Uint8Array 的响应体。
  • response.arrayBuffer(): Promise<ArrayBuffer>:返回一个 Promise,解析为 ArrayBuffer 的响应体。
  • response.blob(): Promise<Blob>:返回一个 Promise,解析为 Blob 的响应体。

流式传输响应体

你可以使用异步迭代器来流式传输响应体。
你也可以直接访问 ReadableStream

流式传输请求体

你也可以使用 ReadableStream 在请求体中流式传输数据:
当使用 HTTP(S) 的流时:
  • 数据直接流式传输到网络,无需将整个请求体缓冲到内存中
  • 如果连接断开,流会被取消
  • 除非流具有已知大小,否则不会自动设置 Content-Length 头部
当使用 S3 的流时:
  • 对于 PUT/POST 请求,Bun 自动使用分片上传
  • 流会分块消费并并行上传
  • 可以通过 S3 选项监控进度

带超时的 URL 请求

要带超时请求 URL,使用 AbortSignal.timeout

取消请求

要取消请求,使用 AbortController

Unix 域套接字

要使用 Unix 域套接字请求 URL,使用 unix: string 选项:

TLS

要使用客户端证书,使用 tls 选项:

自定义 TLS 验证

要自定义 TLS 验证,使用 tls 中的 checkServerIdentity 选项:
此选项类似于 Node 的 tls 模块中的类似选项。

禁用 TLS 验证

要禁用 TLS 验证,将 rejectUnauthorized 设置为 false
这样可以避免使用自签名证书时出现 SSL 错误,但会禁用 TLS 验证,请谨慎使用。

请求选项

除了标准的 fetch 选项之外,Bun 还提供了几个扩展:

协议支持

除了 HTTP(S),Bun 的 fetch 还支持多种其他协议:

S3 URL - s3://

Bun 支持直接从 S3 存储桶获取数据。
使用 S3 时,只有 PUT 和 POST 方法支持请求体。对于上传,Bun 会自动使用分片上传来流式传输主体。 参阅 S3 文档。

文件 URL - file://

你可以使用 file: 协议获取本地文件:
在 Windows 上,路径会自动规范化:

Data URL - data:

Bun 支持 data: URL 方案:

Blob URL - blob:

你可以使用 URL.createObjectURL() 创建的 URL 来获取 blob:

错误处理

Bun 的 fetch 实现包含几个特定的错误情况:
  • 使用 GET/HEAD 方法时使用请求体会抛出错误(这是 fetch API 的预期行为)
  • 同时使用 proxyunix 选项会抛出错误
  • rejectUnauthorized 为 true(或未定义)时,TLS 证书验证失败
  • S3 操作可能会抛出与认证或权限相关的特定错误

Content-Type 处理

当未显式提供时,Bun 会自动为请求体设置 Content-Type 头部:
  • 对于 Blob 对象,使用 blob 的 type
  • 对于 FormData,设置适当的 multipart 边界

调试

用于调试,向 fetch 传递 verbose: true
这会将请求和响应头部打印到终端:
verbose: boolean 是 Bun 特有的扩展,不是 Web 标准 fetch API 的一部分。

性能

在发送 HTTP 请求之前,Bun 需要解析 DNS、连接 TCP 套接字,有时还要完成 TLS 握手。每个步骤都需要时间,尤其是在 DNS 速度慢或网络连接差的情况下。请求完成后,消费响应体也需要时间和内存。 Bun 提供了优化每个步骤的 API。

DNS 预取

当你知道即将连接到某个主机并希望避免初始 DNS 查询时,使用 dns.prefetch

DNS 缓存

默认情况下,Bun 会将 DNS 查询在内存中缓存最多 30 秒,并进行去重。dns.getCacheStats() 返回缓存统计信息。 参见 DNS 缓存

预连接到主机

fetch.preconnect 会在你准备好向其发送请求之前,为一个主机启动 DNS 查询、TCP 套接字连接和 TLS 握手。
fetch.preconnect 之后立即调用 fetch 不会使你的请求变快。预连接只有在知道主机和发送请求之间存在间隔时才有帮助。

启动时预连接

要在启动时预连接到一个主机,传递 --fetch-preconnect
--fetch-preconnect 类似于 HTML 中的 <link rel="preconnect">。在 Windows 上未实现;如果你在 Windows 上需要此功能,请提交 issue。

连接池与 HTTP keep-alive

Bun 会自动复用到同一主机的连接。这称为连接池,可以显著减少建立连接所需的时间。

并发连接限制

默认情况下,Bun 将并发 fetch 请求数量限制为 256,原因有二:
  • 它提高了整体系统稳定性。操作系统对并发打开的 TCP 套接字数量有上限,通常在数千以内。接近此限制会导致整台计算机行为异常。应用程序挂起和崩溃。
  • 它鼓励 HTTP Keep-Alive 连接复用。对于短生命周期的 HTTP 请求,最慢的步骤通常是初始连接建立。复用连接可以节省大量时间。
当超出限制时,请求会排队,并在下一个请求结束时发送。 要提高限制,设置 BUN_CONFIG_MAX_HTTP_REQUESTS 环境变量:
此限制的最大值为 65,535。最大端口号是 65,535,因此任何一台计算机都很难超过此限制。

响应缓冲

读取响应体最快的方法是使用以下方法之一:
  • response.text(): Promise<string>
  • response.json(): Promise<any>
  • response.formData(): Promise<FormData>
  • response.bytes(): Promise<Uint8Array>
  • response.arrayBuffer(): Promise<ArrayBuffer>
  • response.blob(): Promise<Blob>
你也可以使用 Bun.write 将响应体写入磁盘上的文件:

实现细节

  • 连接池默认启用,但可以通过 keepalive: false"Connection: close" 头部为每个请求禁用。
  • 大文件上传在特定条件下使用操作系统的 sendfile 系统调用进行优化:
    • 文件必须大于 32KB
    • 请求不能使用代理
    • 在 macOS 上,只有普通文件(不是管道、套接字或设备)可以使用 sendfile
    • 当这些条件不满足时,或使用 S3/流式上传时,Bun 会回退到将文件读入内存
    • 此优化对于 HTTP(而非 HTTPS)请求尤其有效,文件可以从内核直接发送到网络栈
  • S3 操作自动处理签名请求和合并认证头部
其中许多功能是 Bun 对标准 fetch API 的扩展。