Workers RPC 系统旨在实现不信任彼此的 Worker 之间的安全通信。系统不允许 RPC 会话的任一方访问另一方的任意对象,更不允许调用任意代码。相反,每一方只能调用通过先前调用明确收到 stub 的对象和函数。
这种安全模型通常称为对象能力(Object Capabilities)或基于能力的安全(Capability-Based Security)。Workers RPC 构建在 Cap'n Proto RPC ↗ 之上,而后者又基于 CapTP——分布式编程语言 E ↗ 使用的对象传输协议。
类的私有属性(Private properties) ↗不会直接通过 RPC 暴露。
箭头函数表达式不会通过 RPC 暴露,因为它们定义在类实例上,而非类原型上。不应将其用作 WorkerEntrypoint 类的类方法 ↗。
import { WorkerEntrypoint } from "cloudflare:workers";
export default class extends WorkerEntrypoint {
// add() is exposed over RPC.
add(a, b) {
return a + b;
}
// subtract() is NOT exposed over RPC.
subtract = (a, b) => a - b;
}当你发送应用程序定义类的实例时,接收方只能访问类上声明的方法和属性,而不能访问实例的属性。例如:
class Foo extends RpcTarget {
constructor() {
super();
// i CANNOT be accessed over RPC
this.i = 0;
// funcProp CANNOT be called over RPC
this.funcProp = () => {}
}
// value CAN be accessed over RPC
get value() {
return this.i;
}
// method CAN be called over RPC
method() {}
}此行为是有意为之——旨在防止你意外暴露私有类内部实现。通常,实例属性应声明为私有,通过 # 前缀 ↗。然而,私有属性是 JavaScript 的较新特性,在生态系统中尚未广泛使用。
由于两个 Worker 之间的 RPC 接口可能是安全边界,我们需要格外谨慎,因此在使用 RPC 在 Worker 之间通信时,无论是否具有 # 前缀,实例属性始终为私有。如果你希望暴露属性,可以如上所示在类级别声明显式 getter。
这些可见性规则仅适用于继承 RpcTarget、WorkerEntrypoint 或 DurableObject 的对象,不适用于普通对象。普通对象按「值」传递,发送其所有「自有(own)」属性。
当你通过 RPC 传递函数时,调用方可以访问函数对象本身的「自有」属性。
someRpcMethod() {
let func = () => {};
func.prop = 123; // `prop` is visible over RPC
return func;
}函数上的此类属性像 RpcTarget 的类属性一样异步访问。但与上面的 RpcTarget 示例不同,函数的实例属性对调用方是可访问的。实践中,很少向函数添加属性。