Repository navigation
Core Concepts
Mesh is not a framework. It's a collection of helpers that sit between zap (the HTTP library) and your handler code. Before diving into individual modules, it helps to understand a few ideas that repeat everywhere.
Every incoming HTTP request goes through the same path:
-
zapparses the request into azap.Request- method, path, query params, headers, and body. - Your handler is called with that request.
-
The handler sends a response using one of the
Mesh.responsehelpers.
Mesh only touches step 3, and only the parts of step 2 that deal with parsing inputs.
Any helper that can fail on bad input - MethodCheck, parseFromBody, getParamStrSave - will send the HTTP error response itself before returning null. Your job is just to bail out.
if (method.MethodCheck(r, &.{.POST}) == null) return;
const payload = json.parseFromBody(Payload, arena.allocator(), r) orelse return;There is no second response attempt, no double-send, no cleanup. The null is the signal.
Once a response has been written, there's nothing useful left to do if the write fails. So sendBody and friends print the error to stderr and return void. That's why you see catch {} at the end of json.send(...) - the only real failure left is a serialization error, and even that is usually ignored.
JSON parsing allocates internal structures you don't want to track individually. Every handler that parses JSON should do this:
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();One deinit() frees everything - the parsed tree, intermediate buffers, and any strings the parser allocated. The pattern is uniform across all examples.
If you want to know why arenas work well here: std.json.parseFromSlice builds a tree of heap-allocated nodes that reference each other. Freeing them manually means walking the tree; an arena reduces that to a single call.
| Entity | Comes from | Used for |
|---|---|---|
zap.Request |
Mesh.zap |
The request object. Passed to every helper. |
zap.http.StatusCode |
Mesh.zap |
Status codes - .ok, .bad_request, .not_found, etc. |
response |
Mesh.response |
Sending bodies and errors. |
method |
Mesh.method |
Checking the HTTP method. |
json |
Mesh.json |
Parsing and serializing JSON. |
DB |
Mesh package | Wrapper over a real ddb.DB or a VoidDB. |
VoidDB |
Mesh.VoidDB |
A no-op database stub. |
-
It doesn't route. That's
ServerandRouteNode(not covered in this wiki). -
It doesn't touch headers. Use
zapdirectly. - It doesn't validate. If a field is missing or the wrong type, you get a parse error - nothing more.
-
It doesn't manage DB lifetime. The
DBwrapper is a non-owning handle; you're responsible for the underlyingddb.DBorVoidDB.
Start with Response - it defines the primitives every other module uses to talk to the client. After that, the modules are independent.