跳转到内容
搜索文档

Context (ctx)

最后更新 查看 MarkdownAgent 设置

Context API 提供用于管理 Worker 或 Durable Object 生命周期的方法。

Context 可通过以下方式访问:

请注意,Context API 仅在无状态上下文中可用,即不适用于 Durable Objects。不过,Durable Objects 有另一个对象 Durable Object State,在 Durable Object 类内部可通过 this.ctx 访问,并提供与 Context API 部分相同的功能。

props

ctx.props 提供一种根据 Worker 被调用的上下文向其传递额外配置的方式。例如,当 Worker 被另一个 Worker 调用时,ctx.props 可以提供有关调用 Worker 的信息。

例如,假设你正在配置名为 "frontend-worker" 的 Worker,它必须与名为 "doc-worker" 的另一个 Worker 通信以操作文档。你可以为 "frontend-worker" 配置 Service Binding,如下所示:

{
	"services": [
		{
			"binding": "DOC_SERVICE",
			"service": "doc-worker",
			"entrypoint": "DocServiceApi",
			"props": {
				"clientId": "frontend-worker",
				"permissions": [
					"read",
					"write"
				]
			}
		}
	]
}
[[services]]
binding = "DOC_SERVICE"
service = "doc-worker"
entrypoint = "DocServiceApi"

  [services.props]
  clientId = "frontend-worker"
  permissions = [ "read", "write" ]

现在 frontend-worker 可以使用类似 env.DOC_SERVICE.getDoc(id) 的代码调用 doc-worker。这将发起 Remote Procedure Call,调用 doc-worker 导出的 WorkerEntrypoint DocServiceApigetDoc() 方法。

配置包含 props 值。这是一个任意 JSON 值。当使用 DOC_SERVICE 绑定时,接收调用的 DocServiceApi 实例可以通过 this.ctx.props 访问此 props 值。在此示例中,我们将 props 配置为指定调用来自 frontend-worker,且允许读写文档。不过,props 的内容可以是你想要的任何内容。

Workers 平台的设计确保只有有权编辑和部署目标 Worker 的人才能设置 ctx.props。这意味着你可以信任 ctx.props 内容的真实性。无需在 ctx.props 值中使用密钥或加密签名。

ctx.props 还可用于配置 RPC 接口以表示_特定_资源,从而创建"自定义绑定(binding)"。例如,我们可以配置指向 "doc-worker" 的 Service Binding,仅授予对特定文档的访问权限:

{
	"services": [
		{
			"binding": "FOO_DOCUMENT",
			"service": "doc-worker",
			"entrypoint": "DocumentApi",
			"props": {
				"docId": "e366592caec1d88dff724f74136b58b5",
				"permissions": [
					"read",
					"write"
				]
			}
		}
	]
}
[[services]]
binding = "FOO_DOCUMENT"
service = "doc-worker"
entrypoint = "DocumentApi"

  [services.props]
  docId = "e366592caec1d88dff724f74136b58b5"
  permissions = [ "read", "write" ]

在此示例中,我们在 ctx.props 中放置了 docId 属性。DocumentApi 类可以设计为提供由 ctx.props.docId 标识的特定文档的 API,并强制执行给定权限。

exports

ctx.exports 为所有顶层导出提供自动配置的"回环"绑定(binding)。

  • 对于每个 extends WorkerEntrypoint 的顶层导出(或仅实现 fetch handler 的导出),ctx.exports 自动包含 Service Binding
  • 对于每个 extends DurableObject 的顶层导出(且已通过 migration 配置存储),ctx.exports 自动包含 Durable Object namespace binding

例如:

import { WorkerEntrypoint } from "cloudflare:workers";

export class Greeter extends WorkerEntrypoint {
	greet(name) {
		return `Hello, ${name}!`;
	}
}

export default {
	async fetch(request, env, ctx) {
		let greeting = await ctx.exports.Greeter.greet("World");
		return new Response(greeting);
	},
};

在此示例中,默认 fetch handler 通过 RPC 调用 Greeter 类,就像使用 Service Binding 一样。但是,不需要外部配置。ctx.exports 会从顶层导入_自动_填充。

使用 ctx.exports 时指定 ctx.props

ctx.exports 中的回环 Service Binding 具有常规 Service Binding 不具备的额外能力:调用方可以指定应传递给被调用方的 ctx.props 值。

import { WorkerEntrypoint } from "cloudflare:workers";

export class Greeter extends WorkerEntrypoint {
	greet(name) {
		return `${this.ctx.props.greeting}, ${name}!`;
	}
}

export default {
	async fetch(request, env, ctx) {
		// Make a custom greeter that uses the greeting "Welcome".
		let greeter = ctx.exports.Greeter({ props: { greeting: "Welcome" } });

		// Greet the world. Returns "Welcome, World!"
		let greeting = await greeter.greet("World");

		return new Response(greeting);
	},
};
import { WorkerEntrypoint } from "cloudflare:workers";

type Props = {
	greeting: string;
};

export class Greeter extends WorkerEntrypoint<Env, Props> {
	greet(name) {
		return `${this.ctx.props.greeting}, ${name}!`;
	}
}

export default {
	async fetch(request, env, ctx) {
		// Make a custom greeter that uses the greeting "Welcome".
		let greeter = ctx.exports.Greeter({ props: { greeting: "Welcome" } });

		// Greet the world. Returns "Welcome, World!"
		let greeting = await greeter.greet("World");

		return new Response(greeting);
	},
} satisfies ExportedHandler<Env>;

在此情况下允许动态指定 props,因为调用方是同一个 Worker,因此可以假定其被信任可以指定任何 props。自定义 props 的能力在生成的绑定要通过 RPC 传递给另一个 Worker 或用于动态加载 Workerenv 时特别有用。

请注意,以这种方式指定的 props 值可以包含任何"持久"可序列化类型。这包括所有基本结构化克隆数据类型。它还包括 Service Binding 本身:你可以将 Service Binding 放入另一个 Service Binding 的 props 中。

ctx.exportsctx.props 的 TypeScript 类型

如果使用 TypeScript,应使用 wrangler types 命令 自动生成项目类型。生成的类型将确保 ctx.exports 类型正确。

声明接受 props 的 entrypoint 类时,确保将其声明为 extends WorkerEntrypoint<Env, Props>,其中 Propsctx.props 的类型。请参阅上面的示例。

tracing

ctx.tracing 提供对自定义 span API 的访问,用于创建用户定义的 trace span。这与通过 import { tracing } from "cloudflare:workers" 可用的对象相同。

必须在 Worker 上启用 Tracing 才能记录 span。

export default {
	async fetch(request, env, ctx) {
		return ctx.tracing.enterSpan("handleRequest", async (span) => {
			span.setAttribute("url.path", new URL(request.url).pathname);
			const data = await env.MY_KV.get("key");
			return new Response(data);
		});
	},
};

有关完整 API 详情,请参阅自定义 span

waitUntil

ctx.waitUntil() 延长 Worker 的生命周期,允许你在不阻塞返回响应的情况下执行工作,且这些工作可能在返回响应后继续。它接受一个 Promise,Workers 运行时将继续执行该 Promise,即使 Worker 的 handler 已返回响应。

使用 ctx.waitUntil() 处理可在响应发送后运行的工作,例如日志记录、分析或缓存写入,只要工作能在 waitUntil() 时间限制内完成。如果客户端仍在接收响应(包括流式响应体),Worker 调用会保持活跃,无需 ctx.waitUntil()。如果响应依赖于该工作,请在返回响应之前 await 该工作,或在工作完成时流式传输响应。

waitUntil 通常用于:

你可以多次调用 waitUntil()。类似于 Promise.allSettled,即使传递给一个 waitUntil 调用的 promise 被拒绝,传递给其他 waitUntil() 调用的 promise 仍将继续执行。

例如:

export default {
	async fetch(request, env, ctx) {
		// Forward / proxy original request
		let res = await fetch(request);

		// Add custom header(s)
		res = new Response(res.body, res);
		res.headers.set("x-foo", "bar");

		// Cache the response
		// NOTE: Does NOT block / wait
		ctx.waitUntil(caches.default.put(request, res.clone()));

		// Done
		return res;
	},
};

passThroughOnException

passThroughOnException 方法允许 Worker fail open,在 Worker 抛出未处理异常时将请求传递到源站服务器。当 Worker 作为现有服务前的一层使用时,这很有用,允许 Worker 后面的服务处理 Worker 中出现的任何意外错误情况。

export default {
	async fetch(request, env, ctx) {
		ctx.passThroughOnException();

		try {
			return await fetch(request);
		} catch (error) {
			console.error("Origin fetch failed", error);
			return new Response("Bad Gateway", { status: 502 });
		}
	},
};

这篇文档对您有帮助吗?