news 2026/9/11 20:38:30

Cloudflare API 集成实战:多语言 SDK 客户端初始化、认证、分页与 Zone/DNS 管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cloudflare API 集成实战:多语言 SDK 客户端初始化、认证、分页与 Zone/DNS 管理

Cloudflare API 集成实战:多语言 SDK 客户端初始化、认证、分页与 Zone/DNS 管理

【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills

本篇技术指南以cloudflare-deploy技能中的 API 参考文档为主体,系统讲解如何通过官方 SDK(TypeScript / Python / Go)编程式调用 Cloudflare REST API,覆盖客户端初始化、两种认证方式、自动分页、错误处理,以及 Zone 与 DNS 记录的完整管理流程。读完本文,你将掌握在 Node、Python 与 Go 服务端环境中安全、高效地管理 Cloudflare 域与解析记录的实战方案,并能在遇到 429 限流、403 权限不足等典型问题时快速定位与解决。

背景:这份 API 参考在仓库中的定位

本文依据的文档位于仓库skills/.curated/cloudflare-deploy/references/api/目录,属于 Codex 技能目录中cloudflare-deploy技能(见 SKILL.md)的 API 参考资料。该技能面向"向 Cloudflare 部署应用与基础设施"的场景,其中 api/README.md 给出了调用方式的选择决策树:

  • Workers 运行时内调用 → 优先使用 Bindings(绑定),而非 REST API(绑定不计入 API 限流);
  • 服务端(Node/Python/Go)→ 使用官方 SDK,即本文主体内容;
  • CLI/脚本→ 使用 Wrangler 或curl
  • 基础设施即代码→ 参考同技能下的 Pulumi 或 Terraform;
  • 一次性请求→ 直接使用curl示例。

不同语言官方 SDK 的选型对比如下(数据来自 api/README.md):

语言包名适用场景默认重试次数
TypeScriptcloudflareNode.js、Bun、Next.js、Workers2
PythoncloudflareFastAPI、Django、脚本2
Gocloudflare-go/v4CLI 工具、微服务10

这些 SDK 均由 Stainless 依据 OpenAPI 规范自动生成,因此三者的 API 设计高度一致,学习成本可以一次投入、三处复用。

客户端初始化:三种官方 SDK 的入门写法

参考文档 api.md 首先给出三种语言的客户端初始化方式,这是所有后续调用的起点。

TypeScript

import Cloudflare from 'cloudflare'; const client = new Cloudflare({ apiToken: process.env.CLOUDFLARE_API_TOKEN, });

Python(同步与异步)

from cloudflare import Cloudflare client = Cloudflare(api_token=os.environ.get("CLOUDFLARE_API_TOKEN")) # 异步场景请使用 AsyncCloudflare from cloudflare import AsyncCloudflare client = AsyncCloudflare(api_token=os.environ["CLOUDFLARE_API_TOKEN"])

注意:同步客户端Cloudflare与异步客户端AsyncCloudflare不可混用——对同步客户端执行await会直接抛出TypeError(详见 gotchas.md 中的专项说明)。

Go

import ( "github.com/cloudflare/cloudflare-go/v4" "github.com/cloudflare/cloudflare-go/v4/option" ) client := cloudflare.NewClient( option.WithAPIToken(os.Getenv("CLOUDFLARE_API_TOKEN")), )

Go SDK 通过option包以函数选项(functional options)方式注入认证信息,后续配置超时、重试等同样走option.With*系列。

认证:API Token 与 API Key 两种方式

API Token(推荐)

创建路径:Dashboard(控制台)→ My Profile → API Tokens → Create Token。

创建后通过环境变量导出,并用curl验证连通性:

export CLOUDFLARE_API_TOKEN='your-token-here' curl "https://api.cloudflare.com/client/v4/zones" \ --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

权限原则:Token 的作用域(scopes)应始终使用最小权限——限定到具体 zone、设置有效期。这是推荐方式的原因:可细分授权、可单独轮换、可限定范围。

API Key(传统方式)

curl "https://api.cloudflare.com/client/v4/zones" \ --header "X-Auth-Email: user@example.com" \ --header "X-Auth-Key: $CLOUDFLARE_API_KEY"

不推荐原因:API Key 拥有完整账号访问权限,且无法按权限范围拆分。仅在遗留系统中保留使用。

环境变量与 .env 模式

configuration.md 给出了三种平台的设置方式:

平台命令
Linux/macOSexport CLOUDFLARE_API_TOKEN='token'
PowerShell$env:CLOUDFLARE_API_TOKEN = 'token'
Windows CMDset CLOUDFLARE_API_TOKEN=token

安全红线:绝不要将 Token 提交进版本库,使用.gitignore忽略的.env文件或密钥管理服务:

# .env(记得加入 .gitignore) CLOUDFLARE_API_TOKEN=your-token-here CLOUDFLARE_ACCOUNT_ID=your-account-id
// TypeScript 侧加载 .env import 'dotenv/config'; const client = new Cloudflare({ apiToken: process.env.CLOUDFLARE_API_TOKEN, });
# Python 侧加载 .env from dotenv import load_dotenv load_dotenv() client = Cloudflare(api_token=os.environ["CLOUDFLARE_API_TOKEN"])

三种认证方式的安全性对比(来自 api/README.md):

方法安全性适用场景权限范围
API Token可细分、可轮换生产环境按 zone 或账号
API Key + Email完整账号访问仅遗留系统一切
User Service Key受限仅 Origin CA 证书Origin CA

新项目一律使用 API Token。

自动分页:遍历全部结果而非只取第一页

Cloudflare API 的列表接口是分页返回的,默认页大小为 20(部分接口最大 50,见 gotchas.md)。三个官方 SDK 均内置自动分页能力,可以透明地拉取全部结果:

// TypeScript:for await...of for await (const zone of client.zones.list()) { console.log(zone.id); }
# Python:迭代器协议 for zone in client.zones.list(): print(zone.id)
// Go:ListAutoPaging iter := client.Zones.ListAutoPaging(ctx, cloudflare.ZoneListParams{}) for iter.Next() { zone := iter.Current() fmt.Println(zone.ID) }

这是一个高频踩坑点:若像下面这样只取一次返回结果,将只能拿到第一页(默认 20 条):

// ❌ 错误——仅第一页(20 条) const page = await client.zones.list(); // ✅ 正确——自动分页取全部 const zones = []; for await (const zone of client.zones.list()) { zones.push(zone); }

错误处理:错误类型体系与 SDK 自动重试

参考文档给出了 TypeScript 侧的典型错误处理写法:

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 auto-retries with backoff } else if (err instanceof Cloudflare.APIError) { console.log(err.status, err.message); } }

常见错误类型

错误类型状态码含义
AuthenticationError401Token 无效
PermissionDeniedError403权限范围不足
NotFoundError404资源不存在
RateLimitError429触发限流
InternalServerError≥500Cloudflare 侧故障

SDK 的行为(gotchas.md):对可重试错误自动进行指数退避重试(默认 2 次,Go 默认 10 次),并尊重服务端返回的Retry-After响应头;重试耗尽后抛出RateLimitError。因此业务代码只需捕获最终错误即可,无需自行实现退避(除特殊需求外)。

Python 异步客户端的常见误用

# ❌ 错误——同步客户端不可 await from cloudflare import Cloudflare client = Cloudflare() await client.zones.list() # TypeError # ✅ 正确——使用 AsyncCloudflare from cloudflare import AsyncCloudflare client = AsyncCloudflare() await client.zones.list()

Zone 管理:完整的 CRUD 流程

Zone(域名区域)管理是使用 Cloudflare 的第一步。参考文档给出 TypeScript 与 Go 的示例:

// 列出 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 SDK 由于要区分"零值、null、省略"三种状态,必须使用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), })

不写F()包装器会导致字段无法编译通过或发送时被忽略(gotchas.md 中专门指出了这个坑)。

条件更新模式

实际业务中常需要"先读后写"的条件判断(来自 patterns.md):

// 仅在 Zone 处于 active 状态时才执行更新 const zone = await client.zones.get({ zone_id: 'zone-id' }); if (zone.status === 'active') { await client.zones.edit(zone.id, { paused: false }); }

DNS 管理:记录的增删改查

DNS 记录是高频操作对象。参考文档给出 TypeScript 与 Python 示例:

// 创建 DNS 记录 await client.dns.records.create({ zone_id: 'zone-id', type: 'A', name: 'subdomain.example.com', content: '192.0.2.1', ttl: 1, // auto,自动 TTL 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_id="zone-id", type="A", name="subdomain.example.com", content="192.0.2.1", ttl=1, proxied=True, )

要点说明:ttl: 1表示自动 TTL(由 Cloudflare 自动决定缓存时长);proxied: true即开启"橙色云朵",流量经 Cloudflare 代理(获得 CDN、DDoS 防护等能力)。

DNS 批量更新:更换源站 IP

配合自动分页,可以高效完成全量 A 记录的 IP 迁移(来自 patterns.md):

// 1. 抓取全部 A 记录 const records = []; for await (const record of client.dns.records.list({ zone_id: 'zone-id', type: 'A', })) { records.push(record); } // 2. 并行更新到新 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); } }

SDK 配置:超时、重试与 Base URL

configuration.md 汇总了三语言 SDK 的配置项:

配置项TypeScriptPythonGo默认值
超时timeout(毫秒)timeout(秒)WithRequestTimeout60 秒
重试次数maxRetriesmax_retriesWithMaxRetries2(Go 为 10)
Base URLbaseURLbase_urlWithBaseURLapi.cloudflare.com
const client = new Cloudflare({ apiToken: process.env.CLOUDFLARE_API_TOKEN, timeout: 120000, // 2 分钟(默认 60 秒),单位毫秒 maxRetries: 5, // 默认 2 baseURL: 'https://...', // 代理场景(罕见) }); // 单次请求级覆盖 await client.zones.get( { zone_id: 'zone-id' }, { timeout: 5000, maxRetries: 0 } );
client = Cloudflare( api_token=os.environ["CLOUDFLARE_API_TOKEN"], timeout=120, # 秒(默认 60) max_retries=5, # 默认 2 base_url="https://...", # 代理(罕见) ) # 单次请求级覆盖 client.with_options(timeout=5, max_retries=0).zones.get(zone_id="zone-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 分钟 });

何时调整重试

  • 调大:限流频繁的工作流、网络不稳定环境;
  • 调小:需要快速失败的场景、面向用户的请求(不应让用户久等)。
// 批量操作加大重试 const client = new Cloudflare({ maxRetries: 10 }); // 快速失败:关闭重试 const fastClient = new Cloudflare({ maxRetries: 0 });

可复用客户端实例

生产代码建议将客户端封装为可复用实例并集中管理(gotchas.md):

// 创建可复用客户端实例 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 }); }

限流与典型排错要点

实际限流阈值

限额数值说明
API 限流1200 次 / 5 分钟按用户/Token
IP 限流200 次 / 秒按 IP 地址
GraphQL 限流320 / 5 分钟基于成本计算
推荐并行请求数< 10避免压垮 API
默认页大小20使用自动分页
最大页大小50部分接口

限流应对方案(gotchas.md):

// 加大重试应对限流密集工作流 const client = new Cloudflare({ maxRetries: 5 }); // 应用层节流 import pLimit from 'p-limit'; const limit = pLimit(10); // 最多 10 个并发请求

403 权限不足

症状:Token 有效但仍返回 403 Forbidden。原因:Token 缺少所需权限(scope)。常见操作所需权限对照:

操作所需 Scope
列出 ZoneZone:Read(zone 级或账号级)
创建 ZoneZone:Edit(账号级)
编辑 DNSDNS:Edit(zone 级)
部署 WorkerWorkers Script:Edit(账号级)
读取 KVWorkers KV Storage:Read
写入 KVWorkers KV Storage:Edit

解决:在 Dashboard → My Profile → API Tokens 中重新创建带正确权限的 Token。

401 认证失败

常见原因: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);

Zone 返回 404

可能原因:Zone 不在该 Token 关联的账号下、Zone 已删除、Zone ID 格式错误。排查方式:列出全部 Zone 找出正确 ID:

for await (const zone of client.zones.list()) { console.log(zone.id, zone.name); }

超时与分批处理

默认 60 秒超时在大批量操作(如批量 DNS、Zone 迁移)下容易触发,除调大超时外,还可以将操作分批:

const batchSize = 100; for (let i = 0; i < records.length; i += batchSize) { const batch = records.slice(i, i + batchSize); await processBatch(batch); }

Workers 内避免直接调用 REST API

在 Workers 运行时内,每一次 REST API 子请求都会计入限流配额,因此应改用绑定(Bindings)访问资源(gotchas.md):

// ❌ 错误——Workers 内走 REST API(计入限流) const client = new Cloudflare({ apiToken: env.CLOUDFLARE_API_TOKEN }); const zones = await client.zones.list(); // ✅ 正确——使用 Bindings(不限流) // 通过 env.MY_BINDING 直接访问

实战模式:批量并行与错误恢复

patterns.md 收录了几组高频实战模式。

并行批量创建(注意控制并发)

// 创建多个 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);

受控并发(避免触发限流):

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);

限流感知的指数退避重试

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,单个失败不影响整体 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); } });

与 Wrangler CLI 的衔接

同一技能下还有 Wrangler 参考。Wrangler 本身也是基于这套 API 工作,可作为命令行替代方案:

# 配置认证 wrangler login # 或 export CLOUDFLARE_API_TOKEN='token' # 常用命令(底层均调用 API) wrangler deploy # 通过 API 上传 Worker wrangler kv:key put # KV 操作 wrangler r2 bucket create # R2 操作 wrangler d1 execute # D1 操作 wrangler pages deploy # Pages 操作 # 查看 API 配置 wrangler whoami # 显示已认证用户

部署前建议先用npx wrangler whoami确认认证状态(SKILL.md 的部署前置要求);CI/CD 场景则直接设置CLOUDFLARE_API_TOKEN环境变量。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

最佳实践小结

安全(来自 gotchas.md):

  • 绝不提交 Token 到版本库;
  • 始终使用最小权限;
  • 定期轮换 Token;
  • 为 Token 设置有效期。

性能

  • 批量操作;
  • 善用自动分页;
  • 缓存响应;
  • 妥善处理限流(加大重试或应用层节流)。

代码组织

  • 创建可复用的客户端单例并集中导出;
  • 将常用操作封装成带业务语义的函数;
  • 对限流密集场景显式加大maxRetries,对用户面请求关闭重试实现快速失败。

延伸阅读

  • SDK 配置与环境变量:三语言 SDK 的 timeout / retries / baseURL 配置、Wrangler 集成
  • 真实世界模式与工作流:批量并行、DNS 批量更新、限流恢复等完整示例
  • 限流与排错:429 限流阈值、403 权限映射、SDK 专属坑位
  • API 参考入口:调用方式决策树与阅读顺序
  • Cloudflare 部署技能总览:技能整体结构与部署前置要求
  • Bindings 参考:Workers 运行时内优先使用的资源访问方式
  • Wrangler 参考:CLI 工具的使用细节与认证方式

【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 20:34:17

ML-KWS-for-MCU源码级评测:Cortex-M上语音唤醒的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 20:33:50

2.4GHz同轴馈线选型实战指南:L50与L100深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 20:33:30

计算机毕业设计之jsp小区物业管理系统

随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;小区物业管理系统也不例外&#xff0c;但目前不少小区仍都使用人工管理&#xff0c;小区规模越来越大&#xff0c;小区信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#xff0…

作者头像 李华