Skip to content

Recipes

Bearer Refresh Single-Flight

Centralize token refresh, avoid multiple concurrent refreshes, and skip authentication endpoints so the client does not loop.

import { bearerAuth, bearerRefreshGuard, createHttpClient } from "@cedvict/http-guardian";

const api = createHttpClient({
  baseUrl: "https://api.example.com",
  auth: bearerAuth(() => tokenStore.access()),
  parser,
  guards: [
    bearerRefreshGuard({
      refreshFn: () => tokenStore.refresh(),
      skipRefreshFor: (ctx) => ctx.url.includes("/auth/")
    })
  ]
});

Recommended mode for a cookie-backed browser session.

import {
  cookieAuth,
  cookieSafeRefreshGuard,
  createApiParserRestClassic,
  createHttpClient,
  csrfGuard
} from "@cedvict/http-guardian";

const api = createHttpClient({
  baseUrl: "https://app.example.com/api",
  auth: cookieAuth({ credentials: "include" }),
  parser: createApiParserRestClassic(),
  guards: [
    csrfGuard({ headerName: "X-CSRF-TOKEN" }),
    cookieSafeRefreshGuard({
      refreshPath: "/auth/refresh",
      mePath: "/auth/me"
    })
  ]
});

Observable Client for Angular

import { createHttpClient, noAuth } from "@cedvict/http-guardian";
import { toObservableClient } from "@cedvict/http-guardian-rx";

const promiseClient = createHttpClient({ baseUrl, auth: noAuth(), parser });
const api$ = toObservableClient(promiseClient);

api$.get<User[]>("/users").subscribe((result) => {
  if (result.ok) render(result.data);
});

Backend Trace to Logger, Sentry, and OTel

import { correlationIdGuard, createApiParserStructured } from "@cedvict/http-guardian";
import { loggerPlugin } from "@cedvict/http-guardian-plugin-logger";
import { sentryPlugin } from "@cedvict/http-guardian-plugin-sentry";
import { otelPlugin } from "@cedvict/http-guardian-plugin-otel";

const api = createHttpClient({
  baseUrl,
  auth,
  parser: createApiParserStructured(),
  guards: [correlationIdGuard(), traceMetaGuard],
  plugins: [loggerPlugin({ label: "api" }), sentryPlugin(), otelPlugin()]
});