Choose http-service when one checked Topaz function should receive an
HttpRequest and return an HttpResponse. The generated native host owns the
listener, HTTP/1.1 framing, finite request budgets, overload responses,
logging, and shutdown.
This is not a general Web server framework. It does not grant outbound
networking, raw sockets, ambient environment access, shared mutable Topaz
state, TLS, HTTP/2, WebSocket, or sessions. Put a normal reverse proxy in front
of the process for public TLS and Internet-edge policy. Treat this explicit
Capability boundary as part of the product design.
Complete First Application first. Building the service requires a Rust toolchain for the deployment platform.
Create, lock, and test
The scaffold supplies the package manifest, bounded service defaults, and a concrete handler:
topaz init --target http-service --root hello-service
topaz lock --root hello-service
topaz fmt --check --root hello-service
topaz check --root hello-service --locked
topaz test --root hello-service --locked
The entry module exports exactly one handler with this shape:
import std.http { HttpRequest, HttpResponse, text }
export function handle(req: HttpRequest) -> HttpResponse {
if req.method == "GET" && req.url.path() == "/health" {
return text(200, "ok")
}
text(404, "not found")
}The checker rejects a missing, generic, variadic, defaulted, or differently typed handler before the listener can start.
Develop through loopback
Run the actual generated service on loopback and request its health route:
topaz dev --root hello-service --port 8080
curl --fail-with-body http://127.0.0.1:8080/health
topaz dev forces the bind address to 127.0.0.1, rebuilds the managed
service, and forwards interruption to it. If port 8080 is occupied, choose
another loopback port with --port.
Keep finite service budgets
The scaffold records bounded defaults under [service]:
[service]
bind = "127.0.0.1"
port = 8080
workers = 1
max_connections = 64
queue_capacity = 32
max_target_bytes = 8192
max_header_bytes = 16384
max_headers = 64
max_body_bytes = 1048576
header_timeout_ms = 5000
body_timeout_ms = 5000
handler_timeout_ms = 1000
shutdown_grace_ms = 5000
log_format = "text"
Unknown keys and out-of-range values fail during package loading. Each request gets a fresh runtime context and module graph; requests do not share a Topaz heap. Queue saturation, oversized input, handler deadlines, and invalid responses become bounded host outcomes rather than unbounded work.
Build and inspect the product
topaz build --root hello-service --locked --release --out-dir hello-service-product
cd hello-service-product
./target/release/program --print-config
./target/release/program
On Windows, run target\release\program.exe. The product tree is:
hello-service-product/
├── GENERATED-OUTPUT-NOTICE.txt
├── LICENSE
├── NOTICE
├── THIRD-PARTY-NOTICES.txt
├── target
│ └── release
│ └── program[.exe]
├── topaz-artifact.json
└── topaz-service-config.jsonprogram[.exe] means program on Unix and program.exe on Windows.
--print-config validates and prints effective settings without opening a
listener. The managed JSON file records the embedded defaults. Runtime
overrides use explicit command-line flags; an explicit non-loopback bind looks
like this:
./target/release/program --bind 0.0.0.0 --port 8080
Use that only behind the intended network boundary. The manifest itself may name only a loopback address.
Observable failures
- Oversized bodies, targets, or header sets produce bounded HTTP errors where framing permits a response.
- A full handler queue returns
503; a handler deadline returns504. - A runtime fault or invalid application response returns a generic
500without exposing source paths, request content, or Topaz fault text. - Responses and host logs share a request ID. Logs omit targets, bodies, and header values.
SIGINTand, on Unix,SIGTERMstop admission and drain existing work untilshutdown_grace_ms.
If check or test fails, repair the Topaz diagnostic and repeat the same
command. If a build finds a changed managed file or another target in the
output directory, keep that directory for inspection and choose a new empty
--out-dir.
Source-free deployment
Copy the complete hello-service-product/ directory so the executable,
configuration record, integrity manifest, licenses, and notices stay together.
The copied product needs neither package source, Topaz CLI, a registry, nor
the temporary Cargo workspace. Run it under a process supervisor, retain the
generated budgets, and terminate public TLS at a reverse proxy.