> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hhapi.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 浏览器跨域（CORS）错误排查与服务端代理模式解决方案

> 浏览器直接调用 HHAPI 时遇到跨域错误的原因分析，强调 API Key 暴露的安全风险，并提供完整的 Node.js Express 服务端代理示例作为推荐解决方案。

当你在浏览器前端代码（React、Vue、纯 HTML 页面等）中直接调用 HHAPI 时，浏览器的同源策略会检查响应头中的 CORS 字段，若条件不满足则会拦截请求，在控制台显示跨域错误。本文说明 CORS 问题的根本原因，以及推荐的解决方案。

<Warning>
  **强烈不建议在浏览器前端直接调用 HHAPI。**

  在前端代码中直接调用意味着你的 API Key 会暴露在客户端——任何打开浏览器开发者工具的用户都能看到你的密钥。一旦密钥泄露，可能导致费用被滥用或账户安全风险。**这是安全问题，而非仅仅是技术问题。**
</Warning>

## CORS 产生原因

浏览器的\*\*同源策略（Same-Origin Policy）\*\*规定：网页只能向与自身相同源（协议 + 域名 + 端口均一致）的地址发送请求。当你的前端页面（如 `https://yourapp.com`）尝试请求不同源的 HHAPI 地址时，浏览器会先发送一个 `OPTIONS` 预检请求，检查服务端是否在响应头中声明允许该来源访问：

```http theme={null}
Access-Control-Allow-Origin: https://yourapp.com
```

若服务端未返回对应的 CORS 响应头，浏览器会阻止该请求并在控制台报错：

```text theme={null}
Access to fetch at '<API_BASE_URL>/v1/chat/completions' from origin
'https://yourapp.com' has been blocked by CORS policy.
```

## 推荐解决方案：服务端代理

正确的做法是在你自己的服务端创建一个代理接口，由服务端持有 API Key 并转发请求到 HHAPI。前端只与你自己的服务端通信，API Key 始终不暴露给客户端。

<Steps>
  <Step title="在服务端创建代理接口">
    在你的 Node.js、Python 或其他后端服务中创建一个代理路由，接收前端请求。

    参考下方的 Node.js Express 示例。
  </Step>

  <Step title="前端调用自己的服务端接口">
    前端代码中，将请求目标从 HHAPI 地址改为你自己的服务端地址，无需携带 API Key：

    ```javascript theme={null}
    // ✅ 前端只调用自己的服务端，不直接碰 HHAPI
    const response = await fetch("/api/chat", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        messages: [{ role: "user", content: "你好" }],
      }),
    });
    const data = await response.json();
    ```
  </Step>

  <Step title="服务端持有 API Key 并转发到 HHAPI">
    服务端从环境变量读取 API Key，附加到转发给 HHAPI 的请求中。前端用户无法看到该密钥。
  </Step>
</Steps>

### Node.js Express 代理示例

```javascript theme={null}
import express from "express";
import OpenAI from "openai";

const app = express();
app.use(express.json());

// ✅ API Key 仅在服务端环境变量中，永远不会发送到浏览器
const client = new OpenAI({
  apiKey: process.env.HHAPI_API_KEY,
  baseURL: "<API_BASE_URL>/v1",
});

app.post("/api/chat", async (req, res) => {
  try {
    const { messages } = req.body;

    const completion = await client.chat.completions.create({
      model: "<MODEL_ID>",
      messages: messages,
    });

    res.json(completion);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000, () => console.log("代理服务已启动：http://localhost:3000"));
```

## 如果必须从前端调用（不推荐）

若确有在浏览器直接调用的需求，HHAPI 是否支持配置特定域名的 CORS 白名单（待确认）。请联系 [技术支持](/support) 了解详情。

即使 CORS 问题得以解决，仍请注意 API Key 在前端暴露的安全风险。

<Tip>
  使用服务端代理不仅能解决 CORS 问题，还带来更多好处：

  * **用户鉴权**：在代理层验证用户身份，防止未授权访问
  * **请求审计**：记录请求日志，便于排查问题和分析用量
  * **用量控制**：在代理层实现用户级别的请求限流，防止单个用户超额消耗
  * **密钥隔离**：API Key 集中管理在服务端，轮换密钥时无需修改前端代码
</Tip>

***

**相关资源**

* [获取和管理 API Key](/api-key)
* [获取技术支持](/support)
