EdgeOne Pages 托管的静态页面直接请求第三方 API(如百度 AI)时,会遇到浏览器跨域限制(CORS Error)。解决方案是通过 Edge Function 作为代理中转请求。
浏览器 → EdgeOne 静态页面 → Edge Function (代理) → 第三方 API
↓
添加 CORS 头
在项目根目录创建以下结构:
your-project/
├── index.html
└── edge-functions/
└── api/
└── [your-api-name].js ← 代理函数
// edge-functions/api/[your-api-name].js
// 代理请求第三方 API 并添加 CORS 头
// ⚠️ 重要:敏感凭证不要硬编码,使用环境变量
export default async function onRequest(context) {
// 1. 配置你的第三方 API
const TARGET_API = 'https://api.example.com';
// 2. 获取凭证(优先使用环境变量)
const apiKey = context.env.API_KEY || 'YOUR_API_KEY'; // ← 使用环境变量
// 3. 从请求中获取参数
const url = new URL(context.request.url);
const param1 = url.searchParams.get('param1');
try {
// 4. 发起请求到目标 API
const response = await fetch(`${TARGET_API}?key=${apiKey}¶m1=${param1}`, {
method: 'GET', // 或 POST
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
// POST 请求 body:
// body: JSON.stringify({ key: 'value' })
});
const data = await response.json();
// 5. 返回带 CORS 头的响应
return new Response(JSON.stringify(data), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*', // 允许所有来源
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
},
status: response.ok ? 200 : response.status
});
} catch (error) {
return new Response(JSON.stringify({
error: '代理请求失败',
message: error.message
}), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
status: 500
});
}
}
不要将敏感凭证(如 client_secret、API Key)硬编码在代码中!
在 EdgeOne 控制台设置环境变量:
CLIENT_ID = your_client_id
CLIENT_SECRET = your_client_secret
Edge Function 中通过 context.env 读取:
const clientId = context.env.CLIENT_ID;
const clientSecret = context.env.CLIENT_SECRET;
在 Edge Function 中使用本地配置文件(仅供本地测试):
// ⚠️ 仅供本地测试,生产环境请使用环境变量
const CONFIG = {
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET'
};
// 检查是否配置
if (!clientId || clientId === 'YOUR_CLIENT_ID') {
return new Response(JSON.stringify({
error: '请先配置凭证'
}), { status: 400 });
}
参考 demo/ 目录中的完整示例:
| 文件 | 说明 |
|---|---|
| ------ | ------ |
demo/index.html | 前端页面,调用代理 API |
demo/edge-functions/api/token.js | Edge Function 代理(含凭证配置示例) |
/api/token修改 demo/edge-functions/api/token.js 中的 CONFIG:
const CONFIG = {
client_id: '你的_client_id', // ← 修改这里
client_secret: '你的_client_secret' // ← 修改这里
};
cd demo
edgeone pages dev
然后访问本地预览地址测试。
edgeone pages deploy demo -n your-project-name -t YOUR_API_TOKEN
export default async function onRequest(context) {
// 优先使用环境变量
const clientId = context.env.CLIENT_ID || CONFIG.client_id;
const clientSecret = context.env.CLIENT_SECRET || CONFIG.client_secret;
// 检查凭证
if (!clientId || !clientSecret) {
return new Response(JSON.stringify({ error: '请配置凭证' }), { status: 400 });
}
const url = `https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}`;
try {
const response = await fetch(url, { method: 'POST' });
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
});
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: { 'Access-Control-Allow-Origin': '*' }
});
}
}
export default async function onRequest(context) {
const { request } = context;
const body = await request.json();
const response = await fetch('https://api.example.com/endpoint', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type'
}
});
}
client_secretAccess-Control-Allow-Origin 设为具体域名edgeone pages deploy <项目目录> -n <项目名> -t <API_TOKEN>
每次更新代码后重新部署即可生效。
共 1 个版本