跳转到内容
搜索文档

API 示例

最后更新 查看 MarkdownAgent 设置

以下示例展示如何使用 Cloudflare 的 REST API 与 TypeScript SDK 以编程方式部署与管理 Workers。

前提条件

使用这些示例之前,你需要:

  • 你的 Account ID - 可在 Cloudflare 仪表板 URL 或 API 设置中找到
  • 一个分派命名空间 - 通过仪表板创建
  • 具有 Workers 权限的 API token(API 令牌) - 在 API Tokens 创建

对于 SDK 示例,安装 Cloudflare SDK:

npm install cloudflare

部署用户 Worker

将 Worker 脚本上传到你的分派命名空间。这是客户部署代码时你的平台执行的主要操作。

# First, create the worker script file
cat > worker.mjs << 'EOF'
export default {
  async fetch(request, env, ctx) {
    return new Response("Hello from user Worker!");
  },
};
EOF

# Deploy using multipart form (required for ES modules)
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \
  -H "Authorization: Bearer $API_TOKEN" \
  -F 'metadata={"main_module": "worker.mjs"};type=application/json' \
  -F 'worker.mjs=@worker.mjs;type=application/javascript+module'
import Cloudflare from "cloudflare";

const client = new Cloudflare({
	apiToken: process.env.API_TOKEN,
});

async function deployUserWorker(
	accountId: string,
	namespace: string,
	scriptName: string,
	scriptContent: string,
) {
	const scriptFile = new File([scriptContent], `${scriptName}.mjs`, {
		type: "application/javascript+module",
	});

	const result =
		await client.workersForPlatforms.dispatch.namespaces.scripts.update(
			namespace,
			scriptName,
			{
				account_id: accountId,
				metadata: {
					main_module: `${scriptName}.mjs`,
				},
				files: [scriptFile],
			},
		);

	return result;
}

// Usage
await deployUserWorker(
	"your-account-id",
	"production",
	"customer-123",
	`export default {
  async fetch(request, env, ctx) {
    return new Response("Hello from customer 123!");
  },
};`,
);

使用绑定与标签部署

使用绑定(bindings) 为每个用户 Worker 提供自己的资源(例如 KV 存储或数据库)。使用标签(tags) 按客户 ID、项目 ID 或计划类型组织 Worker,以便批量操作。

以下示例展示如何部署带有自己的 KV namespace 并附加标签的 Worker:

curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \
  -H "Authorization: Bearer $API_TOKEN" \
  -F 'metadata={"main_module": "worker.mjs", "bindings": [{"type": "kv_namespace", "name": "MY_KV", "namespace_id": "your-kv-namespace-id"}], "tags": ["customer-123", "production", "pro-plan"], "compatibility_date": "2024-01-01"};type=application/json' \
  -F 'worker.mjs=@worker.mjs;type=application/javascript+module'
import Cloudflare from "cloudflare";

const client = new Cloudflare({
	apiToken: process.env.API_TOKEN,
});

async function deployWorkerWithBindingsAndTags(
	accountId: string,
	namespace: string,
	scriptName: string,
	scriptContent: string,
	kvNamespaceId: string,
	tags: string[],
) {
	const scriptFile = new File([scriptContent], `${scriptName}.mjs`, {
		type: "application/javascript+module",
	});

	const result =
		await client.workersForPlatforms.dispatch.namespaces.scripts.update(
			namespace,
			scriptName,
			{
				account_id: accountId,
				metadata: {
					main_module: `${scriptName}.mjs`,
					compatibility_date: "2024-01-01",
					bindings: [
						{
							type: "kv_namespace",
							name: "MY_KV",
							namespace_id: kvNamespaceId,
						},
					],
					tags: tags, // e.g., ["customer-123", "production", "pro-plan"]
				},
				files: [scriptFile],
			},
		);

	return result;
}

// Usage
const scriptContent = `export default {
  async fetch(request, env, ctx) {
    const value = await env.MY_KV.get("key") || "default";
    return new Response(value);
  },
};`;

await deployWorkerWithBindingsAndTags(
	"your-account-id",
	"production",
	"customer-123-app",
	scriptContent,
	"kv-namespace-id",
	["customer-123", "production", "pro-plan"],
);

更多信息请参阅绑定标签

部署带静态资源的 Worker

部署提供静态文件(HTML、CSS、JavaScript、图片)的 Worker。这是一个三步流程:

  1. 使用文件清单创建上传会话
  2. 上传资源文件
  3. 使用 assets 绑定部署 Worker

有关静态资源配置与选项的更多详情,请参阅静态资源

步骤 1:创建上传会话

curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME/assets-upload-session" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "manifest": {
      "/index.html": {
        "hash": "<sha256-hash-first-16-bytes-hex>",
        "size": 1234
      },
      "/styles.css": {
        "hash": "<sha256-hash-first-16-bytes-hex>",
        "size": 567
      }
    }
  }'

响应包含 jwt 令牌与 buckets 数组,指示哪些文件需要上传。

步骤 2:上传资源

curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/assets/upload?base64=true" \
  -H "Authorization: Bearer $JWT_FROM_STEP_1" \
  -F '<hash1>=<base64-encoded-content>' \
  -F '<hash2>=<base64-encoded-content>'

步骤 3:使用 assets 部署 Worker

curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \
  -H "Authorization: Bearer $API_TOKEN" \
  -F 'metadata={"main_module": "worker.mjs", "assets": {"jwt": "<completion-token>"}, "bindings": [{"type": "assets", "name": "ASSETS"}]};type=application/json' \
  -F 'worker.mjs=export default { async fetch(request, env) { return env.ASSETS.fetch(request); } };type=application/javascript+module'
interface AssetFile {
	path: string; // e.g., "/index.html"
	content: string; // base64 encoded content
	size: number; // file size in bytes
}

async function hashContent(base64Content: string): Promise<string> {
	const binaryString = atob(base64Content);
	const bytes = new Uint8Array(binaryString.length);
	for (let i = 0; i < binaryString.length; i++) {
		bytes[i] = binaryString.charCodeAt(i);
	}
	const hashBuffer = await crypto.subtle.digest("SHA-256", bytes);
	const hashArray = Array.from(new Uint8Array(hashBuffer));
	// Use first 16 bytes (32 hex chars) per API requirement
	return hashArray
		.slice(0, 16)
		.map((b) => b.toString(16).padStart(2, "0"))
		.join("");
}

async function deployWorkerWithAssets(
	accountId: string,
	namespace: string,
	scriptName: string,
	assets: AssetFile[],
) {
	const apiToken = process.env.API_TOKEN;
	const baseUrl = `https://api.cloudflare.com/client/v4/accounts/${accountId}/workers`;

	// Step 1: Build manifest
	const manifest: Record<string, { hash: string; size: number }> = {};
	const hashToAsset = new Map<string, AssetFile>();

	for (const asset of assets) {
		const hash = await hashContent(asset.content);
		const path = asset.path.startsWith("/") ? asset.path : "/" + asset.path;
		manifest[path] = { hash, size: asset.size };
		hashToAsset.set(hash, asset);
	}

	// Step 2: Create upload session
	const sessionResponse = await fetch(
		`${baseUrl}/dispatch/namespaces/${namespace}/scripts/${scriptName}/assets-upload-session`,
		{
			method: "POST",
			headers: {
				Authorization: `Bearer ${apiToken}`,
				"Content-Type": "application/json",
			},
			body: JSON.stringify({ manifest }),
		},
	);

	const sessionData = (await sessionResponse.json()) as {
		success: boolean;
		result?: { jwt: string; buckets?: string[][] };
	};

	if (!sessionData.success || !sessionData.result) {
		throw new Error("Failed to create upload session");
	}

	let completionToken = sessionData.result.jwt;
	const buckets = sessionData.result.buckets;

	// Step 3: Upload assets in buckets
	if (buckets && buckets.length > 0) {
		for (const bucket of buckets) {
			const formData = new FormData();
			for (const hash of bucket) {
				const asset = hashToAsset.get(hash);
				if (asset) {
					formData.append(hash, asset.content);
				}
			}

			const uploadResponse = await fetch(
				`${baseUrl}/assets/upload?base64=true`,
				{
					method: "POST",
					headers: { Authorization: `Bearer ${completionToken}` },
					body: formData,
				},
			);

			const uploadData = (await uploadResponse.json()) as {
				success: boolean;
				result?: { jwt?: string };
			};

			if (uploadData.result?.jwt) {
				completionToken = uploadData.result.jwt;
			}
		}
	}

	// Step 4: Deploy worker with assets binding
	const workerCode = `
export default {
  async fetch(request, env) {
    return env.ASSETS.fetch(request);
  }
};`;

	const deployFormData = new FormData();
	const metadata = {
		main_module: `${scriptName}.mjs`,
		assets: { jwt: completionToken },
		bindings: [{ type: "assets", name: "ASSETS" }],
	};

	deployFormData.append(
		"metadata",
		new Blob([JSON.stringify(metadata)], { type: "application/json" }),
	);
	deployFormData.append(
		`${scriptName}.mjs`,
		new Blob([workerCode], { type: "application/javascript+module" }),
	);

	const deployResponse = await fetch(
		`${baseUrl}/dispatch/namespaces/${namespace}/scripts/${scriptName}`,
		{
			method: "PUT",
			headers: { Authorization: `Bearer ${apiToken}` },
			body: deployFormData,
		},
	);

	return deployResponse.json();
}

// Usage
await deployWorkerWithAssets("your-account-id", "production", "customer-site", [
	{
		path: "/index.html",
		content: btoa("<html><body>Hello World</body></html>"),
		size: 37,
	},
	{
		path: "/styles.css",
		content: btoa("body { font-family: sans-serif; }"),
		size: 33,
	},
]);

列出 namespace 中的 Worker

检索部署到 namespace 的所有用户 Worker。

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts" \
  -H "Authorization: Bearer $API_TOKEN"
async function listWorkers(accountId: string, namespace: string) {
	const response = await fetch(
		`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/dispatch/namespaces/${namespace}/scripts`,
		{
			headers: {
				Authorization: `Bearer ${process.env.API_TOKEN}`,
			},
		},
	);

	const data = (await response.json()) as {
		success: boolean;
		result: Array<{ id: string; tags?: string[] }>;
	};

	return data.result;
}

// Usage
const workers = await listWorkers("your-account-id", "production");
console.log(workers);

按标签删除 Worker

删除匹配标签筛选器的所有 Worker。当客户删除账户且你需要一次性移除其所有 Worker 时,这很有用。

删除所有标记为 customer-123 的 Worker:

curl -X DELETE "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts?tags=customer-123:yes" \
  -H "Authorization: Bearer $API_TOKEN"
async function deleteWorkersByTag(
	accountId: string,
	namespace: string,
	tag: string,
) {
	const response = await fetch(
		`https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/dispatch/namespaces/${namespace}/scripts?tags=${tag}:yes`,
		{
			method: "DELETE",
			headers: {
				Authorization: `Bearer ${process.env.API_TOKEN}`,
			},
		},
	);

	return response.json();
}

// Usage: Delete all Workers for a customer
await deleteWorkersByTag("your-account-id", "production", "customer-123");

删除单个 Worker

按名称删除特定 Worker。

curl -X DELETE "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \
  -H "Authorization: Bearer $API_TOKEN"
import Cloudflare from "cloudflare";

const client = new Cloudflare({
	apiToken: process.env.API_TOKEN,
});

async function deleteWorker(
	accountId: string,
	namespace: string,
	scriptName: string,
) {
	const result =
		await client.workersForPlatforms.dispatch.namespaces.scripts.delete(
			namespace,
			scriptName,
			{ account_id: accountId },
		);

	return result;
}

// Usage
await deleteWorker("your-account-id", "production", "customer-123");

这篇文档对您有帮助吗?