Networking in C · intermediate · ~20 min

HTTP/1.1 protocol structure

Read and parse HTTP/1.1 request/response frames.

Overview

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.

Why it matters

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).

Core concepts

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.

Syntax notes

Lines split on \r\n exactly. Empty line (just \r\n) terminates the header block.

Lesson

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.

Code examples

GET /path HTTP/1.1\r\n
Host: example.com\r\n
\r\n

Line by line

/* 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 */

Common mistakes

  • Treating \n alone as a line terminator (must be \r\n).
  • Trusting Content-Length AND Transfer-Encoding both (smuggling).

Debugging tips

curl -v shows the full request and response with each header line. nc -l 8080 lets you see what a client sends.

Memory safety

Every header line must have a length cap. Most real attacks against HTTP parsers start with a 64KB+ pathological header.

Real-world uses

Every web server, every load balancer, every WAF, every CDN edge node.

Practice tasks

  1. Parse a request line. 2. Build an HTTP GET request as a string. 3. Refuse a request that has both Content-Length and Transfer-Encoding.

Summary

HTTP/1.1 = ASCII lines terminated by CRLF, header block ends with an empty line. Cap lengths, allow-list methods, refuse ambiguous framing.

Practice with these exercises