RPC
Serve an API whose clients call your F# methods by name. Cap'n Web sends each call over HTTP or a WebSocket, and it can send a chain of dependent calls in one round trip.
- Libraries
Runtime.CapnwebRuntime.Workers - npm
capnweb0.12.0 - Free plan 100,000 requests a day, shared by Pages Functions and Workers
Pricing API
The script on a pricing page calls plans and quote on this API. Cap'n Web exposes the class methods of an object that inherits RpcTarget, and on Workers its RpcTarget is the class exported by cloudflare:workers. With [<AttachMembers>], Fable compiles the F# members as methods of that JavaScript class.
module Pricing
open Fable.Core
module Runtime = FSharp.CloudEdge.Runtime.Workers.Cloudflare.Workers
[<AttachMembers>]
type PricingApi() =
inherit Runtime.RpcTarget()
member _.plans() = [| "starter"; "team"; "business" |]
member _.quote(plan: string, seats: float) =
let perSeat =
match plan with
| "team" -> 8.
| "business" -> 15.
| _ -> 0.
{| plan = plan; seats = seats; monthly = perSeat * seats |}
quote builds its result as an anonymous record. Fable compiles it to a plain JavaScript object, and Cap'n Web sends plain objects to the client by value.
Emitted JavaScript
import { RpcTarget } from "cloudflare:workers";
import { class_type } from "./fable_modules/fable-library-js.5.13.0/Reflection.js";
export class PricingApi extends RpcTarget {
constructor() {
super();
}
plans() {
return ["starter", "team", "business"];
}
quote(plan, seats) {
return {
monthly: ((plan === "team") ? 8 : ((plan === "business") ? 15 : 0)) * seats,
plan: plan,
seats: seats,
};
}
}
Pricing Endpoint
A Pages Function serves the API. newWorkersRpcResponse returns the response for either kind of Cap'n Web request, an HTTP batch or a WebSocket upgrade. The function creates a new PricingApi for each request.
module Workers = FSharp.CloudEdge.Runtime.Workers
module Capnweb = FSharp.CloudEdge.Runtime.Capnweb
let onRequest (context: Workers.EventContext<obj, string, obj>) =
Capnweb.Exports.newWorkersRpcResponse(context.request, Pricing.PricingApi())
Needs a Pages project with this module compiled to functions/api.js. Pages serves that file's onRequest export at /api, following its file-based routing.
Browser code opens a session against that route with Cap'n Web's newHttpBatchRpcSession or newWebSocketRpcSession.
Guarded Endpoint
newWorkersRpcResponse takes session options as its third argument. Cap'n Web calls onSendError with each error that it serializes for a client. This handler writes the error with console.error and returns None, so Cap'n Web applies its default serialization, which omits the stack trace.
open Fable.Core
module Workers = FSharp.CloudEdge.Runtime.Workers
module Capnweb = FSharp.CloudEdge.Runtime.Capnweb
let options =
Capnweb.RpcSessionOptions.Create(
onSendError = (fun error ->
JS.console.error error
None),
limits = Capnweb.RpcSessionOptions.Limits.Create(maxMessageSize = 65536.)
)
let onRequest (context: Workers.EventContext<obj, string, obj>) =
Capnweb.Exports.newWorkersRpcResponse(context.request, Pricing.PricingApi(), options)
In this example the maximum incoming message size is 65,536 UTF-16 code units, set through limits. The default is 33,554,432. Cap'n Web rejects a larger message and aborts the session.
Emitted JavaScript
import { newWorkersRpcResponse } from "capnweb";
import { PricingApi } from "./PricingApi.js";
export const options = {
onSendError: (error) => {
console.error(error);
return undefined;
},
limits: {
maxMessageSize: 65536,
},
};
export function onRequest(context) {
return newWorkersRpcResponse(context.request, new PricingApi(), options);
}
Library Table
| Library | npm package | What it covers |
|---|---|---|
Runtime.Capnweb |
capnweb 0.12.0 |
Sessions, responses, options |
Runtime.Workers |
@cloudflare/workers-types 5.20260906.1 |
RpcTarget, Pages Functions context |