DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
DetWebServer Class Reference

Single-port HTTP server with deterministic, zero-allocation execution. More...

#include <dwserver.h>

Public Member Functions

 DetWebServer ()
 Construct a DetWebServer with an empty routing table.
 
int32_t listen (uint16_t port, ConnProto proto=ConnProto::PROTO_HTTP)
 Register a port to listen on when begin() is called.
 
int32_t begin (const WebServerConfig *cfg=nullptr)
 Initialize all connection slots and open all registered listeners.
 
int32_t begin (uint16_t port, const WebServerConfig *cfg=nullptr)
 Convenience overload: register port as HTTP and start listening.
 
void stop ()
 Gracefully stop the server.
 
int32_t restart (const WebServerConfig *cfg=nullptr)
 Hard-reset all connections and re-open all registered listeners.
 
void on (const char *path, HttpMethod method, Handler callback)
 Register a route handler.
 
void on (const char *path, HttpMethod method, Handler callback, DetIface iface)
 Register a route that only matches on a specific network interface.
 
void on_regex (const char *pattern, HttpMethod method, Handler callback)
 Register a route whose path is a regular expression.
 
void set_ap_ip (uint32_t ap_ip)
 Tell the server the softAP IPv4 address for STA/AP route filtering.
 
void on_not_found (Handler callback)
 Register a fallback handler for unmatched requests.
 
void on_request_log (RequestLogCb cb)
 Install a per-request access-log callback (one hook, no buffering).
 
void use (Middleware mw)
 Register a middleware to run before every request is dispatched.
 
void enable_rate_limit (uint16_t max_requests, uint32_t window_ms)
 Enable a built-in fixed-window request rate limiter.
 
void set_cors (const char *origin)
 Enable CORS by pre-building the Access-Control headers.
 
void set_cache_control (const char *value)
 Set the Cache-Control header emitted for static files.
 
void handle ()
 Drive the server - call every Arduino loop() iteration.
 
void service_once (int worker_id=0)
 Run exactly one service iteration for worker worker_id (the body driven by that worker's task, or by handle() when no task is running).
 
void http_poll_slot (uint8_t slot_id)
 The instance-bound HTTP poll pump for one slot (the HTTP ProtoHandler's on_poll).
 
bool defer (uint8_t slot, detws_deferred_fn fn, void *arg)
 Run fn(arg) on the worker that owns connection slot.
 
void send (uint8_t slot_id, int code, const char *content_type, const char *payload)
 Send an HTTP response with a body and close the connection.
 
void send (uint8_t slot_id, int code, const char *content_type, const uint8_t *body, size_t body_len)
 Send an HTTP response with an explicit-length (possibly binary) body.
 
void send_empty (uint8_t slot_id, int code)
 Send a headers-only HTTP response and close the connection.
 
void redirect (uint8_t slot_id, int code, const char *location)
 Send an HTTP redirect (Location header, empty body) and close.
 
void send_template (uint8_t slot_id, int code, const char *content_type, const char *tmpl, TemplateVar resolver)
 Send a response body with {{name}} placeholders substituted.
 
void send_chunked (uint8_t slot_id, int code, const char *content_type, ChunkSource source, void *ctx=nullptr)
 Stream a response body of unknown length via chunked transfer.
 
void add_response_header (uint8_t slot_id, const char *name, const char *value)
 Queue a custom response header for the next send on this slot.
 
void set_cookie (uint8_t slot_id, const char *name, const char *value, const char *attrs=nullptr)
 Queue a Set-Cookie response header for the next send on this slot.
 
void clear_response_headers (uint8_t slot_id)
 Discard any headers/cookies queued for this slot.
 

Static Public Member Functions

static const char * mime_type (const char *path)
 Guess a Content-Type from a path's file extension.
 

Detailed Description

Single-port HTTP server with deterministic, zero-allocation execution.

Typical usage

DetWebServer server;
void handle_api(uint8_t slot_id, HttpReq *req) {
server.send(slot_id, 200, "application/json", "{\"ok\":true}");
}
void setup() {
WiFi.begin("SSID", "PASSWORD");
server.on("/api/status", HttpMethod::HTTP_GET, handle_api);
server.set_cors("*");
int32_t result = server.begin(80);
if (result < 0) { } // DetWebServerResult code: startup failed
}
void loop() {
server.handle(); // call every iteration - O(MAX_CONNS) per call
}
Single-port HTTP server with deterministic, zero-allocation execution.
Definition dwserver.h:348
void on(const char *path, HttpMethod method, Handler callback)
Register a route handler.
Definition dwserver.cpp:759
void handle()
Drive the server - call every Arduino loop() iteration.
void send(uint8_t slot_id, int code, const char *content_type, const char *payload)
Send an HTTP response with a body and close the connection.
void set_cors(const char *origin)
Enable CORS by pre-building the Access-Control headers.
Definition dwserver.cpp:866
int32_t begin(const WebServerConfig *cfg=nullptr)
Initialize all connection slots and open all registered listeners.
Definition dwserver.cpp:495
@ HTTP_GET
Safe, idempotent read.
Fully-parsed HTTP/1.1 request.

Design constraints

  • Maximum simultaneous connections: MAX_CONNS (default 4).
  • Maximum registered routes: MAX_ROUTES (default 16).
  • Responses are sent synchronously and the TCP connection is closed immediately after every response (HTTP/1.0 close semantics).

Definition at line 347 of file dwserver.h.

Constructor & Destructor Documentation

◆ DetWebServer()

DetWebServer::DetWebServer ( )

Construct a DetWebServer with an empty routing table.

All route slots are marked inactive. CORS is disabled. The not-found handler is null (falls back to built-in 404 response).

Definition at line 236 of file dwserver.cpp.

References MAX_CONNS, MAX_MIDDLEWARE, and MAX_ROUTES.

Member Function Documentation

◆ listen()

int32_t DetWebServer::listen ( uint16_t  port,
ConnProto  proto = ConnProto::PROTO_HTTP 
)

Register a port to listen on when begin() is called.

Call this before begin() for each port you want the server to accept connections on. The proto argument tells the session layer which protocol handler to invoke for events on this port.

For the common single-HTTP-port case, prefer begin(80) which calls this internally. Use the explicit listen() + begin() form when you need multiple ports (e.g., HTTP on 80 and Telnet on 23).

server.listen(80, ConnProto::PROTO_HTTP);
server.listen(23, ConnProto::PROTO_TELNET);
server.begin();
@ PROTO_HTTP
HTTP/1.1 with optional WS and SSE upgrades.
@ PROTO_TELNET
Telnet (RFC 854).
Parameters
portTCP port to open.
protoApplication protocol; defaults to ConnProto::PROTO_HTTP.
Returns
the listener id (a non-negative index) on success - pass it to det_relay_publish() / ssh_forward_begin(); DetWebServerResult::DETWS_ERR_LISTENER_FULL if the pool is full.

Definition at line 411 of file dwserver.cpp.

References DETWS_ERR_LISTENER_FULL, and MAX_LISTENERS.

Referenced by begin().

◆ begin() [1/2]

int32_t DetWebServer::begin ( const WebServerConfig cfg = nullptr)

Initialize all connection slots and open all registered listeners.

Resets the HTTP parser pool, calls DeterministicAsyncTCP::pool_init(), then calls listener_add() for each port registered via listen(). Requires at least one prior listen() call. For the common single-port case use begin(port, cfg) instead.

Parameters
cfgOptional runtime configuration. Pass nullptr for defaults.
Returns
DetWebServerResult::DETWS_OK on success; DetWebServerResult::DETWS_ERR_NO_LISTENERS if no ports were registered; DetWebServerResult::DETWS_ERR_LISTEN_FAILED if a listener could not open.

Definition at line 495 of file dwserver.cpp.

References DETWS_ENABLE_HTTP3, DETWS_ERR_LISTEN_FAILED, DETWS_ERR_NO_LISTENERS, DETWS_OK, detws_workers_start(), http_reset(), listener_add(), MAX_CONNS, DeterministicAsyncTCP::pool_init(), sse_init(), InstanceCtx::worker_server, and ws_init().

Referenced by begin(), and restart().

◆ begin() [2/2]

int32_t DetWebServer::begin ( uint16_t  port,
const WebServerConfig cfg = nullptr 
)

Convenience overload: register port as HTTP and start listening.

Equivalent to listen(port); begin(cfg);. Preserved for backward compatibility with single-port sketches.

Parameters
portTCP port to listen on (typically 80).
cfgOptional runtime configuration. Pass nullptr for defaults.
Returns
DetWebServerResult::DETWS_OK on success; a negative DetWebServerResult on failure.

Definition at line 561 of file dwserver.cpp.

References begin(), and listen().

◆ stop()

void DetWebServer::stop ( )

Gracefully stop the server.

Aborts all active connections, closes the listener, frees the event queue, and resets all HTTP parser slots. The WiFi and TCP/IP stack remain active. Call begin() or restart() to bring the server back up.

Definition at line 715 of file dwserver.cpp.

References detws_workers_stop(), http_reset(), listener_stop_all(), MAX_CONNS, sse_init(), DeterministicAsyncTCP::stop(), and ws_init().

Referenced by restart().

◆ restart()

int32_t DetWebServer::restart ( const WebServerConfig cfg = nullptr)

Hard-reset all connections and re-open all registered listeners.

Equivalent to stop() followed by begin(cfg) using the ports and protocols registered via listen() (or the port passed to begin(port)). The WiFi and TCP/IP stack are not touched.

Calling restart() before any listen() / begin(port) has no effect and returns -1.

Parameters
cfgOptional new runtime configuration. Pass nullptr to reuse the compile-time default (CONN_TIMEOUT_MS).

Definition at line 707 of file dwserver.cpp.

References begin(), DETWS_ERR_NO_LISTENERS, and stop().

◆ on() [1/2]

void DetWebServer::on ( const char *  path,
HttpMethod  method,
Handler  callback 
)

Register a route handler.

Routes are matched in registration order (first match wins). A trailing * in path enables prefix matching: "/api/" followed by * matches "/api/users", "/api/devices", etc.

Parameters
pathURL path pattern, e.g. "/api/status", or a prefix ending in a * wildcard. Must be ≤ MAX_PATH_LEN - 1 characters.
methodHTTP method this route accepts.
callbackFunction called when this route is matched.
Note
Registering more than MAX_ROUTES routes silently drops extras.

Definition at line 759 of file dwserver.cpp.

References Route::callback, fill_route_base(), MAX_ROUTES, Route::method, ROUTE_HTTP, and Route::type.

◆ on() [2/2]

void DetWebServer::on ( const char *  path,
HttpMethod  method,
Handler  callback,
DetIface  iface 
)

Register a route that only matches on a specific network interface.

Identical to on(path, method, callback) but the route is invisible unless the request arrived on iface (DetIface::DETIFACE_STA or DetIface::DETIFACE_AP). A non-matching interface falls through to other routes / 404, so you can, e.g., expose a provisioning UI only on the softAP and the app API only on the station link. Requires set_ap_ip() to have been called so connections can be classified.

Parameters
pathURL path pattern.
methodHTTP method.
callbackHandler invoked on a match.
ifaceDetIface::DETIFACE_STA or DetIface::DETIFACE_AP (DetIface::DETIFACE_ANY = no filter).

Definition at line 770 of file dwserver.cpp.

References Route::callback, fill_route_base(), Route::iface_filter, MAX_ROUTES, Route::method, ROUTE_HTTP, and Route::type.

◆ on_regex()

void DetWebServer::on_regex ( const char *  pattern,
HttpMethod  method,
Handler  callback 
)

Register a route whose path is a regular expression.

The whole request path must match pattern (implicitly anchored). The matcher is a small, bounded, allocation-free backtracker supporting: . (any char), * + ? quantifiers, character classes [...] / [^...] with a-z ranges, the shorthands \d \w \s (and \D \W \S), and \ to escape a metacharacter. It is non-capturing and has no groups () or alternation | - use :name path parameters (see the other on() overload notes / http_get_param) when you need to capture. Matching is bounded by RE_MAX_STEPS and fails closed past that budget.

server.on_regex("/sensor/[0-9]+", HttpMethod::HTTP_GET, handle_sensor);
server.on_regex("/img/.+\\.png", HttpMethod::HTTP_GET, handle_png);
Parameters
patternRegex the full path must match (stored, <= MAX_PATH_LEN-1).
methodHTTP method.
callbackHandler invoked on a match.

Definition at line 787 of file dwserver.cpp.

References Route::callback, fill_route_base(), Route::is_regex, MAX_ROUTES, Route::method, ROUTE_HTTP, and Route::type.

◆ set_ap_ip()

void DetWebServer::set_ap_ip ( uint32_t  ap_ip)

Tell the server the softAP IPv4 address for STA/AP route filtering.

Each accepted connection is tagged DetIface::DETIFACE_AP when its local IP equals ap_ip, else DetIface::DETIFACE_STA. Call once after starting the softAP, e.g. server.set_ap_ip(WiFi.softAPIP()) (IPAddress converts to uint32_t). Without it, every connection is treated as DetIface::DETIFACE_STA.

Parameters
ap_ipsoftAP IPv4 address in network byte order (0 to clear).

Definition at line 782 of file dwserver.cpp.

References detws_ap_ip.

◆ on_not_found()

void DetWebServer::on_not_found ( Handler  callback)

Register a fallback handler for unmatched requests.

Called instead of sending a built-in 404 when no route matches. The callback may call send() to return a custom error page.

Parameters
callbackHandler to invoke on a 404 condition.

Definition at line 848 of file dwserver.cpp.

◆ on_request_log()

void DetWebServer::on_request_log ( RequestLogCb  cb)

Install a per-request access-log callback (one hook, no buffering).

cb is invoked once per response with the method, path, status code, and response body length. Pass nullptr to remove. See RequestLogCb.

Definition at line 259 of file dwserver.cpp.

◆ use()

void DetWebServer::use ( Middleware  mw)

Register a middleware to run before every request is dispatched.

Middlewares run in registration order (see Middleware) ahead of route matching, after the built-in rate-limit check. Up to MAX_MIDDLEWARE may be registered; further calls are ignored. Use this to add cross-cutting behavior - request logging, custom auth, header injection, feature gating - composed independently of individual routes.

static MwResult log_mw(uint8_t slot, HttpReq *req) {
Serial.printf("%s %s\n", req->method, req->path);
return MwResult::MW_NEXT; // fall through to the handler
}
server.use(log_mw);
MwResult
Outcome of a middleware function (see Middleware).
Definition dwserver.h:138
@ MW_NEXT
Continue to the next middleware / the route handler.
char method[DETWS_METHOD_BUF_SIZE]
HTTP method, null-terminated (OPTIONS, or WebDAV methods when enabled).
char path[MAX_PATH_LEN]
URL path, null-terminated; no query string.
Parameters
mwMiddleware function pointer (must not be nullptr).

Definition at line 22 of file middleware.cpp.

References MAX_MIDDLEWARE.

◆ enable_rate_limit()

void DetWebServer::enable_rate_limit ( uint16_t  max_requests,
uint32_t  window_ms 
)

Enable a built-in fixed-window request rate limiter.

Counts all incoming requests in a sliding fixed window; once more than max_requests arrive within window_ms the server answers further requests in that window with 429 Too Many Requests (plus a Retry-After header) instead of dispatching them. The check runs before the middleware chain and route matching, so it bounds work under flood. State is a few per-server counters (no heap, no per-IP table) - a global throttle suited to a small device behind a trusted LAN. For connection-level flood defense see also DETWS_ENABLE_ACCEPT_THROTTLE.

Parameters
max_requestsRequests allowed per window. Pass 0 to disable.
window_msWindow length in milliseconds (must be > 0).

Definition at line 41 of file middleware.cpp.

◆ set_cors()

void DetWebServer::set_cors ( const char *  origin)

Enable CORS by pre-building the Access-Control headers.

Once called, every response produced by send() and send_empty() includes the CORS headers. OPTIONS requests are intercepted and answered with 204 automatically (preflight short-circuit).

Parameters
originAccess-Control-Allow-Origin value, e.g. "*" or "https://example.com". Pass "" to disable CORS.

Definition at line 866 of file dwserver.cpp.

References CORS_HDR_BUF_SIZE.

◆ set_cache_control()

void DetWebServer::set_cache_control ( const char *  value)

Set the Cache-Control header emitted for static files.

Applies to serve_file() / serve_static() responses (beside the ETag), so browsers can cache assets and revalidate cheaply with If-None-Match. Examples: "no-cache" (cache but always revalidate), "max-age=3600", "public, max-age=31536000, immutable". Pass "" / nullptr to disable.

Parameters
valueCache-Control directive, or empty/null to emit no header.

Definition at line 882 of file dwserver.cpp.

References CACHE_CONTROL_BUF_SIZE.

◆ handle()

void DetWebServer::handle ( )

Drive the server - call every Arduino loop() iteration.

Main application tick - tick the session layer then dispatch completed requests.

On ESP32 begin() spawns the server worker task(s) (see DETWS_WORKER_COUNT), which run the pipeline on their own core; handle() is then a no-op and your loop() is free for application code. On host builds (and if no worker task is running) handle() drives one service iteration inline, so existing sketches and the native tests keep working unchanged.

One service iteration (see service_once()):

  1. Calls DeterministicAsyncTCP::check_timeouts() to kill stale connections.
  2. Drains the event queue (connections, data, disconnects, errors).
  3. Scans all connection slots for ParseState::PARSE_COMPLETE requests and dispatches them to the matching route handler.
  4. Auto-sends 400 for any slot stuck in ParseState::PARSE_ERROR.
  5. Auto-sends 413 for any slot stuck in ParseState::PARSE_ENTITY_TOO_LARGE.
  6. Auto-sends 414 for any slot stuck in ParseState::PARSE_URI_TOO_LONG.

Threading note: with the worker task running, route/WS/SSE handlers execute in the worker task. Do server I/O from handlers; pushing from loop() (e.g. SSE broadcast on a timer) runs concurrently with the worker and is made thread-safe in a later phase.

Call this repeatedly from loop(). Each call:

  1. Calls server_tick() which runs timeout sweeps + drains the event queue.
  2. Walks all slots; any in ParseState::PARSE_COMPLETE is dispatched via match_and_execute().
  3. Any slot left in ParseState::PARSE_COMPLETE after dispatch (i.e., callback did not send a response) is reset so it doesn't block the slot.
  4. Any slot in ParseState::PARSE_ERROR receives an automatic 400 response.
  5. Any slot in ParseState::PARSE_ENTITY_TOO_LARGE receives an automatic 413 response.
  6. Any slot in ParseState::PARSE_URI_TOO_LONG receives an automatic 414 response.

Definition at line 1009 of file dwserver.cpp.

References detws_workers_running(), and service_once().

◆ service_once()

void DetWebServer::service_once ( int  worker_id = 0)

Run exactly one service iteration for worker worker_id (the body driven by that worker's task, or by handle() when no task is running).

Services only the connection slots owned by worker_id, so multiple workers run disjoint slot sets in parallel. At DETWS_WORKER_COUNT=1 worker 0 owns every slot. Public so the worker task can invoke it; application code should call handle() rather than this directly.

Definition at line 1019 of file dwserver.cpp.

References conn_pool, det_conn_ack_consumed(), detws_millis(), detws_worker_run_deferred(), InstanceCtx::http_instance, http_proto_set_poll(), MAX_CONNS, ProtoHandler::on_poll, proto_get(), and server_tick().

Referenced by handle().

◆ http_poll_slot()

void DetWebServer::http_poll_slot ( uint8_t  slot_id)

The instance-bound HTTP poll pump for one slot (the HTTP ProtoHandler's on_poll).

Installed into the HTTP handler at begin() via http_proto_set_poll() so the worker dispatch loop pumps HTTP through the same uniform ProtoHandler seam as every other protocol - there is no HTTP special case in the loop. Runs the file/chunk send pumps, the WebSocket + SSE drains, the keep-alive re-parse, and dispatches a completed request into this server's routes. Public only so the poll trampoline can reach it (like service_once); application code never calls it directly.

Parameters
slot_idConnection slot to pump.

Definition at line 1075 of file dwserver.cpp.

References ChunkSend::active, SendCtx::chunk, CONN_ACTIVE, conn_pool, det_conn_abort_slot(), det_conn_begin_close(), DETWS_ENABLE_TLS, http_parse(), http_pool, http_reset(), PARSE_COMPLETE, PARSE_ENTITY_TOO_LARGE, PARSE_ERROR, WsConn::parse_state, PARSE_URI_TOO_LONG, s_send, send(), sse_find(), WS_CLOSED, WS_ERROR, ws_feed_byte(), ws_find(), WS_FRAME_READY, ws_free(), ws_parse(), and ws_reset_frame().

◆ defer()

bool DetWebServer::defer ( uint8_t  slot,
detws_deferred_fn  fn,
void *  arg 
)

Run fn(arg) on the worker that owns connection slot.

The thread-safe way to push to a connection from outside a handler - e.g. an SSE broadcast or a ws_send from loop() or a sensor task. Calling the send API directly from another task would race the worker that owns the slot; instead wrap the send in fn and defer it, and it runs single-threaded in the owning worker's context. arg must stay valid until the callback runs. On host builds (no worker task) it runs inline immediately.

Returns
false if the slot is invalid or the worker's defer queue is full.

Definition at line 1201 of file dwserver.cpp.

References conn_pool, detws_defer(), and MAX_CONNS.

◆ send() [1/2]

void DetWebServer::send ( uint8_t  slot_id,
int  code,
const char *  content_type,
const char *  payload 
)

Send an HTTP response with a body and close the connection.

Writes status line, Content-Type, Content-Length, optional CORS headers, and the payload; then calls tcp_close (tcp_abort on failure). Always calls http_reset() at the end to free the parser slot.

Parameters
slot_idConnection slot index returned by the router.
codeHTTP status code (200, 404, 500, …).
content_typeMIME type string, e.g. "application/json".
payloadNull-terminated response body.
Note
If the underlying PCB has already been freed (e.g. by a concurrent timeout), this function is a no-op that just resets the slot.

Definition at line 1582 of file dwserver.cpp.

References send().

Referenced by http_poll_slot(), and send().

◆ send() [2/2]

void DetWebServer::send ( uint8_t  slot_id,
int  code,
const char *  content_type,
const uint8_t *  body,
size_t  body_len 
)

Send an HTTP response with an explicit-length (possibly binary) body.

Same as send() above but the body length is given, so the body may contain NUL bytes (protobuf, gRPC-web frames, octet-stream, images). body_len is bounded by the single-write limit (65535); larger bodies need the chunked/file path.

Parameters
slot_idConnection slot index returned by the router.
codeHTTP status code.
content_typeMIME type string, e.g. "application/grpc-web+proto".
bodyResponse body (may contain NULs); not required to be terminated.
body_lenNumber of body octets.

Definition at line 1588 of file dwserver.cpp.

References CONN_ACTIVE, conn_pool, CONN_POOL_SLOTS, det_conn_send(), det_conn_send_flush(), http_reset(), TcpConn::pcb, req_is_head(), RESP_HDR_BUF_SIZE, TcpConn::state, and status_text().

◆ send_empty()

void DetWebServer::send_empty ( uint8_t  slot_id,
int  code 
)

Send a headers-only HTTP response and close the connection.

Equivalent to send() with an empty body and Content-Length: 0. Useful for 204 No Content, 304 Not Modified, HEAD responses, and CORS preflight replies.

Parameters
slot_idConnection slot index.
codeHTTP status code.

Definition at line 1662 of file dwserver.cpp.

References CONN_ACTIVE, conn_pool, CONN_POOL_SLOTS, det_conn_send_flush(), http_reset(), TcpConn::pcb, RESP_HDR_BUF_SIZE, TcpConn::state, and status_text().

◆ redirect()

void DetWebServer::redirect ( uint8_t  slot_id,
int  code,
const char *  location 
)

Send an HTTP redirect (Location header, empty body) and close.

Convenience for the common //index.html or canonical-host case, previously hand-rolled via send_empty() plus a manual Location header.

Parameters
slot_idConnection slot index.
codeRedirect status: 301, 302, 303, 307, or 308. Any other value is treated as 302 Found.
locationValue for the Location response header.

Definition at line 1695 of file dwserver.cpp.

References CONN_ACTIVE, conn_pool, det_conn_send_flush(), http_reset(), MAX_CONNS, TcpConn::pcb, RESP_HDR_BUF_SIZE, TcpConn::state, and status_text().

◆ send_template()

void DetWebServer::send_template ( uint8_t  slot_id,
int  code,
const char *  content_type,
const char *  tmpl,
TemplateVar  resolver 
)

Send a response body with {{name}} placeholders substituted.

Streams tmpl to the client, replacing each {{name}} token with the string returned by resolver (nullptr → empty). The body is never buffered whole: it is walked twice - once to compute Content-Length, once to write - so memory use is constant regardless of body size. A {{ with no matching }} (or a name longer than 32 chars) is emitted literally.

Parameters
slot_idConnection slot index.
codeHTTP status code.
content_typeResponse Content-Type.
tmplNull-terminated template text.
resolverPlaceholder resolver (see TemplateVar), or nullptr.

Definition at line 90 of file response.cpp.

References det_conn_send(), http_reset(), MAX_CONNS, req_is_head(), RESP_HDR_BUF_SIZE, and status_text().

◆ send_chunked()

void DetWebServer::send_chunked ( uint8_t  slot_id,
int  code,
const char *  content_type,
ChunkSource  source,
void *  ctx = nullptr 
)

Stream a response body of unknown length via chunked transfer.

Writes the status line and headers (including Transfer-Encoding: chunked, plus any CORS / queued custom headers), then pulls the body from source one piece at a time, adding the chunk framing and the terminating chunk. The body is never buffered whole and the send paces with the TCP window - paging across server loops as it drains - so output size is unbounded in constant memory and a body larger than the send buffer is never truncated. This is the complement to send(), which needs the full payload up front. A HEAD request sends the headers only (source is not called).

Parameters
slot_idConnection slot index.
codeHTTP status code.
content_typeResponse Content-Type.
sourceGenerator that produces the body (must not be nullptr).
ctxOpaque state handed to source; see ChunkSource for the lifetime requirement (must outlive the response).

Definition at line 137 of file response.cpp.

References ChunkSend::active, SendCtx::chunk, ChunkSend::ctx, det_conn_send(), HTTP_11, http_pool, http_reset(), ChunkSend::keep, MAX_CONNS, ChunkSend::raw, req_is_head(), RESP_HDR_BUF_SIZE, s_send, ChunkSend::source, ChunkSend::status, status_text(), ChunkSend::total, and HttpReq::version.

◆ add_response_header()

void DetWebServer::add_response_header ( uint8_t  slot_id,
const char *  name,
const char *  value 
)

Queue a custom response header for the next send on this slot.

Call from inside a handler before send() / send_empty() / redirect(). The header is appended to a fixed per-slot buffer (EXTRA_HDR_BUF_SIZE) and emitted verbatim as Name: value\r\n. Headers that would overflow the buffer are dropped whole (never truncated mid-line). The buffer is cleared automatically at the start of each request.

Parameters
slot_idConnection slot index.
nameHeader field name (no : or CRLF).
valueHeader field value (no CRLF).

Definition at line 276 of file response.cpp.

References EXTRA_HDR_BUF_SIZE, and MAX_CONNS.

◆ set_cookie()

void DetWebServer::set_cookie ( uint8_t  slot_id,
const char *  name,
const char *  value,
const char *  attrs = nullptr 
)

Queue a Set-Cookie response header for the next send on this slot.

Emits Set-Cookie: name=value\r\n, or Set-Cookie: name=value; attrs\r\n when attrs is non-null (e.g. "Path=/; HttpOnly; Max-Age=3600"). Shares the per-slot buffer with add_response_header().

Parameters
slot_idConnection slot index.
nameCookie name.
valueCookie value.
attrsOptional ;-separated attribute string, or nullptr.

Definition at line 289 of file response.cpp.

References EXTRA_HDR_BUF_SIZE, and MAX_CONNS.

◆ clear_response_headers()

void DetWebServer::clear_response_headers ( uint8_t  slot_id)

Discard any headers/cookies queued for this slot.

Parameters
slot_idConnection slot index.

Definition at line 306 of file response.cpp.

References MAX_CONNS.

◆ mime_type()

const char * DetWebServer::mime_type ( const char *  path)
static

Guess a Content-Type from a path's file extension.

Small static extension→type table covering the common web asset types (html, css, js, json, svg, png, jpg, gif, ico, txt, wasm, woff2, …). Case-insensitive on the extension. Falls back to "application/octet-stream" when the extension is unknown or absent.

Parameters
pathFile path or name (e.g. "/css/site.css").
Returns
Static content-type string (never null).

Definition at line 317 of file response.cpp.


The documentation for this class was generated from the following files: