@metorial-outpost/fetch
v0.1.1
Published
A `fetch`-compatible client that signs every outgoing request with an [`OutpostAuth`](../outpost-auth) instance, per the [Metorial Outpost Signature Protocol](../../spec.md). It exists so callers don't have to manually call `auth.sign()` and merge the res
Readme
@metorial/outpost-fetch
A fetch-compatible client that signs every outgoing request with an
OutpostAuth instance, per the Metorial Outpost Signature
Protocol. It exists so callers don't have to manually call auth.sign() and
merge the resulting headers into every request themselves.
Installation
npm install @metorial/outpost-fetch
yarn add @metorial/outpost-fetch
bun add @metorial/outpost-fetch
pnpm add @metorial/outpost-fetchUsage
import { OutpostAuth } from '@metorial-outpost/auth';
import { createOutpostFetch } from '@metorial-outpost/fetch';
let auth = new OutpostAuth({
credential: {
version: 1,
endpoint: 'https://outpost.metorial.com',
outpost_id: 'otp_123',
credential_id: 'otc_456',
private_key: '<base64url PKCS#8 Ed25519 private key>'
},
defaultService: 'metorial.proxy'
});
let outpostFetch = createOutpostFetch({ auth });
let response = await outpostFetch('https://api.metorial.com/v1/foo', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ hello: 'world' })
});createOutpostFetch returns a plain function with the same signature as the global fetch,
so it can be dropped in anywhere a custom fetch implementation is accepted (e.g. an SDK
client's fetch option). Use the OutpostFetch class directly if you'd rather hold onto the
instance:
import { OutpostFetch } from '@metorial-outpost/fetch';
let client = new OutpostFetch({ auth, service: 'metorial.proxy' });
await client.fetch('https://api.metorial.com/v1/foo');Every header on the request — the ones you pass plus anything already on a Request object —
is signed, matching OutpostAuth.sign()'s "hand it the exact headers you're about to send"
contract.
Options
auth— theOutpostAuthinstance to sign requests with.service— defaultservicelabel for requests made through this client. Overridable per call viainit.service; falls back to theOutpostAuthinstance's owndefaultServiceif neither is set.fetch— the underlyingfetchimplementation to call once signing is done. Defaults to the globalfetch.init.proxyContext/init.outpostChain— per-call, forwarded straight into the signed metadata (spec §59.2). Set these when re-signing a relayed request as this Outpost, to carry the original client'sproxy_contextand the request'soutpost_chainthrough unchanged rather than losing them at this hop -- see@metorial/outpost-proxy'screateProxyAdapter.
Body support
Request bodies are hashed as part of the signature, so only body types that can be read
synchronously into bytes are supported: string, Uint8Array, ArrayBuffer,
ArrayBufferView, and URLSearchParams. Pre-serialize FormData, Blob, and
ReadableStream bodies before calling fetch() — passing one throws immediately instead of
silently sending an unsigned or partially-signed request.
License
This project is licensed under the Apache License 2.0.
