iodine 0.2.17 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +36 -3
- data/bin/config.ru +23 -2
- data/bin/http-hello +1 -1
- data/bin/ws-shootout +5 -0
- data/ext/iodine/defer.c +468 -0
- data/ext/iodine/defer.h +105 -0
- data/ext/iodine/evio.c +263 -0
- data/ext/iodine/evio.h +133 -0
- data/ext/iodine/extconf.rb +2 -1
- data/ext/iodine/facil.c +958 -0
- data/ext/iodine/facil.h +423 -0
- data/ext/iodine/http.c +90 -0
- data/ext/iodine/http.h +50 -12
- data/ext/iodine/http1.c +200 -267
- data/ext/iodine/http1.h +17 -26
- data/ext/iodine/http1_request.c +81 -0
- data/ext/iodine/http1_request.h +58 -0
- data/ext/iodine/http1_response.c +403 -0
- data/ext/iodine/http1_response.h +90 -0
- data/ext/iodine/http1_simple_parser.c +124 -108
- data/ext/iodine/http1_simple_parser.h +8 -3
- data/ext/iodine/http_request.c +104 -0
- data/ext/iodine/http_request.h +58 -102
- data/ext/iodine/http_response.c +212 -208
- data/ext/iodine/http_response.h +89 -252
- data/ext/iodine/iodine_core.c +57 -46
- data/ext/iodine/iodine_core.h +3 -1
- data/ext/iodine/iodine_http.c +105 -81
- data/ext/iodine/iodine_websocket.c +17 -13
- data/ext/iodine/iodine_websocket.h +1 -0
- data/ext/iodine/rb-call.c +9 -7
- data/ext/iodine/{rb-libasync.h → rb-defer.c} +57 -49
- data/ext/iodine/rb-rack-io.c +12 -6
- data/ext/iodine/rb-rack-io.h +1 -1
- data/ext/iodine/rb-registry.c +5 -2
- data/ext/iodine/sock.c +1159 -0
- data/ext/iodine/{libsock.h → sock.h} +138 -142
- data/ext/iodine/spnlock.inc +77 -0
- data/ext/iodine/websockets.c +101 -112
- data/ext/iodine/websockets.h +38 -19
- data/iodine.gemspec +3 -3
- data/lib/iodine/version.rb +1 -1
- data/lib/rack/handler/iodine.rb +6 -6
- metadata +23 -19
- data/ext/iodine/http_response_http1.h +0 -382
- data/ext/iodine/libasync.c +0 -570
- data/ext/iodine/libasync.h +0 -122
- data/ext/iodine/libreact.c +0 -350
- data/ext/iodine/libreact.h +0 -244
- data/ext/iodine/libserver.c +0 -957
- data/ext/iodine/libserver.h +0 -481
- data/ext/iodine/libsock.c +0 -1025
- data/ext/iodine/spnlock.h +0 -243
@@ -0,0 +1,90 @@
|
|
1
|
+
#ifndef H_HTTP1_RESPONSE_H
|
2
|
+
#define H_HTTP1_RESPONSE_H
|
3
|
+
|
4
|
+
#include "http1.h"
|
5
|
+
|
6
|
+
/* *****************************************************************************
|
7
|
+
Initialization
|
8
|
+
***************************************************************************** */
|
9
|
+
|
10
|
+
/** Creates / allocates a protocol version's response object. */
|
11
|
+
http_response_s *http1_response_create(http_request_s *request);
|
12
|
+
/** Destroys the response object. No data is sent.*/
|
13
|
+
void http1_response_destroy(http_response_s *);
|
14
|
+
/** Sends the data and destroys the response object.*/
|
15
|
+
void http1_response_finish(http_response_s *);
|
16
|
+
|
17
|
+
/* *****************************************************************************
|
18
|
+
Writing data to the response object
|
19
|
+
***************************************************************************** */
|
20
|
+
|
21
|
+
/**
|
22
|
+
Writes a header to the response. This function writes only the requested
|
23
|
+
number of bytes from the header name and the requested number of bytes from
|
24
|
+
the header value. It can be used even when the header name and value don't
|
25
|
+
contain NULL terminating bytes by passing the `.name_len` or `.value_len` data
|
26
|
+
in the `http_headers_s` structure.
|
27
|
+
|
28
|
+
If the header buffer is full or the headers were already sent (new headers
|
29
|
+
cannot be sent), the function will return -1.
|
30
|
+
|
31
|
+
On success, the function returns 0.
|
32
|
+
*/
|
33
|
+
int http1_response_write_header_fn(http_response_s *, http_header_s header);
|
34
|
+
|
35
|
+
/**
|
36
|
+
Set / Delete a cookie using this helper function.
|
37
|
+
|
38
|
+
To set a cookie, use (in this example, a session cookie):
|
39
|
+
|
40
|
+
http_response_set_cookie(response,
|
41
|
+
.name = "my_cookie",
|
42
|
+
.value = "data");
|
43
|
+
|
44
|
+
To delete a cookie, use:
|
45
|
+
|
46
|
+
http_response_set_cookie(response,
|
47
|
+
.name = "my_cookie",
|
48
|
+
.value = NULL);
|
49
|
+
|
50
|
+
This function writes a cookie header to the response. Only the requested
|
51
|
+
number of bytes from the cookie value and name are written (if none are
|
52
|
+
provided, a terminating NULL byte is assumed).
|
53
|
+
|
54
|
+
Both the name and the value of the cookie are checked for validity (legal
|
55
|
+
characters), but other properties aren't reviewed (domain/path) - please make
|
56
|
+
sure to use only valid data, as HTTP imposes restrictions on these things.
|
57
|
+
|
58
|
+
If the header buffer is full or the headers were already sent (new headers
|
59
|
+
cannot be sent), the function will return -1.
|
60
|
+
|
61
|
+
On success, the function returns 0.
|
62
|
+
*/
|
63
|
+
int http1_response_set_cookie(http_response_s *, http_cookie_s);
|
64
|
+
|
65
|
+
/**
|
66
|
+
Sends the headers (if they weren't previously sent) and writes the data to the
|
67
|
+
underlying socket.
|
68
|
+
|
69
|
+
The body will be copied to the server's outgoing buffer.
|
70
|
+
|
71
|
+
If the connection was already closed, the function will return -1. On success,
|
72
|
+
the function returns 0.
|
73
|
+
*/
|
74
|
+
int http1_response_write_body(http_response_s *, const char *body,
|
75
|
+
size_t length);
|
76
|
+
|
77
|
+
/**
|
78
|
+
Sends the headers (if they weren't previously sent) and writes the data to the
|
79
|
+
underlying socket.
|
80
|
+
|
81
|
+
The server's outgoing buffer will take ownership of the file and close it
|
82
|
+
using `close` once the data was sent.
|
83
|
+
|
84
|
+
If the connection was already closed, the function will return -1. On success,
|
85
|
+
the function returns 0.
|
86
|
+
*/
|
87
|
+
int http1_response_sendfile(http_response_s *, int source_fd, off_t offset,
|
88
|
+
size_t length);
|
89
|
+
|
90
|
+
#endif
|
@@ -4,7 +4,10 @@ license: MIT
|
|
4
4
|
|
5
5
|
Feel free to copy, use and enjoy according to the license provided.
|
6
6
|
*/
|
7
|
+
#define _GNU_SOURCE
|
7
8
|
#include "http1_simple_parser.h"
|
9
|
+
#include <stdlib.h>
|
10
|
+
#include <string.h>
|
8
11
|
#include <strings.h>
|
9
12
|
|
10
13
|
#ifdef __has_include
|
@@ -24,15 +27,17 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
24
27
|
Useful macros an helpers
|
25
28
|
*/
|
26
29
|
|
30
|
+
/*
|
27
31
|
#define a2i(a) \
|
28
32
|
(((a) >= '0' && a <= '9') ? ((a) - '0') : ({ \
|
29
33
|
return -1; \
|
30
34
|
0; \
|
31
35
|
}))
|
36
|
+
*/
|
32
37
|
|
33
38
|
#define CHECK_END() \
|
34
39
|
{ \
|
35
|
-
request->
|
40
|
+
request->udata = pos; \
|
36
41
|
if (pos >= end) { \
|
37
42
|
return -2; \
|
38
43
|
} \
|
@@ -45,6 +50,12 @@ Useful macros an helpers
|
|
45
50
|
if (*pos == '\n' || *pos == 0) \
|
46
51
|
*(pos++) = 0; \
|
47
52
|
}
|
53
|
+
#undef EAT_EOL
|
54
|
+
#define EAT_EOL() \
|
55
|
+
{ \
|
56
|
+
*(pos++) = 0; \
|
57
|
+
*(pos++) = 0; \
|
58
|
+
}
|
48
59
|
|
49
60
|
static inline char *seek_to_char(char *start, char *end, char tok) {
|
50
61
|
while (start < end) {
|
@@ -84,96 +95,89 @@ static inline char *seek_to_2eol(char *start, char *end) {
|
|
84
95
|
|
85
96
|
/* reviews the latest header and updates any required data in the request
|
86
97
|
* structure. */
|
87
|
-
static inline ssize_t review_header_data(http_request_s *request,
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
if (request->headers[request->headers_count].name_length == 4 &&
|
96
|
-
*((uint32_t *)request->headers[request->headers_count].name) ==
|
97
|
-
*((uint32_t *)HOST)) { // exact match
|
98
|
-
request->host = (void *)tmp;
|
99
|
-
request->host_len = request->headers[request->headers_count].value_length;
|
100
|
-
} else if (request->headers[request->headers_count].name_length == 12 &&
|
101
|
-
*((uint64_t *)(request->headers[request->headers_count].name +
|
102
|
-
3)) ==
|
98
|
+
static inline ssize_t review_header_data(http_request_s *request,
|
99
|
+
http_header_s *header) {
|
100
|
+
if (header->name_len == 4 &&
|
101
|
+
*((uint32_t *)header->name) == *((uint32_t *)HOST)) { // exact match
|
102
|
+
request->host = (void *)header->data;
|
103
|
+
request->host_len = header->data_len;
|
104
|
+
} else if (header->name_len == 12 &&
|
105
|
+
*((uint64_t *)(header->name + 3)) ==
|
103
106
|
*((uint64_t *)(CONTENT_TYPE + 3))) { // almost
|
104
|
-
request->content_type = (void *)
|
105
|
-
request->content_type_len =
|
106
|
-
|
107
|
-
|
108
|
-
*((uint64_t *)(request->headers[request->headers_count].name +
|
109
|
-
3)) ==
|
107
|
+
request->content_type = (void *)header->data;
|
108
|
+
request->content_type_len = header->data_len;
|
109
|
+
} else if (header->name_len == 14 &&
|
110
|
+
*((uint64_t *)(header->name + 3)) ==
|
110
111
|
*((uint64_t *)(CONTENT_LENGTH + 3))) { // close match
|
111
112
|
// tmp still holds a pointer to the value
|
112
113
|
size_t c_len = 0;
|
114
|
+
char *tmp = (char *)header->data;
|
113
115
|
while (*tmp) {
|
114
|
-
|
116
|
+
if ((*tmp) >= '0' && (*tmp) <= '9')
|
117
|
+
c_len = (c_len * 10) + ((*tmp) - '0');
|
118
|
+
else
|
119
|
+
return -1;
|
115
120
|
++tmp;
|
116
121
|
};
|
117
122
|
request->content_length = c_len;
|
118
|
-
} else if (
|
119
|
-
*((uint64_t *)
|
120
|
-
*((uint64_t *)UPGRADE)) { // matches also the
|
121
|
-
request->upgrade = (void *)
|
122
|
-
request->upgrade_len =
|
123
|
-
|
124
|
-
|
125
|
-
*((uint64_t *)request->headers[request->headers_count].name) ==
|
123
|
+
} else if (header->name_len == 7 &&
|
124
|
+
*((uint64_t *)header->name) ==
|
125
|
+
*((uint64_t *)UPGRADE)) { // matches also the NUL character
|
126
|
+
request->upgrade = (void *)header->data;
|
127
|
+
request->upgrade_len = header->data_len;
|
128
|
+
} else if (header->name_len == 10 &&
|
129
|
+
*((uint64_t *)header->name) ==
|
126
130
|
*((uint64_t *)CONNECTION)) { // a close enough match
|
127
|
-
request->connection = (void *)
|
128
|
-
request->connection_len =
|
129
|
-
request->headers[request->headers_count].value_length;
|
131
|
+
request->connection = (void *)header->data;
|
132
|
+
request->connection_len = header->data_len;
|
130
133
|
}
|
131
134
|
return 0;
|
132
135
|
}
|
133
136
|
|
134
137
|
#else
|
135
138
|
/* unknown header case */
|
139
|
+
#define to_lower(c)
|
136
140
|
|
137
141
|
static inline ssize_t review_header_data(http_request_s *request,
|
138
|
-
|
139
|
-
if (
|
140
|
-
strncasecmp(
|
141
|
-
|
142
|
-
request->
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
request->headers[request->headers_count].value_length;
|
150
|
-
} else if (request->headers[request->headers_count].name_length == 14 &&
|
151
|
-
strncasecmp(request->headers[request->headers_count].name,
|
152
|
-
CONTENT_LENGTH, 14) == 0) {
|
142
|
+
http_header_s *header) {
|
143
|
+
if (header->name_len == 4 &&
|
144
|
+
strncasecmp((char *)header->name, HOST, 4) == 0) {
|
145
|
+
request->host = (void *)header->data;
|
146
|
+
request->host_len = header->data_len;
|
147
|
+
} else if (header->name_len == 12 &&
|
148
|
+
strncasecmp((char *)header->name, CONTENT_TYPE, 12) == 0) {
|
149
|
+
request->content_type = (void *)header->data;
|
150
|
+
request->content_type_len = header->data_len;
|
151
|
+
} else if (header->name_len == 14 &&
|
152
|
+
strncasecmp((char *)header->name, CONTENT_LENGTH, 14) == 0) {
|
153
153
|
// tmp still holds a pointer to the value
|
154
154
|
size_t c_len = 0;
|
155
|
+
char *tmp = (char *)header->data;
|
155
156
|
while (*tmp) {
|
156
|
-
|
157
|
+
if ((*tmp) >= '0' && (*tmp) <= '9')
|
158
|
+
c_len = (c_len * 10) + ((*tmp) - '0');
|
159
|
+
else
|
160
|
+
return -1;
|
157
161
|
++tmp;
|
158
162
|
};
|
159
163
|
request->content_length = c_len;
|
160
|
-
} else if (
|
161
|
-
strncasecmp(
|
162
|
-
|
163
|
-
request->
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
CONNECTION, 10) == 0) {
|
169
|
-
request->connection = (void *)tmp;
|
170
|
-
request->connection_len =
|
171
|
-
request->headers[request->headers_count].value_length;
|
164
|
+
} else if (header->name_len == 7 &&
|
165
|
+
strncasecmp((char *)header->name, UPGRADE, 7) == 0) {
|
166
|
+
request->upgrade = (void *)header->data;
|
167
|
+
request->upgrade_len = header->data_len;
|
168
|
+
} else if (header->name_len == 10 &&
|
169
|
+
strncasecmp((char *)header->name, CONNECTION, 10) == 0) {
|
170
|
+
request->connection = (void *)header->data;
|
171
|
+
request->connection_len = header->data_len;
|
172
172
|
}
|
173
173
|
return 0;
|
174
174
|
}
|
175
175
|
#endif
|
176
176
|
|
177
|
+
static void no_on_header_found(http_request_s *request, http_header_s *header) {
|
178
|
+
(void)request;
|
179
|
+
(void)header;
|
180
|
+
}
|
177
181
|
/* *****************************************************************************
|
178
182
|
The (public) parsing
|
179
183
|
*/
|
@@ -194,33 +198,40 @@ buffer
|
|
194
198
|
and the same `http_request_s` should be returned to the parsed on the "next
|
195
199
|
round", only the `len` argument is expected to grow.
|
196
200
|
*/
|
197
|
-
ssize_t http1_parse_request_headers(
|
198
|
-
|
199
|
-
|
201
|
+
ssize_t http1_parse_request_headers(
|
202
|
+
void *buffer, size_t len, http_request_s *request,
|
203
|
+
void (*on_header_found)(http_request_s *request, http_header_s *header)) {
|
204
|
+
if (request == NULL || buffer == NULL)
|
200
205
|
return -1;
|
206
|
+
if (!on_header_found)
|
207
|
+
on_header_found = no_on_header_found;
|
201
208
|
if (request->body_str || request->body_file > 0)
|
202
209
|
return 0;
|
203
210
|
if (len == 0)
|
204
211
|
return -2;
|
205
|
-
|
206
|
-
char *
|
212
|
+
http_header_s header;
|
213
|
+
char *pos = (char *)buffer;
|
214
|
+
char *end = (char *)buffer + len;
|
207
215
|
char *next, *tmp;
|
208
216
|
// collect method and restart parser if already collected
|
209
217
|
if (request->method == NULL) {
|
210
218
|
// eat empty spaces
|
211
219
|
while ((*pos == '\n' || *pos == '\r') && pos < end)
|
212
220
|
++pos;
|
221
|
+
CHECK_END();
|
213
222
|
request->method = (char *)pos;
|
214
223
|
next = seek_to_char(pos, end, ' ');
|
215
|
-
if (next == NULL)
|
216
|
-
|
224
|
+
if (next == NULL) {
|
225
|
+
request->method = NULL;
|
226
|
+
return -2;
|
227
|
+
}
|
217
228
|
request->method_len = (uintptr_t)next - (uintptr_t)pos;
|
218
229
|
pos = next;
|
219
230
|
*(pos++) = 0;
|
220
231
|
CHECK_END();
|
221
232
|
} else {
|
222
|
-
/* use the `
|
223
|
-
pos = request->
|
233
|
+
/* use the `udata` pointer to store current position in the buffer */
|
234
|
+
pos = request->udata;
|
224
235
|
CHECK_END();
|
225
236
|
}
|
226
237
|
// collect path
|
@@ -252,14 +263,16 @@ ssize_t http1_parse_request_headers(void *buffer, size_t len,
|
|
252
263
|
EAT_EOL();
|
253
264
|
CHECK_END();
|
254
265
|
}
|
266
|
+
|
255
267
|
// collect headers
|
256
|
-
while (pos < end && *pos !=
|
257
|
-
|
258
|
-
if (request->headers_count >= request->metadata.max_headers)
|
268
|
+
while (pos < end && *pos != 0) { /* NUL as term */
|
269
|
+
if (request->headers_count >= HTTP1_MAX_HEADER_COUNT)
|
259
270
|
return -1;
|
260
271
|
next = seek_to_2eol(pos, end);
|
261
272
|
if (next == NULL)
|
262
273
|
return -2;
|
274
|
+
if (next == pos) /*headers finished */
|
275
|
+
break;
|
263
276
|
#if defined(HTTP_HEADERS_LOWERCASE) && HTTP_HEADERS_LOWERCASE == 1
|
264
277
|
tmp = pos;
|
265
278
|
while (tmp < next && *tmp != ':') {
|
@@ -273,29 +286,29 @@ ssize_t http1_parse_request_headers(void *buffer, size_t len,
|
|
273
286
|
if (!tmp)
|
274
287
|
return -1;
|
275
288
|
#endif
|
276
|
-
|
277
|
-
|
289
|
+
header.name = (void *)pos;
|
290
|
+
header.name_len = (uintptr_t)(tmp - pos);
|
278
291
|
*(tmp++) = 0;
|
279
292
|
if (*tmp == ' ')
|
280
293
|
*(tmp++) = 0;
|
281
|
-
|
282
|
-
|
294
|
+
header.data = (void *)tmp;
|
295
|
+
header.data_len = (uintptr_t)(next - tmp);
|
283
296
|
// eat EOL before content-length processing.
|
284
297
|
pos = next;
|
285
298
|
EAT_EOL();
|
286
299
|
// print debug info
|
287
|
-
// fprintf(stderr, "Got header %s (%u): %s (%u)\n",
|
288
|
-
//
|
289
|
-
// request->headers[request->headers_count].name_length,
|
290
|
-
// request->headers[request->headers_count].value,
|
291
|
-
// request->headers[request->headers_count].value_length);
|
300
|
+
// fprintf(stderr, "Got header %s (%u): %s (%u)\n", header.name,
|
301
|
+
// header.name_len, header.data, header.data_len);
|
292
302
|
// check special headers and assign value.
|
293
|
-
review_header_data(request,
|
294
|
-
// advance header position
|
303
|
+
review_header_data(request, &header);
|
295
304
|
request->headers_count += 1;
|
305
|
+
on_header_found(request, &header);
|
306
|
+
// advance header position
|
296
307
|
CHECK_END();
|
297
308
|
}
|
298
|
-
//
|
309
|
+
// Did we break because there's no more data or end of headers?
|
310
|
+
CHECK_END();
|
311
|
+
// "eat" the end of headers line and finish processing.
|
299
312
|
EAT_EOL();
|
300
313
|
if (request->content_length &&
|
301
314
|
(end - pos) >= (ssize_t)request->content_length) {
|
@@ -308,9 +321,8 @@ ssize_t http1_parse_request_headers(void *buffer, size_t len,
|
|
308
321
|
// request->body_str);
|
309
322
|
return (ssize_t)(pos - (char *)buffer) + request->content_length;
|
310
323
|
}
|
311
|
-
|
312
324
|
// we're done.
|
313
|
-
return pos - (char *)buffer;
|
325
|
+
return (ssize_t)(pos - (char *)buffer);
|
314
326
|
}
|
315
327
|
|
316
328
|
/**
|
@@ -347,28 +359,26 @@ ssize_t http1_parse_request_body(void *buffer, size_t len,
|
|
347
359
|
if (request->body_file == -1)
|
348
360
|
return -1;
|
349
361
|
// use the `next` field to store parser state.
|
350
|
-
uintptr_t *tmp = (uintptr_t *)(&request->
|
362
|
+
uintptr_t *tmp = (uintptr_t *)(&request->udata);
|
351
363
|
*tmp = 0;
|
352
364
|
}
|
353
365
|
// make sure we have anything to read. This might be an initializing call.
|
354
366
|
if (len == 0)
|
355
|
-
return ((uintptr_t)(request->
|
356
|
-
? 0
|
357
|
-
: (-2);
|
367
|
+
return ((uintptr_t)(request->udata)) >= request->content_length ? 0 : (-2);
|
358
368
|
// Calculate how much of the buffer should be read.
|
359
369
|
ssize_t to_read =
|
360
|
-
((request->content_length - ((uintptr_t)request->
|
361
|
-
? (request->content_length - ((uintptr_t)request->
|
370
|
+
((request->content_length - ((uintptr_t)request->udata)) < len)
|
371
|
+
? (request->content_length - ((uintptr_t)request->udata))
|
362
372
|
: len;
|
363
373
|
// write the data to the temporary file.
|
364
374
|
if (write(request->body_file, buffer, to_read) < to_read)
|
365
375
|
return -1;
|
366
376
|
// update the `next` field data with the received content length
|
367
|
-
uintptr_t *tmp = (uintptr_t *)(&request->
|
377
|
+
uintptr_t *tmp = (uintptr_t *)(&request->udata);
|
368
378
|
*tmp += to_read; // request->metadata.next += to_read;
|
369
379
|
|
370
380
|
// check the state and return.
|
371
|
-
if (((uintptr_t)request->
|
381
|
+
if (((uintptr_t)request->udata) >= request->content_length) {
|
372
382
|
lseek(request->body_file, 0, SEEK_SET);
|
373
383
|
return to_read;
|
374
384
|
}
|
@@ -377,9 +387,11 @@ ssize_t http1_parse_request_body(void *buffer, size_t len,
|
|
377
387
|
|
378
388
|
#if defined(DEBUG) && DEBUG == 1
|
379
389
|
|
390
|
+
// #include "http1_request.h"
|
391
|
+
|
380
392
|
#include <time.h>
|
381
393
|
|
382
|
-
void
|
394
|
+
void http1_parser_test(void) {
|
383
395
|
char request_text[] = "GET /?a=b HTTP/1.1\r\n"
|
384
396
|
"Host: local\r\n"
|
385
397
|
"Upgrade: websocket\r\n"
|
@@ -388,11 +400,9 @@ void http_parser_test(void) {
|
|
388
400
|
"\r\n"
|
389
401
|
"Hello World!\r\n";
|
390
402
|
size_t request_length = sizeof(request_text) - 1;
|
391
|
-
|
392
|
-
http_request_s *request = (void *)request_mem;
|
393
|
-
*request = (http_request_s){.metadata.max_headers = 24};
|
403
|
+
http_request_s *request = http_request_create(HTTP_V1);
|
394
404
|
ssize_t ret =
|
395
|
-
http1_parse_request_headers(request_text, request_length, request);
|
405
|
+
http1_parse_request_headers(request_text, request_length, request, NULL);
|
396
406
|
if (ret == -1) {
|
397
407
|
fprintf(stderr, "* Parser FAILED -1.\n");
|
398
408
|
} else if (ret == -2) {
|
@@ -436,7 +446,12 @@ void http_parser_test(void) {
|
|
436
446
|
"Connection: close\r\n"
|
437
447
|
"\r\n"
|
438
448
|
"Hello World!\r\n";
|
439
|
-
http1_parse_request_headers(request_text2, request_length, request
|
449
|
+
if (http1_parse_request_headers(request_text2, request_length, request,
|
450
|
+
NULL) <= 0 ||
|
451
|
+
(request->upgrade_len != 9)) {
|
452
|
+
fprintf(stderr, "* HTTP/1.1 simple_parser unknown error\n");
|
453
|
+
return;
|
454
|
+
}
|
440
455
|
http_request_clear(request);
|
441
456
|
}
|
442
457
|
end = clock();
|
@@ -450,16 +465,17 @@ void http_parser_test(void) {
|
|
450
465
|
"\r\n"
|
451
466
|
"Hello World!\r\n";
|
452
467
|
fprintf(stderr, "start\n");
|
453
|
-
if (http1_parse_request_headers(request_text2, 7, request) != -2)
|
468
|
+
if (http1_parse_request_headers(request_text2, 7, request, NULL) != -2)
|
454
469
|
fprintf(stderr, "Fragmented Parsing FAILED\n");
|
455
470
|
fprintf(stderr, "step\n");
|
456
|
-
if (http1_parse_request_headers(request_text2, 27, request) != -2)
|
471
|
+
if (http1_parse_request_headers(request_text2, 27, request, NULL) != -2)
|
457
472
|
fprintf(stderr, "Fragmented Parsing FAILED\n");
|
458
473
|
fprintf(stderr, "step\n");
|
459
|
-
if (http1_parse_request_headers(request_text2, 38, request) != -2)
|
474
|
+
if (http1_parse_request_headers(request_text2, 38, request, NULL) != -2)
|
460
475
|
fprintf(stderr, "Fragmented Parsing FAILED\n");
|
461
476
|
fprintf(stderr, "step\n");
|
462
|
-
if ((ret = http1_parse_request_headers(request_text2, 98, request)) !=
|
477
|
+
if ((ret = http1_parse_request_headers(request_text2, 98, request, NULL)) !=
|
478
|
+
94)
|
463
479
|
fprintf(stderr, "Fragmented Parsing (some body) FAILED\n");
|
464
480
|
fprintf(stderr, "read: %lu\n", ret);
|
465
481
|
if ((ret += http1_parse_request_body(request_text2 + ret,
|
@@ -474,7 +490,7 @@ void http_parser_test(void) {
|
|
474
490
|
perror("Couldn't read temporary file");
|
475
491
|
fprintf(stderr, "Body:\n%.*s\n", (int)request->content_length, request_text);
|
476
492
|
|
477
|
-
|
493
|
+
http_request_destroy(request);
|
478
494
|
}
|
479
495
|
|
480
496
|
#endif
|