HTTP overview
このコンテンツはまだ日本語訳がありません。
The HTTP module is separate from the I/O broker actors — HTTP servers don’t fit the “one connection many messages” shape, so they get their own DSL and backend abstraction.
import { ActorSystem } from 'actor-ts';import { path, get, post, completeJson, entity, concat } from 'actor-ts/http';
const system = ActorSystem.create('my-app');
const routes = path('api', path('orders', concat( get(async () => completeJson(200, { orders: [] })), post(async (req) => { const order = entity<NewOrder>(req); // ... handle ... return completeJson(201, { id: 'o-1' }); }), ), ),);
const binding = await system.http(8080).bind(routes);console.log(`bound on ${binding.host}:${binding.port}`);Three things going on:
- The route DSL —
path,get,post,concatcompose a tree of routes. Type-safe; compiles to a flat list at bind time. - The marshaller —
entity<T>(req)decodes the request body by Content-Type;completeJson/completeTextencode the response. - The shortcut —
system.http(port).bind(routes)starts a server with the default Fastify backend. For a different backend, passbackend:(see below).
The three pieces
Section titled “The three pieces”| Piece | Lives in | Page |
|---|---|---|
| Routing | actor-ts/http exports path, get, post, complete*, etc. | Route DSL |
| Marshalling | entity<T>(req) decode + completeJson encode. | Marshalling |
| Backend | Pluggable HTTP server — Fastify by default, Hono, Express. | Backends |
The DSL builds an in-memory route tree; system.http(...).bind(routes)
flattens it and registers everything with the chosen backend.
The backends
Section titled “The backends”import { HonoBackend } from 'actor-ts/http';
// Default — no setup needed; Fastify is a hard dependency:await system.http(8080).bind(routes);
// Explicit override (Express / Hono are peer-deps; opt-in):await system.http(8080, { backend: new HonoBackend() }).bind(routes);
// For full control, the underlying extension surface is still there:import { HttpExtensionId } from 'actor-ts';await system.extension(HttpExtensionId) .newServerAt('0.0.0.0', 8080) .useBackend(new HonoBackend()) .bind(routes);| Backend | Runtime fit | When |
|---|---|---|
FastifyBackend (default) | Bun, Node | Production default — Fastify is the most-battle-tested. |
ExpressBackend | Node, Bun | Existing Express middleware ecosystem fits cleanly. |
HonoBackend | Bun, Node, Deno | Tiny + edge-friendly; the most Bun-and-Deno-native option. |
All three implement the same HttpServerBackend interface — the
route DSL compiles identically; the backend just owns the
listen/dispatch loop.
See the backend pages for the configuration options each accepts.
The HTTP client
Section titled “The HTTP client”const response = await http.singleRequest({ method: 'POST', url: 'https://api.example.com/orders', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ sku: 'book-1' }),});
console.log(response.status, response.body);The shared client wraps the runtime’s native fetch. Works
identically on Bun, Node, and Deno (every supported runtime
has fetch built in).
For more elaborate client patterns (retries, caching), wrap the client in a retry + circuit-breaker call.
Middleware
Section titled “Middleware”import { cached, rateLimit } from 'actor-ts/http';
const routes = concat( rateLimit({ max: 100, intervalMs: 1_000 })( cached({ ttlMs: 30_000 })( path('api', /* ... */), ), ),);The framework ships three:
| Middleware | What it does |
|---|---|
| Response cache | Caches GET responses keyed by URL + Vary headers. |
| Rate limit | Per-IP / per-key token-bucket rate limiter. |
| Idempotency key | De-duplicates writes based on an Idempotency-Key header. |
Each is a Route -> Route transformer — wraps a sub-tree of routes
with its behavior. Compose by nesting. See
middleware pages.
Connecting HTTP to actors
Section titled “Connecting HTTP to actors”The route handler returns a Promise<HttpResponse> — you can
freely await actor calls inside:
import {} from 'actor-ts';
const routes = path('orders', path(':id', get(async (req) => { const id = req.path.split('/').pop(); const order = await orderRegistry.ask({ kind: 'get', id }, 5_000,); return completeJson(200, order); }), ),);This is the common pattern — HTTP handlers act as a thin adapter: parse the request, ask an actor, marshal the reply. Keep business logic in actors; HTTP handlers stay short.
Where to next
Section titled “Where to next”- Route DSL — the full DSL:
path,get/post/put/etc.,concat,complete*,redirect,reject. - Marshalling —
entity<T>, Content-Type-driven decoding, response encoding. - Fastify backend — default backend’s configuration.
- Bun.serve backend / Express backend — alternatives.
- Response cache middleware — caching for GET responses.
- Rate limit middleware — per-key rate limiting.
- Idempotency-key middleware — write-deduplication for mutations.
The HttpExtension API
reference covers the full surface.