这篇记录一种“反向代理 OpenAI API”的基础做法。常见用途:

先看最小可用方案,再看生产建议。

  • 统一出口域名
  • 统一日志与监控
  • 统一限流与配额

注意:API key 必须保存在服务端,绝不能暴露在浏览器侧。

Cloudflare Workers

准备:

  • 一个 Cloudflare 账号
  • 一个可绑定到 Worker 的域名

步骤:

  • 新建 Worker
  • 绑定自定义域名
  • 请求转发到 api.openai.com

简化版示例

const TARGET = "https://api.openai.com";

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const url = new URL(request.url);
  url.host = new URL(TARGET).host;

  const proxyReq = new Request(url.toString(), {
    method: request.method,
    headers: request.headers,
    body: request.body,
    redirect: "follow",
  });

  const resp = await fetch(proxyReq);
  const out = new Response(resp.body, resp);
  out.headers.set("Access-Control-Allow-Origin", "*");
  return out;
}

进阶版示例

addEventListener("fetch", (event) => {
  event.respondWith(fetchAndApply(event.request));
});

async function fetchAndApply(request) {
  const url = new URL(request.url);
  const originHost = url.hostname;

  url.protocol = "https:";
  url.host = "api.openai.com";

  const headers = new Headers(request.headers);
  headers.set("Host", url.host);
  headers.set("Referer", `${url.protocol}//${originHost}`);

  const resp = await fetch(url.href, {
    method: request.method,
    headers,
    body: request.body,
  });

  const newHeaders = new Headers(resp.headers);
  newHeaders.set("Cache-Control", "no-store");
  newHeaders.set("Access-Control-Allow-Origin", "*");
  newHeaders.delete("content-security-policy");
  newHeaders.delete("content-security-policy-report-only");
  newHeaders.delete("clear-site-data");

  return new Response(resp.body, {
    status: resp.status,
    headers: newHeaders,
  });
}

Nginx 反向代理

server {
  listen 80;
  server_name example.com;

  location /openai/ {
    proxy_pass https://api.openai.com/;
    proxy_set_header Host api.openai.com;
    proxy_set_header Authorization "Bearer $OPENAI_API_KEY";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Caddy 反向代理

example.com {
  route /openai/* {
    uri strip_prefix /openai
    reverse_proxy https://api.openai.com {
      header_up Host api.openai.com
      header_up Authorization "Bearer {env.OPENAI_API_KEY}"
      header_down -Server
    }
  }
}

安全建议

  • API key 只放服务端
  • 开启日志与限流
  • 遵守 OpenAI 使用政策与本地法规