Files
skills/docs/api-stack/api/api-openapi-ui-redoc/src/handler/handler.md
2026-05-29 08:20:56 +01:00

3.3 KiB

handler — createRedocUiHandler

(no submodules)

Purpose

This module exposes createRedocUiHandler, the factory the api-host calls to obtain the HTTP handler serving the ReDoc HTML shell. The returned handler is a zero-argument function the host invokes per request. It is intentionally router-agnostic — adapters in the api-host layer translate the returned RedocHttpResponse into Hono / api-router envelopes — so the package can be wired into any HTTP surface without dragging a router peer dependency through every consumer.

Features

  • Validates options at construction; invalid input raises OPENAPI_UI_REDOC_INVALID_OPTIONS before any handler runs.
  • Resolves the runtime asset URL up-front; missing bundled / inline payloads raise OPENAPI_UI_REDOC_ASSETS_MISSING at construction, not at request time.
  • Pre-renders the HTML shell once at construction — every subsequent request is a constant-time return of the frozen response object.
  • The response carries Content-Type: text/html; charset=utf-8, Cache-Control: no-cache, and X-Content-Type-Options: nosniff.
  • The handler is idempotent — the same call always returns the same frozen object, so adapters can safely cache it.

Usage: Basic

import { createRedocUiHandler } from "@suaveplan/api-openapi-ui-redoc/handler";

const handler = createRedocUiHandler({ openapiUrl: "/openapi.json" });
const res = handler();
// res.body is the rendered HTML shell.

Usage: Advanced

Wire the bundled-asset strategy into a Hono app, including the cache-busted asset route:

import { Hono } from "hono";
import {
    createRedocUiHandler,
    defineRedocAsset,
} from "@suaveplan/api-openapi-ui-redoc";

const asset = defineRedocAsset(
    "redoc.standalone.js",
    "application/javascript; charset=utf-8",
    runtimeBody
);

const handler = createRedocUiHandler({
    openapiUrl: "/openapi.json",
    uiAssets: "bundled",
    bundledAsset: asset,
    title: "Acme API",
    expandResponses: "200,201",
    theme: "dark",
});

const app = new Hono();
app.get("/docs/ui/redoc", (c) => {
    const r = handler();
    Object.entries(r.headers).forEach(([k, v]) => c.header(k, v));
    return c.body(r.body, r.status);
});
app.get(`/docs/ui/redoc/assets/${asset.hash}/${asset.name}`, (c) => {
    c.header("Content-Type", asset.contentType);
    c.header("Cache-Control", "public, max-age=31536000, immutable");
    return c.body(asset.body as string);
});

API Reference

Symbol Kind Description
RedocHttpResponse type { status, headers, body } — router-agnostic response
RedocHttpHandler type () => RedocHttpResponse
CreateRedocUiHandlerInput type RedocUiOptionsInput & { bundledAsset?, inlineAsset? }
createRedocUiHandler fn Build the handler; pre-renders the shell

Implementation Notes

The handler pre-renders the HTML once at construction. This keeps the per-request hot path a constant-time return of a frozen object — the same shape the api-router would otherwise have to allocate per call. Pre-rendering also means every option-level fault surfaces at host start-up, not at the first request, which is the failure mode operators want for misconfigured deploys.