)
Cloudflare REST API 集成完全指南认证、SDK 配置、限流与实战模式cloudflare-deploy Skill【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills本篇指南以 cloudflare-deploy Skill 中 api 参考目录 为核心骨架系统讲解如何通过 Cloudflare REST API 完成认证、SDK 客户端初始化、自动分页、错误处理、Zone 与 DNS 管理等开发工作。读完你将掌握 TypeScript / Python / Go 三种官方 SDK 的初始化与配置方法、API Token 与 API Key 两种认证方式的取舍、速率限制规避策略以及批量操作、错误恢复等可复用的实战代码模式。何时使用 REST API先看决策树Cloudflare 提供 REST API、Workers 运行时 Bindings、CLIWrangler和基础设施即代码IaC等多种编程接口选用前应先根据调用场景做判断。原文档给出的决策树如下How are you calling the Cloudflare API? ├─ From Workers runtime → Use bindings, not REST API (see ../bindings/) ├─ Server-side (Node/Python/Go) → Official SDK (see api.md) ├─ CLI/scripts → Wrangler or curl (see configuration.md) ├─ Infrastructure-as-code → See ../pulumi/ or ../terraform/ └─ One-off requests → curl examples (see api.md)要点归纳Workers 运行时内优先使用 Bindings而非 REST API。Bindings 在运行时零开销、不消耗 API 速率配额是 Workers 场景下的首选详见下文“Workers 子请求”一节。服务端应用Node/Python/Go使用官方 SDK见 api.md。脚本与 CLI 场景使用 Wrangler 或 curl配置方法见 configuration.md。基础设施即代码转向 Pulumi 或 Terraform 参考。一次性临时请求直接用 curl 示例即可。SDK 选型三种语言如何选择Cloudflare 官方提供 TypeScript、Python、Go 三套 SDK全部由 Stainless 根据 OpenAPI 规范生成因此三者的 API 形态高度一致学习成本可跨语言复用。选型对照如下语言包名最适合场景默认重试次数TypeScriptcloudflareNode.js、Bun、Next.js、Workers2PythoncloudflareFastAPI、Django、脚本2Gocloudflare-go/v4CLI 工具、微服务10需要注意Go SDK 的默认重试次数10 次明显高于 TypeScript / Python2 次这是三套 SDK 之间最值得留意的行为差异见 configuration.md。认证方式API Token 是唯一推荐项方法安全性使用场景权限范围API Token推荐可限定权限、可轮换生产环境按 Zone 或按账户API Key Email拥有完整账户权限无法细化仅限遗留系统全部资源User Service Key受限仅用于 Origin CA 证书Origin CA新项目一律使用 API Token。原文档强调 Token 始终遵循最小权限原则zone 级、限时有效。创建入口为Dashboard → My Profile → API Tokens → Create Token。创建 Token 后可通过环境变量或 curl 立即验证export CLOUDFLARE_API_TOKENyour-token-here curl https://api.cloudflare.com/client/v4/zones \ --header Authorization: Bearer $CLOUDFLARE_API_TOKENAPI Key 方式仅遗留场景使用X-Auth-Email与X-Auth-Key两个请求头curl https://api.cloudflare.com/client/v4/zones \ --header X-Auth-Email: userexample.com \ --header X-Auth-Key: $CLOUDFLARE_API_KEY不推荐 API Key它拥有完整账户访问权限无法按资源范围收缩权限。关于 Token 权限不足导致的 403 错误排查见下文“Token 权限不足403”一节。客户端初始化三语对照TypeScriptimport Cloudflare from cloudflare; const client new Cloudflare({ apiToken: process.env.CLOUDFLARE_API_TOKEN, });Pythonfrom cloudflare import Cloudflare client Cloudflare(api_tokenos.environ.get(CLOUDFLARE_API_TOKEN)) # 异步场景使用 AsyncCloudflare from cloudflare import AsyncCloudflare client AsyncCloudflare(api_tokenos.environ[CLOUDFLARE_API_TOKEN])Goimport ( github.com/cloudflare/cloudflare-go/v4 github.com/cloudflare/cloudflare-go/v4/option ) client : cloudflare.NewClient( option.WithAPIToken(os.Getenv(CLOUDFLARE_API_TOKEN)), )Go 版本要求使用cloudflare-go/v4模块并配合option包以函数式选项注入 API Token。SDK 配置环境变量、超时与重试环境变量与 .env平台命令Linux/macOSexport CLOUDFLARE_API_TOKENtokenPowerShell$env:CLOUDFLARE_API_TOKEN tokenWindows CMDset CLOUDFLARE_API_TOKENtoken安全铁律绝不把 Token 提交进版本库。使用.env文件加入.gitignore或密钥管理服务。# .env记得加入 .gitignore CLOUDFLARE_API_TOKENyour-token-here CLOUDFLARE_ACCOUNT_IDyour-account-id// TypeScript import dotenv/config; const client new Cloudflare({ apiToken: process.env.CLOUDFLARE_API_TOKEN, });# Python from dotenv import load_dotenv load_dotenv() client Cloudflare(api_tokenos.environ[CLOUDFLARE_API_TOKEN])核心配置项选项TypeScriptPythonGo默认值超时timeout毫秒timeout秒WithRequestTimeout60s重试maxRetriesmax_retriesWithMaxRetries2Go 为 10Base URLbaseURLbase_urlWithBaseURLapi.cloudflare.com三语配置示例const client new Cloudflare({ apiToken: process.env.CLOUDFLARE_API_TOKEN, timeout: 120000, // 2 分钟默认 60s单位为毫秒 maxRetries: 5, // 默认 2 baseURL: https://..., // 代理场景罕见 }); // 单次请求覆盖配置 await client.zones.get( { zone_id: zone-id }, { timeout: 5000, maxRetries: 0 } );client Cloudflare( api_tokenos.environ[CLOUDFLARE_API_TOKEN], timeout120, # 秒默认 60 max_retries5, # 默认 2 base_urlhttps://..., # 代理场景罕见 ) # 单次请求覆盖配置 client.with_options(timeout5, max_retries0).zones.get(zone_idzone-id)client : cloudflare.NewClient( option.WithAPIToken(os.Getenv(CLOUDFLARE_API_TOKEN)), option.WithMaxRetries(5), // 默认 10高于 TS/Python option.WithRequestTimeout(2 * time.Minute), // 默认 60s option.WithBaseURL(https://...), // 代理场景罕见 ) // 单次请求覆盖配置 client.Zones.Get(ctx, zone-id, option.WithMaxRetries(0))何时调整超时与重试需要调高超时的场景大型 Zone 迁移、批量 DNS 操作、Worker 脚本上传例如const client new Cloudflare({ timeout: 300000, // 5 分钟 });重试策略调高重试限流密集的工作流、网络不稳定环境maxRetries: 10。调低或关闭重试需要快速失败的场景、面向用户的前端请求maxRetries: 0。// 批量操作提高重试 const client new Cloudflare({ maxRetries: 10 }); // 快速失败场景关闭重试 const fastClient new Cloudflare({ maxRetries: 0 });速率限制配额与 SDK 自动重试原文档给出的限制基线详见 gotchas.md限制项数值每用户/Token1200 次请求 / 5 分钟每 IP200 次请求 / 秒GraphQL320 / 5 分钟基于成本计费SDK 内置行为指数退避自动重试默认 2 次Go 为 10 次尊重Retry-After响应头重试耗尽后抛出RateLimitError429。自动分页与错误处理自动分页所有官方 SDK 对 list 类操作都内置自动分页无需手工翻页// TypeScriptfor await...of for await (const zone of client.zones.list()) { console.log(zone.id); }# Python迭代器协议 for zone in client.zones.list(): print(zone.id)// GoListAutoPaging iter : client.Zones.ListAutoPaging(ctx, cloudflare.ZoneListParams{}) for iter.Next() { zone : iter.Current() fmt.Println(zone.ID) }分页截断陷阱直接await client.zones.list()只返回第一页默认每页 20 条。要拿到全部结果必须用自动分页迭代器遍历见下文“常见坑”小节。错误类型与处理try { const zone await client.zones.get({ zone_id: xxx }); } catch (err) { if (err instanceof Cloudflare.NotFoundError) { // 404 } else if (err instanceof Cloudflare.RateLimitError) { // 429 - SDK 已自动退避重试 } else if (err instanceof Cloudflare.APIError) { console.log(err.status, err.message); } }常用错误类型对照错误类型HTTP 状态含义AuthenticationError401Token 无效PermissionDeniedError403权限范围不足NotFoundError404资源不存在RateLimitError429触发速率限制InternalServerError≥500Cloudflare 服务端错误核心操作Zone 管理与 DNS 管理Zone 生命周期创建、读取、更新、删除// 列出 Zone const zones await client.zones.list({ account: { id: account-id }, status: active, }); // 创建 Zone const zone await client.zones.create({ account: { id: account-id }, name: example.com, type: full, // 或 partial }); // 更新 Zone await client.zones.edit(zone-id, { paused: false, }); // 删除 Zone await client.zones.delete(zone-id);Go 版本注意必须使用cloudflare.F()包装器包裹字段// Go需要 cloudflare.F() 包装 zone, err : client.Zones.New(ctx, cloudflare.ZoneNewParams{ Account: cloudflare.F(cloudflare.ZoneNewParamsAccount{ ID: cloudflare.F(account-id), }), Name: cloudflare.F(example.com), Type: cloudflare.F(cloudflare.ZoneNewParamsTypeFull), })DNS 记录管理// 创建 DNS 记录 await client.dns.records.create({ zone_id: zone-id, type: A, name: subdomain.example.com, content: 192.0.2.1, ttl: 1, // auto proxied: true, // 橙色云朵开启代理 }); // 列出 DNS 记录自动分页 for await (const record of client.dns.records.list({ zone_id: zone-id, type: A, })) { console.log(record.name, record.content); } // 更新 DNS 记录 await client.dns.records.update({ zone_id: zone-id, dns_record_id: record-id, type: A, name: subdomain.example.com, content: 203.0.113.1, proxied: true, }); // 删除 DNS 记录 await client.dns.records.delete({ zone_id: zone-id, dns_record_id: record-id, });# Python 示例 client.dns.records.create( zone_idzone-id, typeA, namesubdomain.example.com, content192.0.2.1, ttl1, proxiedTrue, )实战模式可复用的代码骨架以下模式均来自 patterns.md可直接迁移到生产代码。限流场景下的重试与并发控制// 提高重试次数应对限流 const client new Cloudflare({ maxRetries: 5 }); try { const zone await client.zones.create({ /* ... */ }); } catch (err) { if (err instanceof Cloudflare.RateLimitError) { // 已经过 5 次退避重试仍失败 const retryAfter err.headers[retry-after]; console.log(Rate limited. Retry after ${retryAfter}s); } }批量并行创建配合并发上限// 并行创建多个 DNS 记录注意限流 const records [www, api, cdn].map(subdomain client.dns.records.create({ zone_id: zone-id, type: A, name: ${subdomain}.example.com, content: 192.0.2.1, }) ); await Promise.all(records);控制并发推荐并行数低于 10避免打满 API 配额import pLimit from p-limit; const limit pLimit(10); // 最多 10 个并发 const subdomains [www, api, cdn, /* 更多 */]; const records subdomains.map(subdomain limit(() client.dns.records.create({ zone_id: zone-id, type: A, name: ${subdomain}.example.com, content: 192.0.2.1, })) ); await Promise.all(records);Zone CRUD 工作流// 创建 const zone await client.zones.create({ account: { id: account-id }, name: example.com, type: full, }); // 读取 const fetched await client.zones.get({ zone_id: zone.id }); // 更新 await client.zones.edit(zone.id, { paused: false }); // 删除 await client.zones.delete(zone.id);DNS 批量更新全量 A 记录指向新 IP// 拉取全部 A 记录 const records []; for await (const record of client.dns.records.list({ zone_id: zone-id, type: A, })) { records.push(record); } // 全部更新到新 IP await Promise.all(records.map(record client.dns.records.update({ zone_id: zone-id, dns_record_id: record.id, type: A, name: record.name, content: 203.0.113.1, // 新 IP proxied: record.proxied, ttl: record.ttl, }) ));过滤收集结果// 找出所有已开启代理的 A 记录 const proxiedRecords []; for await (const record of client.dns.records.list({ zone_id: zone-id, type: A, })) { if (record.proxied) { proxiedRecords.push(record); } }错误恢复限流重试函数async function createZoneWithRetry(name: string, maxAttempts 3) { for (let attempt 1; attempt maxAttempts; attempt) { try { return await client.zones.create({ account: { id: account-id }, name, type: full, }); } catch (err) { if (err instanceof Cloudflare.RateLimitError attempt maxAttempts) { const retryAfter parseInt(err.headers[retry-after] || 5); console.log(Rate limited, waiting ${retryAfter}s (retry ${attempt}/${maxAttempts})); await new Promise(resolve setTimeout(resolve, retryAfter * 1000)); } else { throw err; } } } }条件更新与批量容错// 仅当 Zone 处于 active 状态才更新 const zone await client.zones.get({ zone_id: zone-id }); if (zone.status active) { await client.zones.edit(zone.id, { paused: false }); }// 批量处理多个 Zone单个失败不中断整体 const results await Promise.allSettled( zoneIds.map(id client.zones.get({ zone_id: id })) ); results.forEach((result, i) { if (result.status fulfilled) { console.log(Zone ${i}: ${result.value.name}); } else { console.error(Zone ${i} failed:, result.reason.message); } });常见坑与排错本节汇总 gotchas.md 中的高频问题与解决方案。Go必填字段包装器cloudflare.F()Go SDK 为区分“零值 / null / 未传字段”要求可选字段必须用cloudflare.F()包装// 错误写法不编译或字段不会发送 client.Zones.New(ctx, cloudflare.ZoneNewParams{ Name: example.com, }) // 正确写法 client.Zones.New(ctx, cloudflare.ZoneNewParams{ Name: cloudflare.F(example.com), Account: cloudflare.F(cloudflare.ZoneNewParamsAccount{ ID: cloudflare.F(account-id), }), })Python同步与异步客户端混用# 错误写法同步客户端不能 await from cloudflare import Cloudflare client Cloudflare() await client.zones.list() # TypeError # 正确写法使用 AsyncCloudflare from cloudflare import AsyncCloudflare client AsyncCloudflare() await client.zones.list()Token 权限不足403Token 本身有效但返回 403通常是权限范围不足。常见操作所需权限如下操作所需权限列出 ZoneZone:ReadZone 级或账户级创建 ZoneZone:Edit账户级编辑 DNSDNS:EditZone 级部署 WorkerWorkers Script:Edit账户级读取 KVWorkers KV Storage:Read写入 KVWorkers KV Storage:Edit解决Dashboard → My Profile → API Tokens 中重建带正确权限的 Token。分页截断只拿到前 20 条// 错误写法只有第一页20 条 const page await client.zones.list(); // 正确写法拿到全部结果 const zones []; for await (const zone of client.zones.list()) { zones.push(zone); }Workers 子请求更快触达限流在 Workers 运行时内直接调用 REST API每次调用都计入速率配额比预期更快触发限流。正确做法是改用 Bindings绑定访问不计入 API 限流// 错误写法Workers 内走 REST API计入限流 const client new Cloudflare({ apiToken: env.CLOUDFLARE_API_TOKEN }); const zones await client.zones.list(); // 正确写法使用绑定无限流 // 通过 env.MY_BINDING 访问认证失败401可能原因Token 过期、被删除/吊销、环境变量未设置、Token 格式错误。建议在代码入口显式校验 Token并通过 Token 校验接口自测// 校验 Token 已设置 if (!process.env.CLOUDFLARE_API_TOKEN) { throw new Error(CLOUDFLARE_API_TOKEN not set); } // 测试 Token 有效性 const user await client.user.tokens.verify(); console.log(Token valid:, user.status);超时默认 60 秒常见于批量 DNS、Zone 迁移等大操作。处理手段调高超时或拆分批次// 调高超时 const client new Cloudflare({ timeout: 300000, // 5 分钟 }); // 或分批处理 const batchSize 100; for (let i 0; i records.length; i batchSize) { const batch records.slice(i, i batchSize); await processBatch(batch); }Zone 404ID 有效却找不到可能原因Zone 不在 Token 关联的账户下、Zone 已被删除、Zone ID 格式错误。可先列出全部 Zone 核对 IDfor await (const zone of client.zones.list()) { console.log(zone.id, zone.name); }限制速查表资源/限制数值说明API 速率限制1200/5min按用户/TokenIP 速率限制200/sec按 IPGraphQL 速率限制320/5min基于成本计费并行请求建议 10避免压垮 API默认页大小20使用自动分页最大页大小50部分端点与 Wrangler CLI 协同REST API 之外的脚本化运维可借助 Wrangler CLIWrangler 参考# 配置认证 wrangler login # 或 export CLOUDFLARE_API_TOKENtoken # 常用 API 相关命令 wrangler deploy # 通过 API 上传 Worker wrangler kv:key put # KV 操作 wrangler r2 bucket create # R2 操作 wrangler d1 execute # D1 操作 wrangler pages deploy # Pages 操作 # 查看认证信息 wrangler whoami # 显示当前认证用户wrangler.toml示例name my-worker main src/index.ts compatibility_date 2024-01-01 account_id your-account-id # 也可用环境变量 # CLOUDFLARE_ACCOUNT_ID # CLOUDFLARE_API_TOKEN在 cloudflare-deploy Skill 的整体流程中部署前建议先执行npx wrangler whoami验证认证状态见 SKILL.md。最佳实践汇总安全方面绝不提交 Token 到版本库使用最小权限原则定期轮换 Token为 Token 设置过期时间。性能方面批量操作代替逐个调用合理使用自动分页缓存响应妥善处理限流。代码组织// 创建可复用的客户端单例 export const cfClient new Cloudflare({ apiToken: process.env.CLOUDFLARE_API_TOKEN, maxRetries: 5, }); // 封装常用操作 export async function getZoneDetails(zoneId: string) { return await cfClient.zones.get({ zone_id: zoneId }); }参考阅读路径按任务选择合适的文档任务阅读文件初始化 SDK 客户端api.md配置认证/超时/重试configuration.md查找使用模式patterns.md排查错误与限流gotchas.md产品级 APIWorkers/R2/KV 等workers、r2、kv 等Workers 运行时绑定REST API 的替代方案bindingsWrangler CLI 细节wrangler核心结论一句话服务端应用直接使用官方 SDK 并优先 API TokenWorkers 运行时改用 Bindings脚本运维交给 Wrangler批量与高并发场景务必做好并发控制与重试策略。【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考