Networking in C · intermediate · ~20 min
Read and parse HTTP/1.1 request and response frames.
HTTP/1.1 messages are made of ASCII text lines. Each line ends with \r\n (carriage return + line feed). An empty line marks the end of the headers, and the body follows after it.
Parsing the request line and the headers correctly is the foundation of every HTTP server, proxy, and security gateway.
Almost every web server you will read source for contains a hand-written HTTP parser.
Bugs in those parsers have caused serious failures in production systems. Well-known examples include the Apache Range flaw, the nginx alias flaw, and h2c request smuggling.
Format: METHOD SP TARGET SP HTTP/1.x CRLF (where SP is a single space).
The method is one of GET, HEAD, POST, PUT, DELETE, OPTIONS, or PATCH. Per the RFC, methods must be strictly uppercase.
Each header is Name: Value CRLF, and headers repeat line after line.
The body is framed in one of two ways:
Content-Length gives the body size in bytes, orTransfer-Encoding: chunked splits the body into chunks.Never accept both at once. If both arrive together, you have a request-smuggling vector. Refuse the request.
Request smuggling exploits parser divergence between two servers. For example, the front-end honours Content-Length while the back-end honours Transfer-Encoding (or the reverse). The two servers then disagree on where one request ends and the next begins.
A defensive server should refuse any ambiguous frame.
CRLF, not a bare LF.400 and close the connection.Split lines on \r\n exactly. An empty line (just \r\n on its own) ends the header block.
HTTP/1.1 is ASCII text carried over TCP.
A request has three parts:
Responses have the same shape, except the first line carries 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 as a line terminator. The terminator must be \r\n.Content-Length and Transfer-Encoding at the same time. This enables request smuggling.curl -v prints the full request and response, including every header line.nc -l 8080 listens on a port so you can see exactly what a client sends.Cap the length of every header line.
Most real attacks on HTTP parsers begin with a pathological header of 64 KB or more, designed to overflow a buffer or exhaust memory.
Every web server, load balancer, WAF (web application firewall), and CDN edge node.
Content-Length and Transfer-Encoding.CRLF; an empty line ends the header block.Content-Length or chunked Transfer-Encoding, never both.