Skip to content

Core Concepts

Neon32eeee edited this page Oct 17, 2026 · 1 revision

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.

The request lifecycle

Every incoming HTTP request goes through the same path:

  1. zap parses the request into a zap.Request - method, path, query params, headers, and body.
  2. Your handler is called with that request.
  3. The handler sends a response using one of the Mesh.response helpers.

Mesh only touches step 3, and only the parts of step 2 that deal with parsing inputs.

Two conventions that shape everything

1. Helpers send their own error responses

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.

2. Responses swallow send errors

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.

Memory: use an arena

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 overview

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.

What Mesh does not do

  • It doesn't route. That's Server and RouteNode (not covered in this wiki).
  • It doesn't touch headers. Use zap directly.
  • 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 DB wrapper is a non-owning handle; you're responsible for the underlying ddb.DB or VoidDB.

Where to go next

Start with Response - it defines the primitives every other module uses to talk to the client. After that, the modules are independent.

Clone this wiki locally