HTTP
Serve your procedures over HTTP and call them from a typed client.
handle(router, opts?) from tacho/transport/fetch is (Request) => Promise<Response>. POST only. Puts req on context. CORS is not built in - wrap handle().
import serveserve({
fetch: (request: Request) => Promise<Response>fetch: handle<{
ping: ProcedureDef<{}, undefined, "pong">;
}, {
user: string | undefined;
}>(router: {
ping: ProcedureDef<{}, undefined, "pong">;
}, opts?: HandleOptions<{
user: string | undefined;
}> | undefined): (request: Request) => Promise<Response>
handle(const router: {
ping: ProcedureDef<{}, undefined, "pong">;
}
router, {
path?: string | undefinedpath: "/rpc",
createContext?: ((req: Request) => {
user: string | undefined;
} | Promise<{
user: string | undefined;
}>) | undefined
createContext: (req: Requestreq) => ({
user: string | undefineduser: req: Requestreq.Request.headers: HeadersThe **`headers`** read-only property of the Request interface contains the Headers object associated with the request.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/headers)headers.Headers.get(name: string): string | nullThe **`get()`** method of the Headers interface returns a byte string of all the values of a header within a Headers object with a given name. If the requested header doesn't exist in the Headers object, it returns null.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/get)get("x-user") ?? var undefinedundefined,
}),
onError?: ((err: unknown, req: Request) => void) | undefinedonError: (err: unknownerr, req: Requestreq) => var console: Consoleconsole.Console.error(...data: any[]): voidThe **`console.error()`** static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/error_static)error(req: Requestreq.Request.url: stringThe **`url`** read-only property of the Request interface contains the URL of the request.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/url)url, err: unknownerr),
}),
});
| option | |
|---|---|
path |
Other paths → 404. |
createContext |
Merged onto { req }. Throw → JSON-RPC INTERNAL_ERROR. |
onError |
Called when createContext or the stream throws. |
maxBodySize |
Max request body in bytes. Default: 1_048_576 (1 MB). |
maxBatchSize |
Max items in a batch request. Default: 20. |
serializer |
Custom serializer (e.g. superjson). |
Non-POST → 405 + Allow: POST. Notification (no id) → 204.
createClient from tacho/client/http is a typed proxy over POST.
const const client: RPCClient<{
ping: ProcedureDef<{}, undefined, "pong">;
}>
client = createClient<{
ping: ProcedureDef<{}, undefined, "pong">;
}>(opts: ClientOptions): RPCClient<{
ping: ProcedureDef<{}, undefined, "pong">;
}>
createClient<type Router = {
ping: ProcedureDef<{}, undefined, "pong">;
}
Router>({
url: stringurl: "http://localhost:3000",
headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>) | undefinedheaders: () => ({ authorization: stringauthorization: `Bearer ${const token: "secret"token}` }),
signal?: AbortSignal | undefinedsignal: var AbortSignal: {
new (): AbortSignal;
prototype: AbortSignal;
abort(reason?: any): AbortSignal;
any(signals: AbortSignal[]): AbortSignal;
timeout(milliseconds: number): AbortSignal;
}
The **`AbortSignal`** interface represents a signal object that allows you to communicate with an asynchronous operation (such as a fetch request) and abort it if required via an AbortController object.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/AbortSignal)AbortSignal.function timeout(milliseconds: number): AbortSignalThe **`AbortSignal.timeout()`** static method returns an AbortSignal that will automatically abort after a specified time.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/AbortSignal/timeout_static)timeout(5_000),
});
await const client: RPCClient<{
ping: ProcedureDef<{}, undefined, "pong">;
}>
client.ping: (input?: undefined, opts?: CallOptions | undefined) => Promise<"pong">ping();
await const client: RPCClient<{
ping: ProcedureDef<{}, undefined, "pong">;
}>
client.ping: (input?: undefined, opts?: CallOptions | undefined) => Promise<"pong">ping(var undefinedundefined, { signal?: AbortSignal | undefinedsignal: var AbortSignal: {
new (): AbortSignal;
prototype: AbortSignal;
abort(reason?: any): AbortSignal;
any(signals: AbortSignal[]): AbortSignal;
timeout(milliseconds: number): AbortSignal;
}
The **`AbortSignal`** interface represents a signal object that allows you to communicate with an asynchronous operation (such as a fetch request) and abort it if required via an AbortController object.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/AbortSignal)AbortSignal.function timeout(milliseconds: number): AbortSignalThe **`AbortSignal.timeout()`** static method returns an AbortSignal that will automatically abort after a specified time.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/AbortSignal/timeout_static)timeout(1_000) });
| option | |
|---|---|
url |
POST target. |
headers |
Object or () => HeadersInit | Promise<HeadersInit>. |
signal |
Default abort. Per-call: client.ping(input, { signal }). |
fetch |
Custom fetch. |
serializer |
Custom serializer. |
async function* over this transport is SSE. File / Blob in params or returns is Files.