xhttp — Asynchronous HTTP
Introduction
xhttp is xKit's HTTP module, providing both a fully asynchronous HTTP client and server, all powered by xbase's event loop.
- The client uses libcurl's multi-socket API for non-blocking HTTP requests and SSE streaming — ideal for integrating with REST APIs and LLM streaming endpoints. Supports TLS configuration including custom CA certificates, mutual TLS (mTLS), and certificate verification control via
xTlsConf. - The server uses an
xHttpProtovtable interface for protocol-abstracted parsing, supporting both HTTP/1.1 (llhttp) and HTTP/2 (nghttp2, h2c Prior Knowledge) on the same port. TLS listeners are supported viaxHttpServerListenTlswithxTlsConf. Single-threaded, event-driven connection handling — ideal for building lightweight HTTP services and APIs. - WebSocket support includes both server and client. On the server side, call
xWsUpgrade()inside a regular HTTP handler to perform the RFC 6455 upgrade handshake. On the client side, usexWsConnect()to establish an async WebSocket connection to a remote endpoint. The library handles frame codec, ping/pong, fragment reassembly, and close negotiation automatically for both sides.
Design Philosophy
-
Event Loop Integration — Instead of blocking threads, xhttp registers libcurl's sockets with
xEventLoopand uses event-driven I/O. All callbacks are dispatched on the event loop thread, eliminating the need for synchronization. -
Vtable-Based Request Polymorphism — Internally, different request types (oneshot HTTP, SSE streaming) share the same curl multi handle but use different vtables for completion and cleanup. This avoids code duplication while supporting diverse response handling patterns.
-
Zero-Copy Response Delivery — Response headers and body are accumulated in
xBufferinstances and delivered to the callback as pointers. No extra copies are made. -
Automatic Resource Management — Request contexts, curl easy handles, and buffers are automatically cleaned up after the completion callback returns. In-flight requests are cancelled with error callbacks when the client is destroyed.
Architecture
graph TD
subgraph "Application"
APP["User Code"]
end
subgraph "xhttp"
CLIENT["xHttpClient"]
TLS_CLI["TLS Config<br/>(xTlsConf)"]
ONESHOT["Oneshot Request<br/>(GET/POST/Do)"]
SSE["SSE Request<br/>(GetSse/DoSse)"]
PARSER["SSE Parser<br/>(W3C spec)"]
end
subgraph "libcurl"
MULTI["curl_multi"]
EASY1["curl_easy (req 1)"]
EASY2["curl_easy (req 2)"]
end
subgraph "xbase"
LOOP["xEventLoop"]
TIMER["Timer<br/>(curl timeout)"]
FD["FD Events<br/>(socket I/O)"]
end
APP -->|"xHttpClientGet/Post/Do"| ONESHOT
APP -->|"xHttpClientGetSse/DoSse"| SSE
APP -->|"xHttpClientConf.tls"| TLS_CLI
SSE --> PARSER
ONESHOT --> CLIENT
SSE --> CLIENT
TLS_CLI --> CLIENT
CLIENT --> MULTI
MULTI --> EASY1
MULTI --> EASY2
MULTI -->|"CURLMOPT_SOCKETFUNCTION"| FD
MULTI -->|"CURLMOPT_TIMERFUNCTION"| TIMER
FD --> LOOP
TIMER --> LOOP
style CLIENT fill:#4a90d9,color:#fff
style LOOP fill:#50b86c,color:#fff
style MULTI fill:#f5a623,color:#fff
Sub-Module Overview
| File | Description | Doc |
|---|---|---|
server.h | Async HTTP/1.1 & HTTP/2 server (routing, request/response, protocol-abstracted parsing) | server.md |
client.h | Async HTTP client API (GET, POST, Do, SSE, TLS configuration) | client.md |
sse.c | SSE stream parser and request handler | sse.md |
ws.h (server) | WebSocket server API (upgrade, send, close, callbacks) | ws_server.md |
ws.h (client) | WebSocket client API (connect, send, close, callbacks) | ws_client.md |
| (guide) | TLS deployment guide (certificate generation, one-way TLS, mTLS, troubleshooting) | tls.md |
Quick Start
#include <stdio.h>
#include <xbase/event.h>
#include <xhttp/client.h>
static void on_response(const xHttpResponse *resp, void *arg) {
(void)arg;
if (resp->curl_code == 0) {
printf("Status: %ld\n", resp->status_code);
printf("Body: %.*s\n", (int)resp->body_len, resp->body);
} else {
printf("Error: %s\n", resp->curl_error);
}
}
int main(void) {
xEventLoop loop = xEventLoopCreate();
xHttpClient client = xHttpClientCreate(loop, NULL);
xHttpClientGet(client, "https://httpbin.org/get", on_response, NULL);
xEventLoopRun(loop);
xHttpClientDestroy(client);
xEventLoopDestroy(loop);
return 0;
}
Relationship with Other Modules
- xbase — Uses
xEventLoopfor I/O multiplexing andxEventLoopTimerAfterfor curl timeout management. - xbuf — Uses
xBufferfor response header and body accumulation. - libcurl — External dependency (client). Uses the multi-socket API (
curl_multi_socket_action) for non-blocking HTTP. - llhttp — External dependency (server). Provides incremental HTTP/1.1 request parsing, isolated behind the
xHttpProtovtable inproto_h1.c. - nghttp2 — External dependency (server). Provides HTTP/2 frame processing and HPACK header compression, isolated behind the
xHttpProtovtable inproto_h2.c.