Askr
Server & APIs

Client Middleware

Use client middleware with the current published Askr packages.

  • @askrjs/fetch/middleware0.0.1

How to use client middleware

Use client middleware for cross-cutting headers, tracing, and bounded retry policy—not endpoint-specific business rules.

  1. Import the published @askrjs/fetch/middleware entrypoint.
  2. Keep client middleware configuration next to the component, route, or server composition root that owns it.
  3. Handle pending, unavailable, cancellation, and failure states, then verify the production path.
const authorization: Middleware = async (context, next) => {
  const headers = new Headers(context.request.headers);
  headers.set('authorization', 'Bearer ' + session.token);
  return next({ ...context, request: new Request(context.request, { headers }) });
};

const client = createClient(definition, {
  baseUrl: env.API_URL,
  middleware: [authorization],
});

Middleware pipeline

The middleware array passed to createClient() runs outward in the order you list it: each Middleware is a function of (context, next) => Promise<FetchResult> that can inspect or rewrite the request before calling next(), and inspect or rewrite the result after next() resolves. RequestContext exposes the built Request, the endpoint descriptor, the operationId, the current attempt number, and an optional deadline, so middleware can make decisions based on what's actually being sent.

Authentication headers

bearerAuth({ token }) accepts either a static string or a () => string | Promise<string> function, so a fresh access token can be fetched per request instead of baked in once at client creation. apiKeyAuth({ key, value, in }) does the equivalent for an API key delivered as a header or a query parameter, and both are plain Middleware values you drop into the array alongside anything else.

Tracing

telemetry(hooks) exposes three optional callbacks — start(context), end(span, result), and error(span, error) — so a tracing integration can open a span right before a request goes out and close it once the FetchResult (success, HTTP error, or failure) comes back. The span value returned from start() is opaque to the middleware itself and passed straight through to end() or error().

Retry policy

retry({ attempts, methods, statuses, delay }) controls how many times a request is retried, which HTTP methods and response statuses qualify, and how long to wait between attempts via a delay(attempt) function, defaulting to the safe idempotent methods and the common transient status codes. logging(logger?) writes a structured event per request and redacts common credential header and query names automatically, plus whatever header or query name apiKeyAuth() was configured to use.