first commit
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
# `middleware/domain-resolver.ts`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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
|
||||
|
||||
```ts
|
||||
import { createDomainResolverMiddleware } from "@suaveplan/api-plugin-site/middleware/domain-resolver";
|
||||
|
||||
const middleware = createDomainResolverMiddleware(resolver);
|
||||
app.use("*", middleware);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user