Cloudflare - Pages Functions
前言
首先我们来讲解一下平时开发的时候 dev server 的相关流程
pnpm dev 时的调用流程(典型情况)
- 请求发起(浏览器 → Vite dev server 或 直接到目标)
- 前端运行在 Vite 提供的开发服务器(默认
http://localhost:5173)。 - 发起请求的 URL 取决于代码中的前缀写法:
- 如果是相对路径或以
/api开头(例如fetch('/api/run')),浏览器会向当前 origin(localhost:5173)发起请求。 - 如果是完整外部地址(例如
fetch('https://api.example.com/run')),浏览器会直接向该地址发起请求(会遭遇 CORS 限制,除非远端允许)。
- 如果是相对路径或以
- Vite 的 proxy(
vite.config.ts的server.proxy)的作用
- 当你在 vite.config.ts 中配置了:
server: {
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
}
}
}- 浏览器请求
http://localhost:5173/api/run时,Vite dev server 会拦截该请求并在开发服务器端将它转发到https://api.example.com/run(或按 rewrite 后的路径)。 - 代理可修改请求头、转发 body,并避免浏览器端 CORS(因为浏览器只看到和 Vite 的同源请求)。
- 代理不会改变客户端代码里的 API_PREFIX 值——它只是对匹配到的网络请求“替身”转发。
- 前缀(API_PREFIX)从哪里来(在 Vite dev)
- 常见来源:
- 构建时注入:
import.meta.env.VITE_API_PREFIX(在 dev 模式同样可用)——Vite 在运行时把import.meta.env暴露给客户端,值来自 .env 文件(详见 env 部分)。 - 硬编码:直接写 '
/api' 或 '/backend'。 - 运行时注入(少见):通过
<script>window.__CONFIG__ = {...}</script>在index.html中注入并在客户端读取(优点:可在不重建的情况下改变)。
- 构建时注入:
- 如果我们希望在dev阶段通过vite server来代理添加header(比如在network里面隐藏token),可以按照下面这样做
import { defineConfig, loadEnv} from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
import type { ProxyOptions } from 'vite';
export default defineConfig(({mode})=>{
const env = loadEnv(mode, process.cwd())
return {
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
build: {
target: 'esnext',
},
esbuild: {
target: 'esnext',
},
optimizeDeps: {
esbuildOptions: {
target: 'esnext',
},
},
define: {
__APP_CONFIG__: {},
},
server: {
proxy: {
// 任何 /api/rodin 的请求都会被本地 dev-server 转发并注入 Authorization
'/api': {
target: 'https://api.hyper3d.com',
changeOrigin: true,
secure: true,
// configure 用来访问底层的 http-proxy 实例并注册事件
configure: (proxy, options) => {
// proxy 是 http-proxy 实例(来自 http-proxy-middleware / http-proxy)
proxy.on('proxyReq', (proxyReq, req, res) => {
// 仅在本地 dev 时把 token 加到发往上游的请求里
if (env.VITE_RODIN_TOKEN) {
proxyReq.setHeader('authorization', `Bearer ${env.VITE_RODIN_TOKEN}`);
}
});
}
} as ProxyOptions
}
},
}
})wrangler pages dev ./dist(用本地构建的 dist 由 wrangler Pages/Workers 提供)时的调用流程
浏览器发出的请求,只要包含 token,就会在 DevTools 的 Network 里可见;要“看不见”就必须让 token 不从浏览器发出,而由服务端(Pages Function / dev proxy)代为添加并转发到上游。Pages Functions 可以通过绑定的 secrets / environment variables 在运行时读取 token 并注入。
说明:
wrangler pages dev ./dist会把 ./dist 当作 Pages 的静态站点来服务;同时 Cloudflare Pages 支持 Functions(Worker) 用于处理比如 /api/* 的请求;wrangler 能把你的 Worker 本地运行并与 Pages 集成 — 行为取决于你的wrangler.toml、functions目录或routes配置。
- 客户端(浏览器)发起请求 —— 路径解析
- 编译后的前端代码(dist)里 URL 是构建时已确定的:
- 如果你在源码中使用
import.meta.env.VITE_API_PREFIX,这些值在构建时就已被内联到 JS 文件里(例如替成 "/api" 或 "https://api.example.com")。 - 因此,当 wrangler pages dev 提供 index.html 与静态资源时,浏览器会按构建后固化的 URL 发起请求。
- 如果你在源码中使用
- 关键点:在 dist 模式下要改变 API 前缀通常需要重新构建,除非你采用运行时配置(window.CONFIG)手段。
- 如何被转发 / 由谁处理
- 可能的处理方式:
- Pages Functions(或 Worker)处理
/api/*:如果你的项目在 Pages 设置了 Functions(例如 functions/ 下的 Worker 脚本)并且 route 规则匹配 /api/*,那么 wrangler pages dev 会在本地用 Worker 拦截这些请求并执行函数逻辑(可以调用外部 API、注入 secrets 等)。这时浏览器请求到达本地 wrangler,然后由 Worker 代为 fetch() 到外部服务并把响应返回给浏览器(Worker 能安全读取绑定的环境变量/Secrets)。 - 直接请求外部主机:如果构建时 API_PREFIX 指向 https://api.example.com,浏览器会直接向外部主机发起请求(这受远端 CORS 控制)。
- wrangler 本身没有自动代理到外部:不像 Vite dev proxy,wrangler pages dev 并不会自动为 /api 做远端代理,除非你明确创建了一个 Worker/Function 去转发。
- Pages Functions(或 Worker)处理
- 总结:要在 wrangler pages dev 下做到“本地端统一入口并转发 API、隐藏 token”,你通常需要实现一个 Worker(Pages Function)来处理 /api/* 并在 Worker 中用 fetch() 调用真实后端。Worker 可以从 wrangler.toml 的 env / secrets 中读取敏感值(不会暴露给客户端)。
- Env 与 secrets 的获取
- 客户端 env(构建时):import.meta.env.VITE_* 在构建时被替换成字面量,dist 中包含这些值。wrangler pages dev ./dist 无法在运行时替换这些值(除非你在页面里使用运行时注入的 window.CONFIG)。
- Worker/Pages Function 的 env / secret:
- 在 wrangler.toml 中或通过 wrangler secret put 设置的 secret,会以绑定的形式传入 Worker 的 env(或 global)。在 Worker 代码中可以访问并用于转发请求(例如 env.API_KEY)。
- 这些对浏览器不可见(安全),适合在 Worker 里注入 Authorization header 后再 fetch 到后端。
- 示例 Worker 转发伪代码:
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname.startsWith('/api/')) {
const upstream = `https://api.example.com${url.pathname.replace(/^\/api/, '')}`;
const res = await fetch(upstream, {
method: request.method,
headers: {
'Authorization': `Bearer ${env.API_SECRET}`,
// copy other headers as needed
},
body: request.body
});
return res;
}
return fetch(request); // or return static asset
}
}📁 文件结构
mulerun-agent/
├── functions/
│ └── [[path]].ts ← 统一 API 网关 (新建)
├── .dev.vars ← 本地 token 配置(不提交 Git)
├── .env.development ← 前端本地 env(已更新)
├── .env.production ← 前端生产 env(已更新)
├── .gitignore ← 添加 .dev.vars(已更新)
├── QUICK_START.md ← 快速启动指南(新建)
├── PAGES_FUNCTION_GUIDE.md ← 完整使用文档(新建)
└── src/
└── pages/Home.tsx ← 调用 API 的示例位置✅ 已完成的优化
1. 多 Provider 路由支持
新建统一的根路由文件 functions/[[path]].ts,支持:
- ✅
/api/v2/*→ RODIN API (Bearer token) - ✅
/sessions/metering*→ MULE API (x-api-key) - ✅ 自动 CORS 处理
- ✅ 完整的调试日志
关键优势:
- 不需要
/api前缀也能被拦截(/sessions/metering直接路由) - 每个 provider 独立管理 token,便于权限隔离
- 易于扩展新的 provider
2. 安全的环境变量管理
| 文件 | 用途 | Git | 安全性 |
|---|---|---|---|
.dev.vars | 本地 wrangler 环境 | ❌ 不提交 | 🔐 本机仅有 |
.env.development | 前端本地构建 | ✅ 提交 | 🟡 非敏感数据 |
.env.production | 前端生产构建 | ✅ 提交 | 🟡 非敏感数据 |
| Cloudflare Secrets | 线上 token 存储 | N/A | 🔐 加密存储 |
3. 完整的调试与文档
- 📄
QUICK_START.md- 一键启动指南 - 📄
PAGES_FUNCTION_GUIDE.md- 完整部署与使用文档 - 📝 代码注释 - Pages Function 中详细的逻辑说明
- 🔍 结构化日志 -
[Request]、[Proxy]、[Response]便于排查
🔄 工作流总结
本地开发
.dev.vars (RODIN_API_TOKEN, MULE_AGENT_KEY)
↓
pnpm build
↓
pnpm wrangler pages dev ./dist
↓
浏览器访问 http://localhost:8788
↓
前端请求 /api/v2/rodin 或 /sessions/metering
↓
Pages Function 拦截并根据路径转发到对应 provider
↓
Token 由服务端添加,浏览器无法看到 ✅生产部署
编辑 .env.production 中的 VITE_API_URL
↓
在 Cloudflare Pages UI 配置 Secrets:
- RODIN_API_BASE, RODIN_API_TOKEN
- MULE_API_BASE, MULE_AGENT_KEY
↓
pnpm build && wrangler pages deploy ./dist
或 Git 自动部署
↓
Cloudflare Pages 运行 functions/[[path]].ts
↓
前端请求到 https://yoursite.pages.dev/api/v2/rodin
↓
Pages Function 从 Secrets 读取 token,转发请求
↓
Token 安全隐藏 ✅📋 前端代码使用示例
RODIN API 调用
import { request } from '@/services'
// 调用 RODIN 生成模型
const response = await request.post('/api/v2/rodin', {
prompt: 'A 3D cat',
settings: { quality: 'high' }
})路由过程:
/api/v2/rodin
→ 匹配 pathname.startsWith('/api/v2')
→ 使用 RODIN_API_BASE + RODIN_API_TOKEN
→ https://api.hyper3d.com/api/v2/rodin (Bearer Token)MULE API 调用
// 查询计费数据
const response = await request.get('/sessions/metering?user_id=123')路由过程:
/sessions/metering
→ 匹配 pathname.startsWith('/sessions/metering')
→ 使用 MULE_API_BASE + MULE_AGENT_KEY
→ https://api.mulerun.com/sessions/metering (x-api-key)⚙️ 扩展新的 Provider
如果需要添加第三个 provider(比如 /billing/* 用另一个 API),步骤如下:
1. 修改 functions/[[path]].ts
在 getProvider() 函数中添加新路由:
// 在 getProvider 函数中添加
if (pathname.startsWith('/billing')) {
return {
provider: {
base: env.BILLING_API_BASE,
token: env.BILLING_API_KEY,
authType: 'bearer', // 或 'key'
},
pathForUpstream: pathname,
};
}2. 更新 .dev.vars
BILLING_API_BASE="https://billing.example.com"
BILLING_API_KEY="your-billing-key"3. 线上部署
在 Cloudflare Pages UI → Settings → Environment variables 中添加相同的变量。
4. 前端使用
const response = await request.get('/billing/invoices')🔐 安全最佳实践
✅ 应该做
- ✅ 把所有 token/key 放在
.dev.vars或 Cloudflare Secrets(不提交 Git) - ✅ 使用 Pages Function 作为 API 网关隐藏 token
- ✅ 在生产环境中标记 Secrets 为加密类型
- ✅ 定期轮换 token
- ✅ 为不同环境使用不同的 token
❌ 不应该做
- ❌ 把 token 放在
VITE_*或.env.production(会被编译进前端代码) - ❌ 把
.dev.vars提交到 Git - ❌ 在浏览器 Console 中输出 token
- ❌ 使用生产 token 在本地开发
📊 对比:修改前后
修改前
❌ 两个独立的 API 调用方式
❌ /api/v2/* 和 /sessions/metering 无法区分认证方式
❌ 无法同时隐藏多个 token
❌ 扩展新 provider 需要新建文件
❌ 路由逻辑散落修改后
✅ 统一的 API 网关 (functions/[[path]].ts)
✅ 支持多 provider,灵活路由
✅ 每个 provider 独立 token 管理
✅ 所有 token 在服务端,浏览器无法看到
✅ 易于扩展,添加新 provider 只需修改一个文件
✅ 完整的日志与调试信息一、先给结论(方便快速决定)
如果你已经把前端部署在 Cloudflare Pages 且仅需一个简单代理 /api/v2 来隐藏 token:优先选 Pages Functions(最简单、同仓部署、同域、易调试)。
如果你需要更复杂的路由、多个独立服务、或想把代理独立管理:选 Cloudflare Worker(独立 Worker)(更灵活、可复用、适合大型场景)。
下面先把概念讲清,再分别给出两套完整可运行示例(Pages Functions 版本与独立 Worker 版本),包含本地调试、如何写 secret、如何部署、如何在前端调用、注意事项与常见问题排查。
二、概念与差异速览(图文并茂口语化)
Cloudflare Worker:一个独立的边缘 JavaScript 环境(类似在全球有很多小型 serverless 节点),你可以写任意后端逻辑、绑定任意域名或 route。通常通过 wrangler 管理与部署。 优点:独立、灵活、强;缺点:对初学者多一步配置(wrangler、route、zone_id 等)。
Pages Functions:Cloudflare Pages 内置的“函数目录”方案,意味着你的静态站(Pages)与后端函数放在同一个代码仓库 & 一次部署。文件放在 functions/(或 Pages 要求的路径),Pages 会自动部署并将路径映射到函数。 优点:极简体验(同一 repo、一键部署),对前端工程师友好;缺点:在多项目/微服务场景下不够独立。
三、环境准备(通用)
Node.js(建议 >=18)
Cloudflare 帐号(已注册)
你已有前端项目(React + Vite),并且已部署/准备部署到 Cloudflare Pages(可选)
本地终端、编辑器(VSCode 等)
安装/登录 wrangler(用于独立 Worker 或 pages secret 操作):
npm install -g wrangler@latest # 可选:也可用 npx 执行
wrangler login四、重要概念:Variable vs Secret(必须记住)
Variable(env / vars):可以是明文,用于非敏感配置(构建时注入、或 env 运行时使用)。不要放敏感 token。
Secret(加密):加密存储,只能在 Worker/Pages Function 的运行时读取,不能泄露在构建或浏览器端。把 Bearer token 放到 Secret 里。
在 CLI:
Pages secret(绑定到 Pages 项目):
npx wrangler pages secret put API_TOKEN --project-name <your-pages-project>Worker secret(独立 Worker):
echo "MY_TOKEN" | npx wrangler secret put API_TOKEN五、方案 A:Pages Functions(推荐你的场景)
场景适用:你的网站已经部署在 Cloudflare Pages,想在同域下把 /api/v2/* 代理到后端并隐藏 Bearer token。页面与函数放同仓,一起部署最方便。
- 文件位置 & 约定(以常见 Pages 项目结构为例)
在你的项目里(与 dist / build 输出并列)创建:
project-root/
├─ src/ # React 源码(不受影响)
├─ functions/
│ └─ api/
│ └─ v2/
│ └─ [...path].js # catch-all,处理 /api/v2/*
├─ package.json
└─ other files...functions/api/v2/[...path].js(完整代码):
// functions/api/v2/[...path].js
export async function onRequest(context) {
// context 包含 request, env, params, etc.
const { request, env, params } = context;
const url = new URL(request.url);
// params.path 是 catch-all 捕获到的部分(数组形式或字符串,依据 runtime)
// 这里我们直接利用 pathname 替换更简单:
const upstreamBase = env.GLOBAL_UPSTREAM_BASE || 'https://api.example.com';
if (!url.pathname.startsWith('/api/v2')) {
return new Response('Not Found', { status: 404 });
}
// 映射路径: /api/v2/foo/bar -> /v2/foo/bar
const upstreamPath = url.pathname.replace(/^\/api\/v2/, '/v2');
const upstreamUrl = upstreamBase + upstreamPath + url.search;
const apiToken = env.API_TOKEN; // Pages secret / environment binding
if (!apiToken) {
return new Response('Server misconfigured: API_TOKEN missing', { status: 500 });
}
// 复制原请求的 headers 和 body
const headers = new Headers(request.headers);
headers.set('Authorization', `Bearer ${apiToken}`);
headers.delete('Host');
const init = {
method: request.method,
headers,
body: (request.method === 'GET' || request.method === 'HEAD') ? undefined : request.body,
redirect: 'manual'
};
const resp = await fetch(upstreamUrl, init);
// 处理 CORS(如果同域部署,严格限制 origin 更安全)
const respHeaders = new Headers(resp.headers);
respHeaders.set('Access-Control-Allow-Origin', '*');
respHeaders.set('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
respHeaders.set('Access-Control-Allow-Headers', 'Content-Type,Authorization');
return new Response(resp.body, {
status: resp.status,
statusText: resp.statusText,
headers: respHeaders
});
}说明要点
env.API_TOKEN:在 Pages 项目里通过 CLI 或 Dashboard 把 secret 加入(见下)。
Path catch-all:Pages Functions 支持以 [...] 方式捕获任意子路径。
CORS:示例使用 *,上线请把 * 换成你的域名以更安全(例如 https://mulerun-rodin.pages.dev)。
- 把 Secret 加入 Pages(CLI)
# 假设你的 pages 项目名是 mulerun-rodin(在 dashboard 可以看到 project name)
npx wrangler pages secret put API_TOKEN --project-name mulerun-rodin
# 它会提示你粘贴 token(不会在控制台回显),粘贴后回车保存也可以在 Cloudflare Dashboard → Pages → 你的 Project → Settings → Variables & Secrets 添加。
- 本地开发与调试
Pages Functions 在本地可用 wrangler dev 调试,但通常你会先用 Vite 本地开发:
方法 A:在另一个终端运行 npx wrangler dev(模拟 functions),然后把 Vite 的 proxy 指向 http://127.0.0.1:8787,在 Vite 中配置 server.proxy:
// vite.config.js
export default {
// ...
server: {
proxy: {
'/api/v2': 'http://127.0.0.1:8787'
}
}
}方法 B:直接 wrangler pages dev(如果你要模拟完整 Pages 行为,需参照 docs)。 4) 部署
提交代码到你的 Pages 仓库(如果你使用 GitHub + Cloudflare Pages),Cloudflare 会在你 push 后自动 build & deploy(会自动部署 functions)。
或用 wrangler 手动操作(视 Pages 流程而定)。 六、方案 B:独立 Cloudflare Worker(适合更复杂场景)
场景适用:你想把代理做成独立服务、需要自定义路由或多个站点共用同一个代理,或想独立运维。
- 项目结构(最小)
my-wrangler/
├─ src/
│ └─ index.js
├─ wrangler.toml
└─ package.jsonsrc/index.js(模块化 Worker):
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (!url.pathname.startsWith('/api/v2')) {
return fetch(request); // passthrough 或 404
}
const upstreamBase = env.GLOBAL_UPSTREAM_BASE || 'https://api.example.com';
const upstreamPath = url.pathname.replace(/^\/api\/v2/, '/v2');
const upstreamUrl = upstreamBase + upstreamPath + url.search;
const apiToken = env.API_TOKEN;
if (!apiToken) {
return new Response('Server misconfigured: API_TOKEN missing', { status: 500 });
}
const headers = new Headers(request.headers);
headers.set('Authorization', `Bearer ${apiToken}`);
headers.delete('Host');
const init = {
method: request.method,
headers,
body: (request.method === 'GET' || request.method === 'HEAD') ? undefined : request.body,
redirect: 'manual'
};
const upstreamResp = await fetch(upstreamUrl, init);
const respHeaders = new Headers(upstreamResp.headers);
respHeaders.set('Access-Control-Allow-Origin', '*');
respHeaders.set('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
respHeaders.set('Access-Control-Allow-Headers', 'Content-Type,Authorization');
return new Response(upstreamResp.body, {
status: upstreamResp.status,
statusText: upstreamResp.statusText,
headers: respHeaders
});
}
};- wrangler.toml(最小)
name = "mulerun-rodin-proxy"
main = "src/index.js"
compatibility_date = "2025-11-18"
workers_dev = true
# 若要绑定到 pages 域名下的 route,可在 Dashboard 配置 route:
# route = "mulerun-rodin.pages.dev/api/*"
# zone_id = "<your-zone-id>"- 把 Secret 加到 Worker
echo "YOUR_REAL_API_TOKEN" | npx wrangler secret put API_TOKEN
# 或在交互中运行:
npx wrangler secret put API_TOKEN
# 然后粘贴值- 本地调试
npx wrangler dev src/index.js
# 打开 http://127.0.0.1:8787 并测试 /api/v2/...注意:wrangler dev 本地调试不会自动读取 Dashboard 上的 secret,你需要使用 .dev.vars 或在本地模拟(详见下面「本地 secret 与 .dev.vars」)。 5) 部署并绑定到 Pages 域名(如果你想让 mulerun-rodin.pages.dev/api/* 触发 Worker)
方法 A(Dashboard):Cloudflare Dashboard → Workers → 选择你的 Worker → Routes → 添加 mulerun-rodin.pages.dev/api/*。这样访问 mulerun-rodin.pages.dev/api/... 时会先走 Worker。
方法 B(wrangler):在 wrangler.toml 填 route、zone_id 并 wrangler publish(这种方式通常需要 zone_id,获取 zone_id 可在 dash 或 API 查找)。
七、本地开发细节:.dev.vars 与 Vite 本地代理
开发时你不该把真实 token 放到仓库。两种常用方法:
- 用 .dev.vars(仅本地、NOT committed)来提供 env:
API_TOKEN = "LOCAL_FAKE_TOKEN"
GLOBAL_UPSTREAM_BASE = "https://api.example.com"wrangler dev 会读取 .dev.vars 并注入 env。 2. Vite 本地 dev 时,用 server.proxy 把 /api/v2 转发到 wrangler dev 本地地址(http://127.0.0.1:8787),从而在本地体验同域调用:
// vite.config.js
export default {
server: {
proxy: {
'/api/v2': 'http://127.0.0.1:8787'
}
}
}八、前端(React)如何调用代理
前端只需要像调用本地 API 一样调用相对路径,不带任何敏感 token:
// src/api.js
export async function callApi(path, data) {
const res = await fetch(`/api/v2/${path}`, {
method: data ? 'POST' : 'GET',
headers: { 'Content-Type': 'application/json' },
body: data ? JSON.stringify(data) : undefined,
credentials: 'same-origin',
});
if (!res.ok) { throw new Error(`HTTP ${res.status}`); }
return res.json();
}注意在本地开发时,若你没有运行 wrangler dev,可以在 Vite 中配置代理把 /api/v2 指向真实上游(仅用于开发,切勿把真实 token 放在前端 env 中)。
九、CORS、安全与注意事项
CORS:如果你把前端与 Functions/Worker 放在同域(pages domain),通常无需 CORS;如果跨域访问,需要在 Worker/Function 返回 Access-Control-Allow-Origin 等头。生产环境请替换 * 为具体域名。
不要把 token 写成 VITE_ 前缀的 env:Vite 中以 VITE_ 开头的环境变量会被打包进前端代码并能被浏览器看到 —— 绝对不要放敏感信息。
不要把 secret 写到 wrangler.toml 的 vars:那是明文。应该使用 wrangler secret put 或 Pages 的 secret 功能。
鉴权:Worker/Function 能隐藏后端 token,但仍需做业务级鉴权(比如用户身份验证、访问频率控制等),否则任何人都能调用代理(可以限制 origin / referer,但这些头可伪造)。更安全的方式是让前端先登录并带上用户 token(短期 token)进行二次校验,Worker 再用服务器 token 和上游服务沟通。 十、完整操作清单(Copy & Paste)
下面给出最常用的 Pages Functions 流程(你选择 Pages Functions 时照做):
在你的项目根创建 function 文件:
mkdir -p functions/api/v2
# 将上面的 [...path].js 内容粘贴进去在 Cloudflare Pages Dashboard 查看你的 project name(如 mulerun-rodin)。
本地开发(可选):
# 给本地 dev 用一个假的 token(仅本地)
cat > .dev.vars <<EOF
API_TOKEN = "LOCAL_FAKE_TOKEN"
GLOBAL_UPSTREAM_BASE = "https://api.example.com"
EOF
# 启动 wrangler dev(如果需要模拟 functions)
npx wrangler dev
# 启动 vite
npm run dev在 Pages 项目中添加 Secret(生产):
npx wrangler pages secret put API_TOKEN --project-name mulerun-rodin提交代码并 push(Cloudflare Pages 自动构建并部署)。部署后访问:
https://mulerun-rodin.pages.dev/api/v2/your/path
前端调用:
fetch('/api/v2/your/path') // 前端不包含 token,Worker/Function 注入 token 再转发十一、排错清单(常见问题)
请求返回 500,提示 API_TOKEN missing:说明 env 没注入 secret,确认你在 Pages Dashboard 或用 wrangler pages secret put 提交了 API_TOKEN。
本地 wrangler dev 看不到 secret:wrangler dev 不会自动读取 Dashboard 的 secret;用 .dev.vars 本地模拟或用 wrangler secret put(这会上传到 Cloudflare)。
CORS 报错(浏览器):检查 Worker/Function 是否在 OPTIONS 请求中返回 Access-Control-Allow-* 头。对 preflight(OPTIONS)要返回 200 并包含允许的 headers。
404:检查 functions 文件路径与请求路径是否匹配(Pages Functions 路径映射严格,catch-all 文件名要写对)。