Files
skills/docs/api-stack/api/api-plugin-site/src/middleware/domain-resolver.md
2026-05-29 08:20:56 +01:00

2.7 KiB

middleware/domain-resolver.ts

(no submodules)

Purpose

Factory that builds a Hono middleware which resolves the incoming request's Host header to a site + organization and injects them into the request context. The middleware is the canonical hook applications install at the top of their route stack so downstream handlers can use c.get("site") / c.get("organization") without re-resolving on every endpoint. It is exposed as a service (domainResolverMiddleware) by the plugin's onInit so unrelated plugins can install it positionally without importing the package directly.

The middleware never errors on miss — it falls through with no context keys set. This matches the upstream behaviour and keeps the same instance reusable on route trees containing both site-bound and unbound endpoints.

Features

  • Reads Host then X-Forwarded-Host so reverse-proxied deployments work.
  • Strips the port via host.split(":") before lookup.
  • Normalises through normalizeDomain so the value passed to the resolver is canonical.
  • Injects site, organization, siteId, organizationId on success.
  • Silent fall-through on miss — downstream is free to 404 or render maintenance.

Usage: Basic

import { createDomainResolverMiddleware } from "@suaveplan/api-plugin-site/middleware/domain-resolver";

const middleware = createDomainResolverMiddleware(resolver);
app.use("*", middleware);

Usage: Advanced

import { createDomainResolverMiddleware } from "@suaveplan/api-plugin-site/middleware/domain-resolver";

// Wrap to enforce site presence on a specific subtree.
const middleware = createDomainResolverMiddleware(resolver);
app.use("/site", async (c, next) => {
    await middleware(c, next);
    if (c.get("site") === undefined) {
        return c.json({ error: "Site not found for host" }, 404);
    }
});

API Reference

  • type DomainResolverMiddleware = (c: Context, next: Next) => Promise<void | Response>.
  • createDomainResolverMiddleware(resolver: DomainResolverService): DomainResolverMiddleware.

Implementation Notes

  • The middleware does not throw on a resolver error — the resolver's own error path already records the error outcome on the OTel counter. Throwing here would force every consumer to wrap the entire request in try/catch.
  • X-Forwarded-Host is consulted only when Host is absent; if both are present we trust the proxy by deferring to the inner header set, matching the upstream convention.
  • The four injected context keys are typed via the hono ContextVariableMap augmentation (consumers can re-declare for their app), but the middleware itself does not augment the global declaration to avoid namespace collisions with siblings.