Cap’n Web: a new RPC system for browsers and web serversというのが面白そうだった。
Cap’n Web は新しい RPC システムで、特徴としては、JS/TS の環境(ブラウザやサーバ)で便利に機能する点。
以下のような特徴をもつ
- スキーマレス (gRPC の.proto のようなファイルは不要)
- HTTP(単発バッチ)、WebSocket(持続接続)、MessagePort(ブラウザ内通信)で利用可能
- JSON をベースとしたシリアライズ形式 を利用(前身である Cap’n Proto がゼロコピーバイナリシリアライズをやっていたのとは対照的)
- RPC で関数を含むオブジェクトを受け渡せる
もともと Cloudflare Workers には組み込みの RPC のシステムがあったが、Cap’n Web はそれを機能的におおむね互換する形で、Cloudflare 以外の JavaScript 環境でも使える OSS として提供されている。またWorkers RPC と相互運用性もあり、今後不足している機能が拡充されていくということなので、最終的には置き換えを狙っているように思える。
RPC(Remote Procedure Call)はその名の通りリモートの処理を呼び出しできる仕組み。今だとgRPCは有名なので知ってたり使った事ある人もいるかもしれない。
gRPC だとサービスとして定義されたメソッドを呼び出せるだけであったが、Cap’n Web では関数を渡して、それを相手から呼び出すこともできる。これにより、たとえば「認証の結果得られたオブジェクトを介して、認証後でないとできない操作を行う」ということが自然と実現できる。
// https://blog.cloudflare.com/capnweb-javascript-rpc-library/ の例より
//
// 以下のようなserverを実装して
class MyApiServer extends RpcTarget {
authenticate(apiKey) {
let username = await checkApiKey(apiKey);
return new AuthenticatedSession(username);
}
}
class AuthenticatedSession extends RpcTarget {
constructor(username) {
super();
this.username = username;
}
whoami() {
return this.username;
}
// ...other methods requiring auth...
}
//
// 以下のようにclientから呼び出す
let batch = newHttpBatchRpcSession("https://example.com/api");
// Authencitate the API key, returning a Session object.
let sessionPromise = batch.authenticate(apiKey);
// Get the user's name.
let name = await sessionPromise.whoami();
console.log(name);
クライアントから session を得るには authenticate()を介するしかないため、認証を介さない whoami()呼び出しは行えない。 これはCapability-based securityと呼ばれる仕組みで、 最近だと WASM の WASI でも採用されているらしい。 https://www.chikuwa.it/blog/2023/capability/
Cap’n Web はだいぶ面白くて実用的になりそうな気がする。 クライアントもサーバも JavaScript/TypeScript で実装している場合は、Cap’n Web を採用することで開発の効率がかなり良くなるのでは… 一方、言語をまたいだ呼び出しが必要な場合や、シリアライズ結果の通信コストを気にしないといけない用途だと向いてないかもしれない。 あと、サーバやクライアントをバージョンアップさせる時にどういうフローでやるんだろう(タイミングがずれると互換性壊れたりしないか?)というのが気になった。