Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_http_req.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27
28#include "nilorea/n_http_req.h"
29#include "nilorea/n_log.h"
30
31#include <string.h>
32
33static int failures = 0;
34
35/* Parse a NUL-terminated request literal (its byte length is the wire length). */
36static n_http_req_status parse(const char* s, n_http_request* out) {
37 return n_http_request_parse(s, strlen(s), out);
38}
39
40#define WANT(expr, want, msg) \
41 do { \
42 if ((expr) != (want)) { \
43 n_log(LOG_ERR, "FAIL: %s", (msg)); \
44 failures++; \
45 } \
46 } while (0)
47
48int main(void) {
51
52 /* a valid GET */
53 WANT(parse("GET /v1/me?x=1 HTTP/1.1\r\nHost: e\r\n\r\n", &r), N_HTTP_REQ_OK,
54 "valid GET should parse");
55 WANT(r.method, N_HTTP_REQ_GET, "method GET");
56 if (strcmp(r.path, "/v1/me?x=1") != 0) {
57 n_log(LOG_ERR, "FAIL: GET path");
58 failures++;
59 }
60
61 /* a valid POST with a body + an Authorization header */
62 WANT(parse("POST /v1/send HTTP/1.1\r\nContent-Length: 5\r\n"
63 "Authorization: Bearer tok\r\n\r\nhello",
64 &r),
65 N_HTTP_REQ_OK, "valid POST should parse");
66 WANT(r.method, N_HTTP_REQ_POST, "method POST");
67 if (r.content_length != 5) {
68 n_log(LOG_ERR, "FAIL: content_length");
69 failures++;
70 }
71 if (strcmp(r.authorization, "Bearer tok") != 0) {
72 n_log(LOG_ERR, "FAIL: authorization capture");
73 failures++;
74 }
75
76 /* rejections */
77 WANT(parse("PUT / HTTP/1.1\r\n\r\n", &r), N_HTTP_REQ_ERROR,
78 "unsupported method rejected");
79 WANT(parse("GET http://e/x HTTP/1.1\r\n\r\n", &r), N_HTTP_REQ_ERROR,
80 "non-origin-form target rejected");
81 WANT(parse("GET /a#frag HTTP/1.1\r\n\r\n", &r), N_HTTP_REQ_ERROR,
82 "fragment in target rejected");
83 WANT(parse("GET / HTTP/2.0\r\n\r\n", &r), N_HTTP_REQ_ERROR,
84 "unsupported version rejected");
85 WANT(parse("POST / HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n", &r),
86 N_HTTP_REQ_ERROR, "Transfer-Encoding rejected (smuggling)");
87 WANT(parse("POST / HTTP/1.1\r\nContent-Length: 1\r\nContent-Length: 2\r\n"
88 "\r\n",
89 &r),
90 N_HTTP_REQ_ERROR, "duplicate Content-Length rejected (smuggling)");
91 WANT(parse("POST / HTTP/1.1\r\nContent-Length: abc\r\n\r\n", &r),
92 N_HTTP_REQ_ERROR, "non-numeric Content-Length rejected");
93
94 /* incomplete: no CRLFCRLF yet, still under the cap -> read more */
95 WANT(parse("GET / HTTP/1.1\r\nHost: e", &r), N_HTTP_REQ_INCOMPLETE,
96 "partial head is INCOMPLETE");
97 /* shorter than the CRLFCRLF terminator: still just "read more" */
99 "empty buffer is INCOMPLETE");
101 "buffer shorter than CRLFCRLF is INCOMPLETE");
102
103 /* NULL args */
104 WANT(n_http_request_parse(NULL, 0, &r), N_HTTP_REQ_ERROR, "NULL buf");
105
106 if (failures) {
107 n_log(LOG_ERR, "ex_http_req: %d failure(s)", failures);
108 return 1;
109 }
110 n_log(LOG_NOTICE, "ex_http_req: all checks passed");
111 return 0;
112}
static int failures
Definition ex_atlas.c:51
int main(void)
Definition ex_atlas.c:117
static n_http_req_status parse(const char *s, n_http_request *out)
Definition ex_http_req.c:36
#define WANT(expr, want, msg)
Definition ex_http_req.c:40
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:104
n_http_req_status n_http_request_parse(const char *buf, size_t len, n_http_request *out)
parse an HTTP/1.1 request head from [buf, buf+len)
Definition n_http_req.c:83
Pure, strict, bounded parser for an HTTP/1.1 request head.
n_http_req_status
Result of n_http_request_parse.
Definition n_http_req.h:78
@ N_HTTP_REQ_INCOMPLETE
no CRLFCRLF yet, still under the cap
Definition n_http_req.h:80
@ N_HTTP_REQ_ERROR
malformed / oversized / unsupported
Definition n_http_req.h:81
@ N_HTTP_REQ_OK
a complete, valid head was parsed
Definition n_http_req.h:79
char authorization[256u+1]
Definition n_http_req.h:73
char path[2048u+1]
Definition n_http_req.h:70
long long content_length
Definition n_http_req.h:71
n_http_req_method method
Definition n_http_req.h:69
@ N_HTTP_REQ_POST
Definition n_http_req.h:59
@ N_HTTP_REQ_GET
Definition n_http_req.h:58
A parsed request head.
Definition n_http_req.h:68
Generic log system.