@hile/http-over-micro
Preserve HTTP method, headers, status, JSON bodies, and binary streams across Registry-discovered Hile Micro calls.Choose This Package When
Use When
Use this package when one HTTP ingress must project a request to a Registry-discovered Hile microservice while preserving HTTP method, duplicate headers, query values, status, cookies, redirects, JSON bodies, and streamed file bodies. The package defines the transport contract only. The public listener and its authentication, authorization, route selection, header policy, and final Koa response remain owned by the gateway.Do Not Use When
- Do not use it for ordinary in-process HTTP controllers that do not cross a Micro boundary.
- Do not use it as a durable queue or retry layer.
- Do not use it for RSC Flight, MCP, WebSocket upgrades, HTTP trailers, or informational
1xxresponses; those protocols keep their own transports. - Do not put business logic in the gateway merely because the gateway performs the HTTP projection.
Install
Imports
Copy-Paste Example
Provider message:ctx.request.body; use the untouched incoming Readable instead for raw uploads.
More Examples
Upload and download without a transport switch
The caller supplies a normal JSON value or anAsyncIterable, Uint8Array, or ArrayBuffer. callHttpOverMicro() snapshots JSON values into the request envelope and automatically moves binary or iterable bodies into Micro request input.
retries: 0, including reads, writes, inline bodies, and streams. Streaming request bodies are non-replayable: an explicit nonzero value fails before dispatch. Opt-in retry of replayable requests still needs an end-to-end attempt budget and business idempotency; failure does not prove that a write did not commit. The adapter never retries a malformed response after consuming its head/body.
Response metadata before response bytes
Every HTTP-over-Micro call uses one Micro response stream. Its first chunk is a response head; body chunks follow only whenbody.kind is stream:
Set-Cookie. Header names are canonical lowercase on the wire. Query tuples preserve repeated query values without inventing an object serialization rule.
Zod parses, not merely checks
schema.headers, schema.query, schema.params, and schema.body each receive the logical value seen by the handler. Schema transforms and coercions are returned to the handler.
For a streamed request, schema.body receives the Readable. Use a Zod custom or union schema only when that endpoint intentionally accepts a stream; a JSON-object body schema rejects the stream naturally.
Runtime And Lifecycle Notes
defineHttpOverMicroMessage()returns adefineMicroMessage()definition marked withprotocol: '@hile/http-over-micro'. File loading preserves this marker; rawapp.register(path, definition.fn, { protocol: definition.protocol })must pass it explicitly.callHttpOverMicro()fixes the outgoing protocol marker; callers cannot override it. Micro carries that marker in existing request metadata and rejects a route/protocol mismatch after route matching but before any handler/schema/business side effect. Plain Micro routes cannot become HOM routes by receiving a payload that resembles its HTTP envelope. The reverse misdelivery is rejected too, and a mismatch does not fall through to a less-specific route.- The marker is protocol isolation, not authentication or capability authorization. There is no new modem frame, operation addressing mode, dispatcher endpoint, or parallel discovery catalog. The optional metadata field is an incremental wire value: all selectable receiver replicas must be upgraded before relying on isolation, because older receivers may ignore it.
- The Micro route remains the file/message path. HTTP method is protocol data and one definition may accept one method or a method list. Unsupported methods return
405plusAllowwithout invoking the handler. - Inline bodies use JSON serialization semantics and default to a 1 MiB bound. Override
limits.maxInlineBodyBytesexplicitly on both ends when a deployment requires another limit; use streams for files and large byte bodies. - Final response statuses are
200..599.HEAD,204,205, and304responses reject bodies.1xx, protocol upgrades, and trailers are intentionally out of scope. - Destroying the returned streamed body cancels the underlying Micro response.
signal, total timeout, idle timeout, and stream window are passed toApplication.stream(). - Credit-based backpressure bounds buffered chunks, not the total number of transferred bytes. The HTTP ingress and provider handler must each enforce their endpoint-specific upload/download byte limit while consuming a stream.
- The caller owns the returned response stream and must consume or destroy it. The package fully consumes empty and inline responses before resolving.
- Cookies and
Locationare opaque response headers. The public gateway remains responsible for cookie ownership, security attributes, redirect policy, and hop-by-hop header removal. - Treat
namespaceandurlas public routing information, not authorization. Gateway owns external authentication and policy; an owning service exposes an HTTP adapter by explicitly defining its HOM message. Use normal Micro discovery and route protocol isolation, not a new Browser provider catalog. Deployments allowing client-selected service namespaces must evaluate that routing exposure explicitly; the marker does not prevent direct calls by trusted internal peers.
Anti-Patterns
- Do not handcraft the request envelope or consume the response-head frame yourself; use
callHttpOverMicro(). - Do not call
Application.call()for this protocol. A response may need headers followed by a body stream, so the package intentionally usesApplication.stream()for every result. - Do not encode files as Base64 inside an inline JSON body.
- Do not collapse response headers into a plain object when duplicate
Set-Cookievalues matter. - Do not enable retries for an upload stream.
- Do not expose ordinary Micro handlers through a public route merely because their input schema happens to reject an HOM envelope; require the pre-handler protocol check on every selectable replica.
- Do not create an additional business dispatcher, generated HTTP route table, or MCP capability catalog to wrap typed Micro operations.
- Do not forward every inbound header, raw cookie, or identity credential merely because the protocol can carry it.
Verification Checklist
- Unit tests cover inline, empty, malformed, method-mismatch, and Zod-coercion cases.
- A real Registry-discovered WebSocket test carries request and response streams at the same time.
- Duplicate response headers survive in order.
- Invalid request metadata fails with HTTP status
400; invalid upstream response metadata fails locally with502. - Inline bodies are bounded and JSON-serializable; files use stream bodies.
- Cancellation, timeout, idle timeout, and backpressure remain owned by
@hile/microand@hile/message-modem. - Real Registry/WebSocket tests cover ordinary-to-HOM and HOM-to-ordinary misdelivery with zero handler effects, including file-loaded marker preservation and explicit raw registration.
- Same-service delegation uses the explicit local unary binding; native streamed business operations retain their native interfaces and must not be forced through the unary contract.
Related Recipes
Micro RPC With Message Loader
Complete Example
Provider handler:operation.path values stay fixed and cannot use [id] or [...paths].
Provider boot:
Package-Local AI Guide
This package also shipsAI.md in npm so agents can read accurate examples after installation.