代理

H3 代理工具。

fetchWithEvent(event, url, init?)

发起 fetch 请求,使用事件的上下文和请求头。

如果 url/ 开头,则请求通过 event.app.fetch()(子请求)在内部分派,永远不会离开进程。

安全性: 切勿将未经过滤的用户输入作为 url 传递。调用方负责验证和限制 URL。

getProxyRequestHeaders(event)

获取请求头对象,但不包含已知会在代理时导致问题的头部。

proxy(event, target, opts)

向目标 URL 发起代理请求,并将响应返回给客户端。

如果 target/ 开头,则请求通过 event.app.fetch()(子请求)在内部分派,永远不会离开进程。这会绕过任何外部安全层(反向代理认证、IP 白名单、mTLS)。

安全性: 切勿将未经过滤的用户输入作为 target 传递。调用方负责验证和限制目标 URL(例如:主机白名单、阻止内部路径、强制协议)。

proxyRequest(event, target, opts)

将传入请求代理到目标 URL。

如果 target/ 开头,则请求由应用路由器通过 event.app.fetch() 在内部处理,而不是发起外部 HTTP 请求。

请求体会以流的方式传输到目标端,不会被缓冲。按照 Fetch 标准,请求体只能被消费一次,因此如果你事先读取了它(例如通过 readBody()readFormData() 或读取请求体的中间件),流就会被锁定,代理会失败。如果你需要在检查请求体的同时继续代理,请从副本中读取,并保持原始事件不变。

安全性: 切勿将未经过滤的用户输入作为 target 传递。调用方负责验证和限制目标 URL(例如:主机白名单、阻止内部路径、强制协议)。在代理不受信任输入时,建议使用 bodyLimit() 中间件,以防止过大的请求体消耗过多资源。

示例:

app.all("/proxy", async (event) => {
  const body = await event.req.clone().json(); // 从副本中读取
  // ...检查请求体...
  return proxyRequest(event, "/target"); // 原始流仍然保持完整
});