25static constexpr uint32_t FNV_OFFSET = 2166136261u;
26static constexpr uint32_t FNV_PRIME = 16777619u;
28static constexpr uint32_t fnv1a(
const char *s, uint32_t h = FNV_OFFSET)
30 return *s ? fnv1a(s + 1, (h ^ (uint8_t)*s) * FNV_PRIME) : h;
33static constexpr uint32_t HASH_HTTP10 = fnv1a(
"HTTP/1.0");
34static constexpr uint32_t HASH_HTTP11 = fnv1a(
"HTTP/1.1");
49static inline bool is_tchar(uint8_t b)
51 if (b >=
'A' && b <=
'Z')
53 if (b >=
'a' && b <=
'z')
55 if (b >=
'0' && b <=
'9')
87static inline bool is_vchar(uint8_t b)
89 return b >= 0x21 && b <= 0x7E;
102static inline bool is_field_value_char(uint8_t b)
105 || (b >= 0x20 && b <= 0x7E)
116static void parse_query_params(
HttpReq *req)
118 const char *qs = req->
query;
134 if (c ==
'=' && !in_val)
140 qp->
key[key_idx++] = c;
142 qp->
val[val_idx++] = c;
184 else if (!is_tchar(
byte))
208 else if (!is_vchar(
byte))
226 parse_query_params(p);
229 else if (!is_vchar(
byte))
289 else if (!is_tchar(
byte))
323 if (strcasecmp(p->
headers[h].
key,
"Content-Length") == 0)
330 else if (!is_field_value_char(
byte))
393 if (strcasecmp(req->
headers[i].
key, key) == 0)
#define MAX_VAL_LEN
Maximum header field-value length.
#define MAX_QUERY_PARAMS
Maximum number of parsed query-string parameters.
#define MAX_QUERY_LEN
Maximum raw query-string length (everything after ?).
#define QUERY_VAL_LEN
Maximum query-parameter value length.
#define BODY_BUF_SIZE
Maximum request body bytes stored in HttpReq::body.
#define MAX_HEADERS
Maximum HTTP headers stored per request.
#define MAX_PATH_LEN
Maximum URL path length (including leading /).
#define MAX_CONNS
Maximum simultaneous TCP connections.
#define QUERY_KEY_LEN
Maximum query-parameter key length.
#define MAX_KEY_LEN
Maximum header field-name length (e.g. "Content-Type").
void http_parser_reset(HttpReq *req)
Reset a parser context to the initial (PARSE_METHOD) state.
const char * http_get_header(const HttpReq *req, const char *key)
Look up a header value by name (case-insensitive).
void http_parser_feed(HttpReq *p, uint8_t byte)
Feed one byte to the parser state machine.
const char * http_get_query(const HttpReq *req, const char *key)
Look up a query parameter value by name (case-sensitive).
HttpReq http_pool[MAX_CONNS]
Pool of parser contexts, one per transport slot.
Standalone HTTP/1.1 request parser — no transport dependency.
@ PARSE_BODY
Reading the request body.
@ PARSE_HEADER_VAL
Reading a header field value.
@ PARSE_QUERY
Reading the raw query string (after ?).
@ PARSE_COMPLETE
Full request parsed; ready for dispatch.
@ PARSE_HEADER_KEY
Reading a header field name.
@ PARSE_EXPECT_BODY_LF
Consuming the LF of the blank-line CRLF.
@ PARSE_VERSION
Accumulating HTTP/1.x — hashed for validation.
@ PARSE_URI_TOO_LONG
Path exceeds MAX_PATH_LEN → 414.
@ PARSE_EXPECT_LF
Consuming the LF of a header-line CRLF pair.
@ PARSE_ENTITY_TOO_LARGE
Content-Length > BODY_BUF_SIZE → 413.
@ PARSE_PATH
Reading the URL path component.
@ PARSE_ERROR
Unrecoverable parse failure → 400.
@ PARSE_METHOD
Reading the HTTP method (GET, POST, …).
@ HTTP_UNKNOWN
Version string did not match any known token.
@ HTTP_11
HTTP/1.1 — persistent connection by default.
@ HTTP_10
HTTP/1.0 — close semantics by default.
Fully-parsed HTTP/1.1 request.
QueryParam query_params[MAX_QUERY_PARAMS]
Parsed key=value pairs.
Header headers[MAX_HEADERS]
Captured header fields.
char query[MAX_QUERY_LEN]
Raw query string (after ?).
uint32_t _version_hash
FNV-1a accumulator for version validation (internal).
uint8_t body[BODY_BUF_SIZE+1]
Stored body bytes, always null-terminated.
uint8_t header_count
Valid entries in headers[].
size_t current_token_idx
Write cursor shared by key/value sub-states.
ParseState parse_state
Current parser state.
size_t path_idx
Write cursor into path[].
size_t content_length
Value of Content-Length header (0 if absent).
uint8_t slot_id
Transport slot index (set by presentation layer).
size_t body_len
Bytes stored in body[] (≤ BODY_BUF_SIZE).
HttpVersion version
Protocol version parsed from the request line.
char method[8]
HTTP method, null-terminated (max 7: OPTIONS).
char path[MAX_PATH_LEN]
URL path, null-terminated; no query string.
uint8_t query_count
Valid entries in query_params[].
size_t body_bytes_read
Body bytes received (may exceed BODY_BUF_SIZE).
size_t query_idx
Write cursor into query[].
A single parsed query-string parameter.
char val[QUERY_VAL_LEN]
Parameter value (empty string if absent).
char key[QUERY_KEY_LEN]
Parameter name, null-terminated.