1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "httpparser.h"
30
31 #include "../daemon/httpparser.h"
32
33 #include <cx/string.h>
34
35 CX_TEST(test_parse_request_line) {
36 CX_TEST_DO {
37 HttpParser parser;
38 memset(&parser,
0,
sizeof(HttpParser));
39 parser.start_line = cx_mutstr(
"GET / HTTP/1.1\r\n");
40
41 int ret1 = parse_request_line(&parser);
42 CX_TEST_ASSERT(!ret1);
43 CX_TEST_ASSERT(!cx_strcmp(parser.method,
"GET"));
44 CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/"));
45 CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.1"));
46
47 memset(&parser,
0,
sizeof(HttpParser));
48 parser.start_line = cx_mutstr(
"POST /longer/url/test/path/ HTTP/1.0\r\n");
49 int ret2 = parse_request_line(&parser);
50 CX_TEST_ASSERT(!ret2);
51 CX_TEST_ASSERT(!cx_strcmp(parser.method,
"POST"));
52 CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/longer/url/test/path/"));
53 CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.0"));
54
55 memset(&parser,
0,
sizeof(HttpParser));
56 parser.start_line = cx_mutstr(
"G / v\r\n");
57 int ret3 = parse_request_line(&parser);
58 CX_TEST_ASSERT(!ret3);
59 CX_TEST_ASSERT(!cx_strcmp(parser.method,
"G"));
60 CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/"));
61 CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"v"));
62
63 memset(&parser,
0,
sizeof(HttpParser));
64 parser.start_line = cx_mutstr(
"HEAD /space HTTP/0.9 \r\n");
65 int ret4 = parse_request_line(&parser);
66 CX_TEST_ASSERT(!ret4);
67 CX_TEST_ASSERT(!cx_strcmp(parser.method,
"HEAD"));
68 CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/space"));
69 CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/0.9"));
70
71
72 memset(&parser,
0,
sizeof(HttpParser));
73 parser.start_line = cx_mutstr(
"PROPFIND /collection/ HTTP/1.1\n");
74 int uret1 = parse_request_line(&parser);
75 CX_TEST_ASSERT(!uret1);
76 CX_TEST_ASSERT(!cx_strcmp(parser.method,
"PROPFIND"));
77 CX_TEST_ASSERT(!cx_strcmp(parser.uri,
"/collection/"));
78 CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.1"));
79
80
81 parser.start_line = cx_mutstr(
"\r\n");
82 int nret1 = parse_request_line(&parser);
83 CX_TEST_ASSERT(nret1);
84
85 parser.start_line = cx_mutstr(
"GET\r\n");
86 int nret2 = parse_request_line(&parser);
87 CX_TEST_ASSERT(nret2);
88
89 parser.start_line = cx_mutstr(
"GET /test\r\n");
90 int nret3 = parse_request_line(&parser);
91 CX_TEST_ASSERT(nret3);
92
93 parser.start_line = cx_mutstr(
"GET /test \r\n");
94 int nret4 = parse_request_line(&parser);
95 CX_TEST_ASSERT(nret4);
96
97 parser.start_line = cx_mutstr(
"/test HTTP/1.1\r\n");
98 int nret5 = parse_request_line(&parser);
99 CX_TEST_ASSERT(nret5);
100
101 parser.start_line = cx_mutstr(
"GET /uri HTTP/1.1 test\r\n");
102 int nret6 = parse_request_line(&parser);
103 CX_TEST_ASSERT(nret6);
104
105 parser.start_line = cx_mutstr(
" /uri2 HTTP/1.1\r\n");
106 int nret7 = parse_request_line(&parser);
107 CX_TEST_ASSERT(nret7);
108
109 parser.start_line = cx_mutstr(
"GET HTTP/1.1\r\n");
110 int nret8 = parse_request_line(&parser);
111 CX_TEST_ASSERT(nret8);
112 }
113 }
114
115 CX_TEST(test_parse_response_line) {
116 CX_TEST_DO {
117 HttpParser parser;
118 memset(&parser,
0,
sizeof(HttpParser));
119 parser.start_line = cx_mutstr(
"HTTP/1.1 200 OK\r\n");
120 parser.type =
1;
121
122 int ret1 = parse_response_line(&parser);
123 CX_TEST_ASSERT(!ret1);
124 CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.1"));
125 CX_TEST_ASSERT(!cx_strcmp(parser.msg,
"OK"));
126 CX_TEST_ASSERT(parser.status ==
200);
127
128 memset(&parser,
0,
sizeof(HttpParser));
129 parser.start_line = cx_mutstr(
"HTTP/1.0 201 Created\r\n");
130 parser.type =
1;
131 int ret2 = parse_response_line(&parser);
132 CX_TEST_ASSERT(!ret2);
133 CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/1.0"));
134 CX_TEST_ASSERT(!cx_strcmp(parser.msg,
"Created"));
135 CX_TEST_ASSERT(parser.status ==
201);
136
137 memset(&parser,
0,
sizeof(HttpParser));
138 parser.start_line = cx_mutstr(
"HTTP/0.9 204 No Content\r\n");
139 parser.type =
1;
140 int ret3 = parse_response_line(&parser);
141 CX_TEST_ASSERT(!ret3);
142 CX_TEST_ASSERT(!cx_strcmp(parser.httpv,
"HTTP/0.9"));
143 CX_TEST_ASSERT(!cx_strcmp(parser.msg,
"No Content"));
144 CX_TEST_ASSERT(parser.status ==
204);
145
146
147 memset(&parser,
0,
sizeof(HttpParser));
148 parser.start_line = cx_mutstr(
"HTTP/1.1 200\r\n");
149 parser.type =
1;
150 int nret1 = parse_response_line(&parser);
151 CX_TEST_ASSERT(nret1);
152
153 memset(&parser,
0,
sizeof(HttpParser));
154 parser.start_line = cx_mutstr(
"\r\n");
155 parser.type =
1;
156 int nret2 = parse_response_line(&parser);
157 CX_TEST_ASSERT(nret2);
158
159 memset(&parser,
0,
sizeof(HttpParser));
160 parser.start_line = cx_mutstr(
"200\r\n");
161 parser.type =
1;
162 int nret3 = parse_response_line(&parser);
163 CX_TEST_ASSERT(nret3);
164
165 memset(&parser,
0,
sizeof(HttpParser));
166 parser.start_line = cx_mutstr(
"HTTP/1.1 2345 Test Message\r\n");
167 parser.type =
1;
168 int nret4 = parse_response_line(&parser);
169 CX_TEST_ASSERT(nret4);
170
171 memset(&parser,
0,
sizeof(HttpParser));
172 parser.start_line = cx_mutstr(
"HTTP/1.1 xy1 OK\r\n");
173 parser.type =
1;
174 int nret5 = parse_response_line(&parser);
175 CX_TEST_ASSERT(nret5);
176
177 memset(&parser,
0,
sizeof(HttpParser));
178 parser.start_line = cx_mutstr(
" 200 OK\r\n");
179 parser.type =
1;
180 int nret6 = parse_response_line(&parser);
181 CX_TEST_ASSERT(nret6);
182 }
183 }
184
185 CX_TEST_SUBROUTINE(test_http_parser_process, cxstring request,
int chunksize) {
186 netbuf buf;
187 memset(&buf,
0,
sizeof(netbuf));
188 buf.inbuf = (
unsigned char*)request.ptr;
189 buf.maxsize = request.length;
190 HeaderArray *header = header_array_create();
191 HttpParser *parser = http_parser_new2(
0, &buf, header);
192
193 while(buf.cursize < request.length) {
194 buf.cursize += chunksize;
195 if(buf.cursize > buf.maxsize) {
196 buf.cursize = buf.maxsize;
197 }
198
199 int ret = http_parser_process(parser);
200 if(buf.cursize < buf.maxsize) {
201 CX_TEST_ASSERT(ret ==
1);
202 }
else {
203 CX_TEST_ASSERT(ret ==
0);
204 }
205 }
206 CX_TEST_ASSERT(http_parser_validate(parser));
207
208 http_parser_free(parser);
209 header_array_free(header);
210 }
211
212 #define _CX_STR(s) { s,
sizeof(s)
-1 }
213
214 static cxstring req0 =
_CX_STR(
215 "GET / HTTP/1.1\r\n"
216 "Host: example.com\r\n"
217 "\r\n");
218
219 static cxstring req1 =
_CX_STR(
"GET /api/data?id=42 HTTP/1.1\r\n"
220 "Host: api.example.com\r\n"
221 "User-Agent: TestClient/1.0\r\n"
222 "Accept: application/json\r\n"
223 "Accept-Language: en-US,en;q=0.9\r\n"
224 "Connection: keep-alive\r\n"
225 "Cache-Control: no-cache\r\n"
226 "\r\n");
227
228 static cxstring req2 =
_CX_STR(
"GET /search?q=network+testing HTTP/1.1\r\n"
229 "Host: www.example.com\r\n"
230 "User-Agent: Mozilla/5.0 (X11; Linux x86_64) TestBrowser/99.0\r\n"
231 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"
232 "Accept-Language: en-US,en;q=0.9,de;q=0.8\r\n"
233 "Accept-Encoding: gzip, deflate, br\r\n"
234 "Connection: keep-alive\r\n"
235 "Cache-Control: max-age=0\r\n"
236 "Upgrade-Insecure-Requests: 1\r\n"
237 "Pragma: no-cache\r\n"
238 "DNT: 1\r\n"
239 "Sec-Fetch-Dest: document\r\n"
240 "Sec-Fetch-Mode: navigate\r\n"
241 "Sec-Fetch-Site: none\r\n"
242 "Sec-Fetch-User: ?1\r\n"
243 "Referer: https://www.example.com/\r\n"
244 "X-Forwarded-For: 203.0.113.195\r\n"
245 "X-Request-ID: 123e4567-e89b-12d3-a456-426614174000\r\n"
246 "\r\n");
247
248 CX_TEST(test_http_parser_process_full) {
249 CX_TEST_DO {
250 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0, req0.length);
251 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1, req1.length);
252 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2, req2.length);
253 }
254 }
255
256 CX_TEST(test_http_parser_process_chunk_1b) {
257 CX_TEST_DO {
258 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0,
1);
259 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1,
1);
260 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2,
1);
261 }
262 }
263
264 CX_TEST(test_http_parser_process_chunk_2b) {
265 CX_TEST_DO {
266 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0,
2);
267 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1,
2);
268 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2,
2);
269 }
270 }
271
272 CX_TEST(test_http_parser_process_chunk_3b) {
273 CX_TEST_DO {
274 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0,
3);
275 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1,
3);
276 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2,
3);
277 }
278 }
279
280 CX_TEST(test_http_parser_process_chunk_4b) {
281 CX_TEST_DO {
282 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req0,
4);
283 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req1,
4);
284 CX_TEST_CALL_SUBROUTINE(test_http_parser_process, req2,
4);
285 }
286 }
287