Skip to content

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.

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

NuGet packages

Runtime.Capnweb 0.1.0, Runtime.Workers 0.1.0.

See installation and release availability.

Edit this page