Header: <cwist/net/http/http.h>
Low-level HTTP structures, framing limits, and parsing logic.
Defined in <cwist/net/http/http.h> to guard every connection against resource exhaustion.
CWIST_HTTP_MAX_HEADER_SIZE– cap on accumulated header bytes (default 8KiB).CWIST_HTTP_MAX_BODY_SIZE– cap on POST body bytes kept in memory (default 10MiB).CWIST_HTTP_READ_BUFFER_SIZE– scratch buffer per connection for pipelined/keep‑alive traffic.CWIST_HTTP_TIMEOUT_MS– poll timeout used while waiting for header/body as well as while sending responses.
cwist_http_request *cwist_http_request_create(void);Allocates a new HTTP request structure.
cwist_app_listen wires each inbound request with framework context:
req->app– back-reference to the runningcwist_app(useful for pulling global config).req->db– sharedcwist_dbhandle configured viacwist_app_use_db.
cwist_http_request *cwist_http_parse_request(const char *raw_request);Parses a raw HTTP string into a cwist_http_request object.
cwist_http_request *cwist_http_receive_request(
int client_fd,
char *read_buf,
size_t buf_size,
size_t *buf_len
);Blocking, framed read helper for keep-alive sockets.
- Reads until
\r\n\r\n, enforcingCWIST_HTTP_MAX_HEADER_SIZE. - Parses headers plus
Content-Lengthand continues polling/recving until the full body is buffered. - Leaves any bytes for the next request in
read_buf; caller passes the same buffer back in the next iteration. - Returns
NULLon timeout, malformed framing, or when limits are exceeded.
cwist_http_response *cwist_http_response_create(void);Allocates a new HTTP response structure. Default status is 200 OK.
cwist_error_t cwist_http_response_send_file(
cwist_http_response *res,
const char *file_path,
const char *content_type_hint,
size_t *out_size
);Reads a static file from disk, copies it into the response body, and sets a sensible Content-Type. Files larger than CWIST_HTTP_MAX_BODY_SIZE are rejected with -EFBIG unless the route is tagged with CWIST_ENDPOINT_FILE, which switches Linux/macOS/FreeBSD to sendfile(2) so the kernel streams the payload directly. Returns 0 on success and propagates -errno on failures (-ENOENT, -EISDIR, etc.). out_size is optional; when provided it receives the file length so handlers can emit HEAD responses without buffering the payload. The built-in table includes modern web extensions such as .wasm and .mjs.
cwist_error_t cwist_http_header_add(cwist_http_header_node **head, const char *key, const char *value);Adds a header to the linked list.
char *cwist_http_header_get(cwist_http_header_node *head, const char *key);Retrieves the value of a header by key. Returns NULL if not found.
Header lookup is case-insensitive (Host and host are equivalent).
static_http_handler in src/framework/app.c now loops on cwist_http_receive_request until either side requests Connection: close. Each response generated via cwist_http_send_response() contains an explicit Content-Length, and the send path uses poll()+send(MSG_NOSIGNAL) to avoid blocking indefinitely or tripping SIGPIPE while ApacheBench is bursting 64 concurrent keep-alive posts.
tests/stress_test.c spins up a minimal /api endpoint and shells out to:
ab -k -n 20000 -c 64 -p payload.json -T application/json http://127.0.0.1:31744/api
The test succeeds only when the server drains each request body, recycles the leftover bytes for the next request on the same socket, and finalizes every response without triggering apr_pollset_poll timeout or connection reset.
cwist_error_t cwist_http_server_loop(int server_fd, cwist_server_config *config, void (*handler)(int, void *), void *ctx);Starts the main server loop.
- Supports iterative, forking, and multithreaded models via
config. ctxis passed to the handler for thread-safe state management.
cwist_error_t cwist_accept_socket(int server_fd, struct sockaddr *sockv4, void (*handler_func)(int, void *), void *ctx);Low-level accept loop wrapper.
long cwist_http_continuation_shed_count(void);Monotonic counter of pipelined HTTP/1.1 continuations dropped (and whose connections were closed) because the reactor post queue was full. Also exposed via Prometheus /metrics as cwist_http_continuation_shed_total. Useful for backpressure and shed-rate alerting.
void cwist_http_response_add_security_headers(cwist_http_response *res);Injects a default set of hardening headers into the response if each is not already present (first-one-wins, so a handler can pre-set a header to override the default). Safe to call on both HTTP and HTTPS responses. Does not set Strict-Transport-Security; use cwist_http_response_add_hsts() for that.
Headers set by this function:
| Header | Default value |
|---|---|
X-Frame-Options |
DENY |
X-Content-Type-Options |
nosniff |
Referrer-Policy |
strict-origin-when-cross-origin |
Content-Security-Policy |
restricted default-src/script-src/style-src/font-src/img-src policy |
Cross-Origin-Resource-Policy |
same-origin |
Permissions-Policy |
camera/microphone/geolocation/payment/usb/interest-cohort all denied |
Cross-Origin-Opener-Policy |
same-origin |
void cwist_http_response_add_hsts(cwist_http_response *res);Adds Strict-Transport-Security: max-age=31536000; includeSubDomains to a TLS response. No-op when the header is already present. Per RFC 6797 section 7.2, call this only from an HTTPS handler; never call it on a plain-HTTP response.