Networking in C · intermediate · ~20 min
Read and parse HTTP/1.1 request/response frames.
HTTP/1.1 frames are ASCII lines separated by \r\n, followed by an empty line, then a body. Parsing the request line and the headers correctly is the foundation of every HTTP server, proxy, and security gateway.
Every web server you'll ever read source for has a hand-rolled HTTP parser. Bugs in those parsers have wrecked production systems (Apache Range, nginx alias, h2c smuggling).
Request line. METHOD SP TARGET SP HTTP/1.x CRLF. Method is one of GET/HEAD/POST/PUT/DELETE/OPTIONS/PATCH (strictly uppercase per RFC).
Headers. Name: Value CRLF, repeating. Names are case-insensitive; values can contain almost anything.
Body. Either Content-Length bytes, or Transfer-Encoding: chunked framing. Never both. If both arrive together you have a request-smuggling vector — refuse.
Pentester mindset. Parser divergence between front-end and back-end is the smuggling primitive (front-end honours CL, back-end honours TE — or vice versa). Defensive servers should refuse ambiguous frames.
Defensive coding habit. Allow-list methods; cap header length; require CRLF (not LF alone). When in doubt about a frame, return 400 and close the connection.
Lines split on \r\n exactly. Empty line (just \r\n) terminates the header block.
HTTP/1.1 is ASCII over TCP. A request is a method + path + version line, followed by header lines, an empty line, then optional body. Responses look the same with a status code instead of a method.
GET /path HTTP/1.1\r\n
Host: example.com\r\n
\r\n
/* Parse the request line: METHOD SP TARGET SP HTTP/1.x */
const char *sp1 = strchr(line, ' ');
const char *sp2 = strchr(sp1 + 1, ' ');
if (!sp1 || !sp2 || strncmp(sp2+1, "HTTP/", 5)) return -1;
/* method = [line, sp1) path = (sp1, sp2) version = sp2+1 .. CR */
\n alone as a line terminator (must be \r\n).curl -v shows the full request and response with each header line. nc -l 8080 lets you see what a client sends.
Every header line must have a length cap. Most real attacks against HTTP parsers start with a 64KB+ pathological header.
Every web server, every load balancer, every WAF, every CDN edge node.
HTTP/1.1 = ASCII lines terminated by CRLF, header block ends with an empty line. Cap lengths, allow-list methods, refuse ambiguous framing.