HTTP basics: the view struct and the three-way return
What RequestProc receives is not a wrapped object but a set of native xrt pointers you can act on directly. This chapter completes the map of that view — the next four chapters all work on it.
Overview
14.1 Intro
Writing HTTP business code needs three things: knowing what the request is (method, path, headers, body), knowing where to write the response (the transport), and knowing who takes over after you. Most frameworks knead all three into a Request/Response object, trading abstraction for convenience; XServer hands you the three things apart — the six fields of XS_HttpReq are their addresses.
14.2 XS_HttpReq field by field
typedef struct {
xnetstream* tcp; /* exactly one of tcp/tls non-null: raw transport */
xtlsstream* tls; /* the full xrt stream/send API applies */
const xhttp1head* head; /* incl. MethodCode; view valid in the callback */
xhttp1body* body; /* framing machine: fixed / chunked / close */
const XS_HostInfo* host;
XS_ServerInfo* server;
} XS_HttpReq;
| Field | Purpose | Use in this chapter |
|---|---|---|
tcp / tls | response outlet | sending response bytes (ch15) |
head | request identity | MethodCode, path, field views (14.3) |
body | request body | incremental reading (ch16) |
host / server | ownership | topology info, Custom knobs |
Why is there no Response field? — because the response is not an object; it is the byte stream you write to the transport. That is "zero wrapping" taken to its conclusion: no hidden response buffer, and therefore no "when does the framework flush" class of problems.
14.3 Reading request headers
static XS_RequestResult RequestProc(XS_HttpReq* pReq)
{
/* method: a bit mask — single method and set element at once (ref-enums) */
if ( pReq->head->MethodCode == XHTTP_METHOD_GET ) { ... }
/* path and field views: xstrview = pointer + length, valid in the callback */
/* the concrete accessors (field lookup / path splitting) are in xrt · http1 */
return XS_FALLBACK;
}
Two iron rules for reading the head: first, the field views of head are valid only within this callback's stack — XServer copies the request head in the PinHead phase to prevent ring-buffer reuse, but it still expires after the generation swap / request ends; second, never compare paths with C string functions — views carry lengths, compare by length (the xrtStrView tooling).
14.4 Timing & threading
- Once per request; called per request on keep-alive connections
- workers concurrency — RequestProc must be reentrant (no cross-request mutable statics, or lock yourself)
- A byte-consumption cross-check runs between driver and script: a mismatch between your declared consumption and the wire severs the connection — the script is treated as an untrusted boundary
14.5 Contract
- Borrowing: all six fields are valid inside the callback; values may be copied out, pointers may not.
- Three-way: finish the response before XS_OK; one byte written means no FALLBACK; after TAKEOVER the driver steps out.
- Concurrency: RequestProc runs concurrently on workers — reentrancy is a hard requirement.
Common mistakes
- Symptom
- Sporadic wrong path decisions, especially with query strings or non-NUL-terminated buffers.
- Cause
- An xstrview is not a C string — it may carry no NUL terminator; the length is authoritative.
if ( strcmp(pPath, "/api") == 0 )/* compare by view length (xrtStrView tools) */- Symptom
- Garbled counts under concurrency, sporadic crashes.
- Cause
- Forgetting workers concurrency — statics read and written by several requests at once.
Exercises
Write a RequestProc: GET prints "GET", POST prints "POST", everything else returns XS_FALLBACK.
Count processed requests (hint: atomics, the xrtAtomic family).
Store a head view pointer in a global and read it on the next request — observe and explain; then switch to copying inside the callback.
Summary
| Point | Conclusion |
|---|---|
| View struct | tcp/tls (outlet) + head (identity) + body (payload) + host/server (ownership) |
| No Response object | the response is a byte stream into the transport (ch15) |
| Header rules | views valid in the callback; compare by length, never as C strings |
| Concurrency | reentrant on workers; consumption cross-checked against the wire |
- xrt reference · http1 — the complete xhttp1head field views and header lookup APIs
- xrt reference · string — view comparison and safe string tools