Skip to main content

HTTP Pipeline

Copy-Paste Example

File route examples:
The catch-all declaration is required: /assets/logo.svg and /assets/icons/logo.svg match, while /assets does not. The controller reads the portable declaration name rather than find-my-way’s internal wildcard key:
ctx.params.paths is icons/logo.svg for /assets/icons/logo.svg. Dynamic names must be unique across the complete route and cannot be __proto__, prototype, or constructor. Static routes win over [id], and [id] wins over [...paths]. Routes with the same structure but different parameter names conflict during loading. A configured prefix may use native /:tenant or bracket-style /[tenant] parameters and is compiled separately from portable file segments. Use http.route() when deliberately registering native find-my-way syntax by hand; native syntax is not accepted in file names.

More Examples

The second parse is intentional when you need parsed/coerced data. Hile’s controller validation does not write safeParse().data back to ctx.request.body.

Trusted reverse proxy

Http does not trust forwarded headers by default. When the listener is reachable only through a controlled reverse proxy, enable Koa’s proxy semantics explicitly and bound the number of proxy IPs that may be read:
The edge proxy must replace, not append untrusted input to, X-Forwarded-Proto and the configured client-IP header. It must send X-Forwarded-Proto: https after TLS termination so ctx.protocol, ctx.secure, and Secure Cookie handling reflect the public connection. Keep the Hile listener inaccessible to untrusted direct clients: proxy: true trusts these headers and is not itself a network trust boundary. Use proxyIpHeader only when the deployment uses a client-IP header other than X-Forwarded-For. maxIpsCount bounds the proxy chain read from that header; set it to the known number of trusted hops instead of relying on Koa’s unbounded default. HttpProps composes Koa’s complete constructor options with Hile’s port and find-my-way options. Koa settings such as env, subdomainOffset, keys, asyncLocalStorage, proxy, proxyIpHeader, and maxIpsCount are passed through without a Hile-owned mirror or a second Hile-specific option contract.

Runtime And Lifecycle Notes

  • new Http({ port }) creates a Koa app from the complete HttpProps object and a find-my-way router.
  • proxy defaults to false. When enabled, proxyIpHeader and maxIpsCount are passed to Koa before any middleware or controller handles requests.
  • http.use(middleware) registers Koa middleware before listen().
  • http.listen() returns a close function.
  • http.load(directory, options) scans *.controller.{ts,js,tsx,jsx,mjs} by suffix.
  • .d.ts declarations and .js.map source maps are never controller routes.
  • File loading is atomic: invalid syntax, import failure, invalid exports, or conflicts unregister the routes already acquired by that batch.
  • defineController() supports method-only, method-plus-middlewares, and metadata-plus-Zod forms.
  • Response plugins transform handler return values and set ctx.body when the final result is not undefined.

Anti-Patterns

  • Setting ctx.body and returning a value from the same controller.
  • Loading controllers after starting only because an old example does it; prefer load before listen in new code.
  • Using old validation examples that assume Zod coercion rewrote ctx.query.
  • Enabling proxy on a listener that untrusted clients can reach directly, or allowing an edge proxy to preserve client-supplied forwarded headers.

Verification Checklist

  • Controller files default-export defineController(...) or an array of controllers.
  • Required catch-all controllers use [...name].controller.ts, keep it as the final segment, and read the slash-joined value from ctx.params.name.
  • Controllers return response values.
  • Boot service awaits http.load() before http.listen().
  • Zod schemas are used for validation, and parsed data is explicitly parsed when needed.
  • Reverse-proxy deployments replace forwarded headers, protect the direct listener, and set maxIpsCount to the known proxy-hop count.