Reference · Jobs and services

accept_calls

signature
accept_calls(map) -> null

What it does

At the top level of a service, says which calls from other services it takes and how each proves who makes it. Written as a declaration, accept_calls { ... }, it takes:

Who called is request.caller in the server fn: { name, by }, by being "quillo", "key", "jwt" or "mtls", with scopes and claims for a token and subject and uri for a certificate. server fn refund(...) for ["shop"] takes calls from those callers only (403 otherwise), and none from pages: /_quillo/rpc/refund answers 404, and a page's script has no server.refund (since 0.7: anyone could call it there). It gives null.

Examples

in a program
// billing.qweaccept_calls {    keys: { shop: [env("SHOP_KEY"), env("SHOP_KEY_OLD")], notify: env("NOTIFY_KEY") },    shared: false,    jwt: { issuer: env("IDP"), audience: "billing", jwks: env("IDP") + "/.well-known/jwks.json" },    client_cert: { header: "x-forwarded-client-cert" },    check: (caller) => caller.name != "mallory",}server fn refund(account: int, cents: int) for ["shop"] {    { refunded: cents, by: request.caller.name }}server fn whoami() = { caller: request.caller, user: request.user, forwarded: request.forwarded }

Both sides, with a key for one caller: billing takes calls signed with the shop's key and no others, and the shop declares the service with that key and calls it as a function of its own:

in a program
// billing.qweaccept_calls { keys: { shop: env("SHOP_KEY") }, shared: false }server fn refund(account: int, cents: int) for ["shop"] {    { refunded: cents, account, by: request.caller.name }}// shop.qweservice billing = "billing.qwe" { auth: { key: env("SHOP_KEY"), as: "shop" } }route POST /orders/:id/refund {    let r = billing.refund(int(id), 1200) ?? reply 502 "Billing refused the refund"    <p>Refunded {r.refunded} cents to account {r.account}, as {r.by}</p>}
SHOP_KEY=... quillo run billing.qwe --port 8081SHOP_KEY=... quillo run shop.qwe --service-url billing=http://localhost:8081

A post to the shop's /orders/42/refund answers Refunded 1200 cents to account 42, as shop. A program that declares billing with no auth, and so signs with the shared secret, gets billing's 401 as an error value (service billing: 401 this service takes no calls signed with the shared secret (accept_calls { shared: false })), which its visitor sees as a 500 unless the route answers it. Run in one process (quillo run shop.qwe alone), the call is a function's call: nothing is checked, and request.caller is null.

print(accept_calls({ keys: { shop: "shop-key-0123456789abcdef0123456789" } }))
output
null

Edge cases

print(accept_calls({ shared: false }))
output
null

Errors

An option it does not take, an empty key (an environment variable not set), a jwt without audience or without jwks or secret, or accept_calls with nothing in it, is a runtime error as the program loads.

this one fails
accept_calls { jwt: { secret: "s" } }
output
line 1: `accept_calls`: `jwt` needs `audience`: a token for another service must not be taken here
this one fails
accept_calls { keys: { shop: "" } }
output
line 1: `accept_calls`: the key of `shop` is empty (is its environment variable set?)
this one fails
accept_calls {}
output
line 1: `accept_calls` with nothing in it takes what it took before: give keys, jwt, client_cert, check or shared: false

Chaining

It is a declaration, written once at the top level of the service, not piped into or out of. Its keys come from the environment:

in a program
accept_calls { keys: { shop: split(env("SHOP_KEYS") ?? "", ",") } }

See also

later.status, ready, publish, env

Thread
1Useful? Like it, or add to its thread below.

Thread 0 posts

On accept_calls(): questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.

    Edit this page on GitHub · every example's output was made by running it (tools/refcheck.mjs) · questions on Discord or r/quillo