http.c
http.c - HTTP Protocol Parser and Builder
http.c is an HTTP protocol parser and builder library and CLI. It reads HTTP wire bytes from stdin, emits normalized message metadata plus the raw logical body, and builds HTTP wire messages from raw payload bytes and metadata.
It composes with stream tools such as netl and nets:
netl 127.0.0.1:8080 'http parse | app'
app | http build response --status 200 | nets 127.0.0.1:8080
CLI
Examples
Parse one HTTP request from stdin:
printf 'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n' | http parse
Parse all messages from a keep-alive stream:
cat stream.bin | http parse --all
Build a POST request:
printf 'hello' | http build request \
--method POST \
--target /api \
--header 'host: localhost' \
--header 'content-type: text/plain'
Build a 200 response:
cat index.html | http build response \
--status 200 \
--header 'content-type: text/html'
Build a chunked response:
cat large.bin | http build response \
--status 200 \
--header 'content-type: application/octet-stream' \
--chunked
Commands
| Command | Description |
|---|---|
parse | Parse one HTTP message from stdin and emit normalized output. |
parse --all | Parse all HTTP messages from stdin until EOF. |
build request | Build an HTTP request from stdin body. |
build response | Build an HTTP response from stdin body. |
Parse options
| Option | Description |
|---|---|
--all | Parse all messages until EOF, separated by ---. |
Build request options
| Option | Description |
|---|---|
--method <method> | HTTP method. Default: GET. |
--target <target> | Request target. Default: /. |
--version <version> | HTTP version. Default: 1.1. |
--header <name: value> | Add a request header. Repeatable. |
--chunked | Use Transfer-Encoding: chunked. |
--chunk-size <n> | Chunk size in bytes. Default: 8192. |
Build response options
| Option | Description |
|---|---|
--status <code> | HTTP status code. Default: 200. |
--reason <phrase> | Reason phrase. Default: derived from status. |
--version <version> | HTTP version. Default: 1.1. |
--header <name: value> | Add a response header. Repeatable. |
--chunked | Use Transfer-Encoding: chunked. |
--chunk-size <n> | Chunk size in bytes. Default: 8192. |
--trailer <name: value> | Add a trailer (chunked only). Repeatable. |
Common options
| Option | Description |
|---|---|
-h, --help | Show help and exit. |
-v, --version | Show version and exit. |
Parse output format
http parse writes metadata lines, one empty line, then raw body bytes:
http.type=request
http.version=1.1
request.method=POST
request.target=/api?a=1
request.path=/api
request.query=a=1
header.host=localhost
header.content-type=text/plain
body.length=4
hello
Response output:
http.type=response
http.version=1.1
response.status=200
response.reason=OK
header.content-type=text/plain
body.length=4
hello
- Header names are lowercased.
- Repeated headers are emitted as separate lines in order.
- Chunked bodies are automatically dechunked; only logical payload bytes appear.
- Trailers are emitted as
trailer.<name>=<value>lines beforebody.length. body.lengthalways reflects the logical byte count, not the wire byte count.
For --all, messages are separated by \n---\n on its own line. The consumer uses body.length to determine the exact end of each body.
Public API
#include "http.h"
kc_http_t *ctx = kc_http_open();
kc_http_set_op(ctx, KC_HTTP_OP_PARSE);
kc_http_exec(ctx);
kc_http_close(ctx);
Build a response programmatically:
kc_http_t *ctx = kc_http_open();
kc_http_set_op(ctx, KC_HTTP_OP_BUILD_RESPONSE);
kc_http_set_status(ctx, 200);
kc_http_add_header(ctx, "content-type: text/plain");
kc_http_exec(ctx);
kc_http_close(ctx);
Lifecycle
kc_http_open()allocates a context with default settings.kc_http_set_*/kc_http_add_*configure the operation.kc_http_exec()reads fromstdinand writes tostdout.kc_http_close()frees all owned memory.
http.c owns HTTP framing completely. Callers provide raw payload bytes and receive logical payload bytes. Wire framing details (chunk syntax, Content-Length, CRLF) are never exposed to the caller.
Protocol support
| Version | Status |
|---|---|
| HTTP/0.9 | Parsed (simple request, no headers, no body) |
| HTTP/1.0 | Full parse and build |
| HTTP/1.1 | Full parse and build, chunked, trailers |
| HTTP/2 | Binary frame parse/build for HEADERS and DATA |
| HTTP/3 | Frame parse/build for HEADERS and DATA |
Source Layout
| File | Role |
|---|---|
src/http.c | CLI argument parsing only |
src/libhttp.c | Shared context, helpers, and protocol dispatch |
src/http1.c | HTTP/0.9, HTTP/1.0, and HTTP/1.1 parser/builder |
src/http2.c | HTTP/2 frame and HPACK parser/builder |
src/http3.c | HTTP/3 frame and QPACK parser/builder |
Build
make
Artifacts:
bin/{arch}/{platform}/http
bin/{arch}/{platform}/libhttp.a
bin/{arch}/{platform}/libhttp.so
Windows:
bin/{arch}/windows/http.exe
bin/{arch}/windows/libhttp.dll
bin/{arch}/windows/libhttp.dll.a
Multiarch Builds
make all
Targets: x86_64/linux, x86_64/windows, i686/linux, i686/windows, aarch64/linux, aarch64/android, armv7/linux, armv7/android, armv7hf/linux, riscv64/linux, powerpc64le/linux, mips/linux, mipsel/linux, mips64el/linux, s390x/linux, loongarch64/linux.
License
This project is distributed under the GNU General Public License version 3 (GPLv3).
Repo
GitHub: kaisarcode/http.c
