http_parser.rb 0.5.1 → 0.6.0.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitmodules +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +11 -4
- data/LICENSE-MIT +20 -0
- data/README.md +51 -46
- data/bench/standalone.rb +23 -0
- data/bench/thin.rb +1 -0
- data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +121 -56
- data/ext/ruby_http_parser/ruby_http_parser.c +89 -48
- data/ext/ruby_http_parser/vendor/http-parser/AUTHORS +32 -0
- data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +5 -1
- data/ext/ruby_http_parser/vendor/http-parser/Makefile +34 -17
- data/ext/ruby_http_parser/vendor/http-parser/README.md +9 -2
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +1045 -589
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.gyp +79 -0
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +148 -17
- data/ext/ruby_http_parser/vendor/http-parser/test.c +1138 -128
- data/ext/ruby_http_parser/vendor/http-parser-java/AUTHORS +32 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT +30 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/Makefile +34 -17
- data/ext/ruby_http_parser/vendor/http-parser-java/README.md +30 -18
- data/ext/ruby_http_parser/vendor/http-parser-java/TODO +9 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/ext/primitives.jar +0 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +1075 -607
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.gyp +79 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +190 -40
- data/ext/ruby_http_parser/vendor/http-parser-java/src/Http-parser.java.iml +22 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/FieldData.java +41 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +4 -2
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPHeadersCompleteCallback.java +13 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +67 -52
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +5 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParserUrl.java +76 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +323 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/{lolevel/Util.java → Util.java} +34 -35
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPHeadersCompleteCallback.java +12 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +839 -587
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +2 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +374 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/ParseUrl.java +51 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java +69 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java +52 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java +16 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java +48 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java +171 -446
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java +62 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java +3 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java +27 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Url.java +127 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java +236 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java +59 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/test.c +1318 -184
- data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +355 -49
- data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
- data/http_parser.rb.gemspec +10 -2
- data/lib/http_parser.rb +17 -0
- data/spec/parser_spec.rb +157 -23
- data/spec/support/requests.json +236 -24
- data/spec/support/responses.json +182 -36
- data/tasks/compile.rake +5 -3
- data/tasks/fixtures.rake +8 -2
- metadata +209 -127
- data/ext/ruby_http_parser/vendor/http-parser-java/CONTRIBUTIONS +0 -4
- data/ext/ruby_http_parser/vendor/http-parser-java/compile +0 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test_permutations +0 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test_unit +0 -1
|
@@ -17,12 +17,11 @@ typedef struct ParserWrapper {
|
|
|
17
17
|
ryah_http_parser parser;
|
|
18
18
|
|
|
19
19
|
VALUE request_url;
|
|
20
|
-
VALUE request_path;
|
|
21
|
-
VALUE query_string;
|
|
22
|
-
VALUE fragment;
|
|
23
20
|
|
|
24
21
|
VALUE headers;
|
|
25
22
|
|
|
23
|
+
VALUE upgrade_data;
|
|
24
|
+
|
|
26
25
|
VALUE on_message_begin;
|
|
27
26
|
VALUE on_headers_complete;
|
|
28
27
|
VALUE on_body;
|
|
@@ -32,6 +31,8 @@ typedef struct ParserWrapper {
|
|
|
32
31
|
VALUE stopped;
|
|
33
32
|
VALUE completed;
|
|
34
33
|
|
|
34
|
+
VALUE header_value_type;
|
|
35
|
+
|
|
35
36
|
VALUE last_field_name;
|
|
36
37
|
VALUE curr_field_name;
|
|
37
38
|
|
|
@@ -45,9 +46,8 @@ void ParserWrapper_init(ParserWrapper *wrapper) {
|
|
|
45
46
|
wrapper->parser.http_minor = 0;
|
|
46
47
|
|
|
47
48
|
wrapper->request_url = Qnil;
|
|
48
|
-
|
|
49
|
-
wrapper->
|
|
50
|
-
wrapper->fragment = Qnil;
|
|
49
|
+
|
|
50
|
+
wrapper->upgrade_data = Qnil;
|
|
51
51
|
|
|
52
52
|
wrapper->headers = Qnil;
|
|
53
53
|
wrapper->completed = Qfalse;
|
|
@@ -60,9 +60,7 @@ void ParserWrapper_mark(void *data) {
|
|
|
60
60
|
if(data) {
|
|
61
61
|
ParserWrapper *wrapper = (ParserWrapper *) data;
|
|
62
62
|
rb_gc_mark_maybe(wrapper->request_url);
|
|
63
|
-
rb_gc_mark_maybe(wrapper->
|
|
64
|
-
rb_gc_mark_maybe(wrapper->query_string);
|
|
65
|
-
rb_gc_mark_maybe(wrapper->fragment);
|
|
63
|
+
rb_gc_mark_maybe(wrapper->upgrade_data);
|
|
66
64
|
rb_gc_mark_maybe(wrapper->headers);
|
|
67
65
|
rb_gc_mark_maybe(wrapper->on_message_begin);
|
|
68
66
|
rb_gc_mark_maybe(wrapper->on_headers_complete);
|
|
@@ -93,6 +91,10 @@ static ID Ion_body;
|
|
|
93
91
|
static ID Ion_message_complete;
|
|
94
92
|
|
|
95
93
|
static VALUE Sstop;
|
|
94
|
+
static VALUE Sreset;
|
|
95
|
+
static VALUE Sarrays;
|
|
96
|
+
static VALUE Sstrings;
|
|
97
|
+
static VALUE Smixed;
|
|
96
98
|
|
|
97
99
|
/** Callbacks **/
|
|
98
100
|
|
|
@@ -100,10 +102,8 @@ int on_message_begin(ryah_http_parser *parser) {
|
|
|
100
102
|
GET_WRAPPER(wrapper, parser);
|
|
101
103
|
|
|
102
104
|
wrapper->request_url = rb_str_new2("");
|
|
103
|
-
wrapper->request_path = rb_str_new2("");
|
|
104
|
-
wrapper->query_string = rb_str_new2("");
|
|
105
|
-
wrapper->fragment = rb_str_new2("");
|
|
106
105
|
wrapper->headers = rb_hash_new();
|
|
106
|
+
wrapper->upgrade_data = rb_str_new2("");
|
|
107
107
|
|
|
108
108
|
VALUE ret = Qnil;
|
|
109
109
|
|
|
@@ -127,24 +127,6 @@ int on_url(ryah_http_parser *parser, const char *at, size_t length) {
|
|
|
127
127
|
return 0;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
int on_path(ryah_http_parser *parser, const char *at, size_t length) {
|
|
131
|
-
GET_WRAPPER(wrapper, parser);
|
|
132
|
-
rb_str_cat(wrapper->request_path, at, length);
|
|
133
|
-
return 0;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
int on_query_string(ryah_http_parser *parser, const char *at, size_t length) {
|
|
137
|
-
GET_WRAPPER(wrapper, parser);
|
|
138
|
-
rb_str_cat(wrapper->query_string, at, length);
|
|
139
|
-
return 0;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
int on_fragment(ryah_http_parser *parser, const char *at, size_t length) {
|
|
143
|
-
GET_WRAPPER(wrapper, parser);
|
|
144
|
-
rb_str_cat(wrapper->fragment, at, length);
|
|
145
|
-
return 0;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
130
|
int on_header_field(ryah_http_parser *parser, const char *at, size_t length) {
|
|
149
131
|
GET_WRAPPER(wrapper, parser);
|
|
150
132
|
|
|
@@ -161,17 +143,45 @@ int on_header_field(ryah_http_parser *parser, const char *at, size_t length) {
|
|
|
161
143
|
int on_header_value(ryah_http_parser *parser, const char *at, size_t length) {
|
|
162
144
|
GET_WRAPPER(wrapper, parser);
|
|
163
145
|
|
|
146
|
+
int new_field = 0;
|
|
147
|
+
VALUE current_value;
|
|
148
|
+
|
|
164
149
|
if (wrapper->last_field_name == Qnil) {
|
|
150
|
+
new_field = 1;
|
|
165
151
|
wrapper->last_field_name = wrapper->curr_field_name;
|
|
166
152
|
wrapper->curr_field_name = Qnil;
|
|
153
|
+
}
|
|
167
154
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
155
|
+
current_value = rb_hash_aref(wrapper->headers, wrapper->last_field_name);
|
|
156
|
+
|
|
157
|
+
if (new_field == 1) {
|
|
158
|
+
if (current_value == Qnil) {
|
|
159
|
+
if (wrapper->header_value_type == Sarrays) {
|
|
160
|
+
rb_hash_aset(wrapper->headers, wrapper->last_field_name, rb_ary_new3(1, rb_str_new2("")));
|
|
161
|
+
} else {
|
|
162
|
+
rb_hash_aset(wrapper->headers, wrapper->last_field_name, rb_str_new2(""));
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
if (wrapper->header_value_type == Smixed) {
|
|
166
|
+
if (TYPE(current_value) == T_STRING) {
|
|
167
|
+
rb_hash_aset(wrapper->headers, wrapper->last_field_name, rb_ary_new3(2, current_value, rb_str_new2("")));
|
|
168
|
+
} else {
|
|
169
|
+
rb_ary_push(current_value, rb_str_new2(""));
|
|
170
|
+
}
|
|
171
|
+
} else if (wrapper->header_value_type == Sarrays) {
|
|
172
|
+
rb_ary_push(current_value, rb_str_new2(""));
|
|
173
|
+
} else {
|
|
174
|
+
rb_str_cat(current_value, ", ", 2);
|
|
175
|
+
}
|
|
171
176
|
}
|
|
177
|
+
current_value = rb_hash_aref(wrapper->headers, wrapper->last_field_name);
|
|
172
178
|
}
|
|
173
179
|
|
|
174
|
-
|
|
180
|
+
if (TYPE(current_value) == T_ARRAY) {
|
|
181
|
+
current_value = rb_ary_entry(current_value, -1);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
rb_str_cat(current_value, at, length);
|
|
175
185
|
|
|
176
186
|
return 0;
|
|
177
187
|
}
|
|
@@ -190,6 +200,8 @@ int on_headers_complete(ryah_http_parser *parser) {
|
|
|
190
200
|
if (ret == Sstop) {
|
|
191
201
|
wrapper->stopped = Qtrue;
|
|
192
202
|
return -1;
|
|
203
|
+
} else if (ret == Sreset){
|
|
204
|
+
return 1;
|
|
193
205
|
} else {
|
|
194
206
|
return 0;
|
|
195
207
|
}
|
|
@@ -236,10 +248,7 @@ int on_message_complete(ryah_http_parser *parser) {
|
|
|
236
248
|
|
|
237
249
|
static ryah_http_parser_settings settings = {
|
|
238
250
|
.on_message_begin = on_message_begin,
|
|
239
|
-
.on_path = on_path,
|
|
240
|
-
.on_query_string = on_query_string,
|
|
241
251
|
.on_url = on_url,
|
|
242
|
-
.on_fragment = on_fragment,
|
|
243
252
|
.on_header_field = on_header_field,
|
|
244
253
|
.on_header_value = on_header_value,
|
|
245
254
|
.on_headers_complete = on_headers_complete,
|
|
@@ -276,12 +285,24 @@ VALUE ResponseParser_alloc(VALUE klass) {
|
|
|
276
285
|
return Parser_alloc_by_type(klass, HTTP_RESPONSE);
|
|
277
286
|
}
|
|
278
287
|
|
|
288
|
+
VALUE Parser_strict_p(VALUE klass) {
|
|
289
|
+
return HTTP_PARSER_STRICT == 1 ? Qtrue : Qfalse;
|
|
290
|
+
}
|
|
291
|
+
|
|
279
292
|
VALUE Parser_initialize(int argc, VALUE *argv, VALUE self) {
|
|
280
293
|
ParserWrapper *wrapper = NULL;
|
|
281
294
|
DATA_GET(self, ParserWrapper, wrapper);
|
|
282
295
|
|
|
283
|
-
|
|
296
|
+
wrapper->header_value_type = rb_iv_get(CLASS_OF(self), "@default_header_value_type");
|
|
297
|
+
|
|
298
|
+
if (argc == 1) {
|
|
284
299
|
wrapper->callback_object = argv[0];
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (argc == 2) {
|
|
303
|
+
wrapper->callback_object = argv[0];
|
|
304
|
+
wrapper->header_value_type = argv[1];
|
|
305
|
+
}
|
|
285
306
|
|
|
286
307
|
return self;
|
|
287
308
|
}
|
|
@@ -299,10 +320,14 @@ VALUE Parser_execute(VALUE self, VALUE data) {
|
|
|
299
320
|
size_t nparsed = ryah_http_parser_execute(&wrapper->parser, &settings, ptr, len);
|
|
300
321
|
|
|
301
322
|
if (wrapper->parser.upgrade) {
|
|
302
|
-
|
|
303
|
-
|
|
323
|
+
if (RTEST(wrapper->stopped))
|
|
324
|
+
nparsed += 1;
|
|
325
|
+
|
|
326
|
+
rb_str_cat(wrapper->upgrade_data, ptr + nparsed, len - nparsed);
|
|
327
|
+
|
|
328
|
+
} else if (nparsed != (size_t)len) {
|
|
304
329
|
if (!RTEST(wrapper->stopped) && !RTEST(wrapper->completed))
|
|
305
|
-
rb_raise(eParserError, "Could not parse data entirely");
|
|
330
|
+
rb_raise(eParserError, "Could not parse data entirely (%zu != %zu)", nparsed, len);
|
|
306
331
|
else
|
|
307
332
|
nparsed += 1; // error states fail on the current character
|
|
308
333
|
}
|
|
@@ -353,7 +378,7 @@ VALUE Parser_upgrade_p(VALUE self) {
|
|
|
353
378
|
ParserWrapper *wrapper = NULL;
|
|
354
379
|
DATA_GET(self, ParserWrapper, wrapper);
|
|
355
380
|
|
|
356
|
-
return wrapper->parser.upgrade
|
|
381
|
+
return wrapper->parser.upgrade ? Qtrue : Qfalse;
|
|
357
382
|
}
|
|
358
383
|
|
|
359
384
|
VALUE Parser_http_version(VALUE self) {
|
|
@@ -414,10 +439,20 @@ VALUE Parser_status_code(VALUE self) {
|
|
|
414
439
|
}
|
|
415
440
|
|
|
416
441
|
DEFINE_GETTER(request_url);
|
|
417
|
-
DEFINE_GETTER(request_path);
|
|
418
|
-
DEFINE_GETTER(query_string);
|
|
419
|
-
DEFINE_GETTER(fragment);
|
|
420
442
|
DEFINE_GETTER(headers);
|
|
443
|
+
DEFINE_GETTER(upgrade_data);
|
|
444
|
+
DEFINE_GETTER(header_value_type);
|
|
445
|
+
|
|
446
|
+
VALUE Parser_set_header_value_type(VALUE self, VALUE val) {
|
|
447
|
+
if (val != Sarrays && val != Sstrings && val != Smixed) {
|
|
448
|
+
rb_raise(rb_eArgError, "Invalid header value type");
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
ParserWrapper *wrapper = NULL;
|
|
452
|
+
DATA_GET(self, ParserWrapper, wrapper);
|
|
453
|
+
wrapper->header_value_type = val;
|
|
454
|
+
return wrapper->header_value_type;
|
|
455
|
+
}
|
|
421
456
|
|
|
422
457
|
VALUE Parser_reset(VALUE self) {
|
|
423
458
|
ParserWrapper *wrapper = NULL;
|
|
@@ -441,11 +476,17 @@ void Init_ruby_http_parser() {
|
|
|
441
476
|
Ion_body = rb_intern("on_body");
|
|
442
477
|
Ion_message_complete = rb_intern("on_message_complete");
|
|
443
478
|
Sstop = ID2SYM(rb_intern("stop"));
|
|
479
|
+
Sreset = ID2SYM(rb_intern("reset"));
|
|
480
|
+
|
|
481
|
+
Sarrays = ID2SYM(rb_intern("arrays"));
|
|
482
|
+
Sstrings = ID2SYM(rb_intern("strings"));
|
|
483
|
+
Smixed = ID2SYM(rb_intern("mixed"));
|
|
444
484
|
|
|
445
485
|
rb_define_alloc_func(cParser, Parser_alloc);
|
|
446
486
|
rb_define_alloc_func(cRequestParser, RequestParser_alloc);
|
|
447
487
|
rb_define_alloc_func(cResponseParser, ResponseParser_alloc);
|
|
448
488
|
|
|
489
|
+
rb_define_singleton_method(cParser, "strict?", Parser_strict_p, 0);
|
|
449
490
|
rb_define_method(cParser, "initialize", Parser_initialize, -1);
|
|
450
491
|
|
|
451
492
|
rb_define_method(cParser, "on_message_begin=", Parser_set_on_message_begin, 1);
|
|
@@ -465,10 +506,10 @@ void Init_ruby_http_parser() {
|
|
|
465
506
|
rb_define_method(cParser, "status_code", Parser_status_code, 0);
|
|
466
507
|
|
|
467
508
|
rb_define_method(cParser, "request_url", Parser_request_url, 0);
|
|
468
|
-
rb_define_method(cParser, "request_path", Parser_request_path, 0);
|
|
469
|
-
rb_define_method(cParser, "query_string", Parser_query_string, 0);
|
|
470
|
-
rb_define_method(cParser, "fragment", Parser_fragment, 0);
|
|
471
509
|
rb_define_method(cParser, "headers", Parser_headers, 0);
|
|
510
|
+
rb_define_method(cParser, "upgrade_data", Parser_upgrade_data, 0);
|
|
511
|
+
rb_define_method(cParser, "header_value_type", Parser_header_value_type, 0);
|
|
512
|
+
rb_define_method(cParser, "header_value_type=", Parser_set_header_value_type, 1);
|
|
472
513
|
|
|
473
514
|
rb_define_method(cParser, "reset!", Parser_reset, 0);
|
|
474
515
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Authors ordered by first contribution.
|
|
2
|
+
Ryan Dahl <ry@tinyclouds.org>
|
|
3
|
+
Jeremy Hinegardner <jeremy@hinegardner.org>
|
|
4
|
+
Sergey Shepelev <temotor@gmail.com>
|
|
5
|
+
Joe Damato <ice799@gmail.com>
|
|
6
|
+
tomika <tomika_nospam@freemail.hu>
|
|
7
|
+
Phoenix Sol <phoenix@burninglabs.com>
|
|
8
|
+
Cliff Frey <cliff@meraki.com>
|
|
9
|
+
Ewen Cheslack-Postava <ewencp@cs.stanford.edu>
|
|
10
|
+
Santiago Gala <sgala@apache.org>
|
|
11
|
+
Tim Becker <tim.becker@syngenio.de>
|
|
12
|
+
Jeff Terrace <jterrace@gmail.com>
|
|
13
|
+
Ben Noordhuis <info@bnoordhuis.nl>
|
|
14
|
+
Nathan Rajlich <nathan@tootallnate.net>
|
|
15
|
+
Mark Nottingham <mnot@mnot.net>
|
|
16
|
+
Aman Gupta <aman@tmm1.net>
|
|
17
|
+
Tim Becker <tim.becker@kuriositaet.de>
|
|
18
|
+
Sean Cunningham <sean.cunningham@mandiant.com>
|
|
19
|
+
Peter Griess <pg@std.in>
|
|
20
|
+
Salman Haq <salman.haq@asti-usa.com>
|
|
21
|
+
Cliff Frey <clifffrey@gmail.com>
|
|
22
|
+
Jon Kolb <jon@b0g.us>
|
|
23
|
+
Fouad Mardini <f.mardini@gmail.com>
|
|
24
|
+
Paul Querna <pquerna@apache.org>
|
|
25
|
+
Felix Geisendörfer <felix@debuggable.com>
|
|
26
|
+
koichik <koichik@improvement.jp>
|
|
27
|
+
Andre Caron <andre.l.caron@gmail.com>
|
|
28
|
+
Ivo Raisr <ivosh@ivosh.net>
|
|
29
|
+
James McLaughlin <jamie@lacewing-project.org>
|
|
30
|
+
David Gwynne <loki@animata.net>
|
|
31
|
+
LE ROUX Thomas <thomas@procheo.fr>
|
|
32
|
+
Randy Rizun <rrizun@ortivawireless.com>
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
|
|
2
|
+
Igor Sysoev.
|
|
3
|
+
|
|
4
|
+
Additional changes are licensed under the same terms as NGINX and
|
|
5
|
+
copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
2
6
|
|
|
3
7
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
8
|
of this software and associated documentation files (the "Software"), to
|
|
@@ -1,41 +1,58 @@
|
|
|
1
|
-
OPT_DEBUG=-O0 -g -Wall -Wextra -Werror -I.
|
|
2
|
-
OPT_FAST=-O3 -DHTTP_PARSER_STRICT=0 -I.
|
|
3
|
-
|
|
4
1
|
CC?=gcc
|
|
2
|
+
AR?=ar
|
|
3
|
+
|
|
4
|
+
CPPFLAGS += -I.
|
|
5
|
+
CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1 -DHTTP_PARSER_DEBUG=1
|
|
6
|
+
CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA)
|
|
7
|
+
CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0 -DHTTP_PARSER_DEBUG=0
|
|
8
|
+
CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA)
|
|
5
9
|
|
|
10
|
+
CFLAGS += -Wall -Wextra -Werror
|
|
11
|
+
CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA)
|
|
12
|
+
CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA)
|
|
13
|
+
CFLAGS_LIB = $(CFLAGS_FAST) -fPIC
|
|
6
14
|
|
|
7
|
-
test: test_g
|
|
15
|
+
test: test_g test_fast
|
|
8
16
|
./test_g
|
|
17
|
+
./test_fast
|
|
9
18
|
|
|
10
19
|
test_g: http_parser_g.o test_g.o
|
|
11
|
-
$(CC) $(
|
|
20
|
+
$(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@
|
|
12
21
|
|
|
13
22
|
test_g.o: test.c http_parser.h Makefile
|
|
14
|
-
$(CC) $(
|
|
15
|
-
|
|
16
|
-
test.o: test.c http_parser.h Makefile
|
|
17
|
-
$(CC) $(OPT_FAST) -c test.c -o $@
|
|
23
|
+
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c test.c -o $@
|
|
18
24
|
|
|
19
25
|
http_parser_g.o: http_parser.c http_parser.h Makefile
|
|
20
|
-
$(CC) $(
|
|
26
|
+
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c http_parser.c -o $@
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
test_fast: http_parser.o test.o http_parser.h
|
|
29
|
+
$(CC) $(CFLAGS_FAST) $(LDFLAGS) http_parser.o test.o -o $@
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
$(CC) $(
|
|
31
|
+
test.o: test.c http_parser.h Makefile
|
|
32
|
+
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
$(CC) $(
|
|
34
|
+
http_parser.o: http_parser.c http_parser.h Makefile
|
|
35
|
+
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c
|
|
30
36
|
|
|
31
37
|
test-run-timed: test_fast
|
|
32
38
|
while(true) do time ./test_fast > /dev/null; done
|
|
33
39
|
|
|
40
|
+
test-valgrind: test_g
|
|
41
|
+
valgrind ./test_g
|
|
42
|
+
|
|
43
|
+
libhttp_parser.o: http_parser.c http_parser.h Makefile
|
|
44
|
+
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o
|
|
45
|
+
|
|
46
|
+
library: libhttp_parser.o
|
|
47
|
+
$(CC) -shared -o libhttp_parser.so libhttp_parser.o
|
|
48
|
+
|
|
49
|
+
package: http_parser.o
|
|
50
|
+
$(AR) rcs libhttp_parser.a http_parser.o
|
|
34
51
|
|
|
35
52
|
tags: http_parser.c http_parser.h test.c
|
|
36
53
|
ctags $^
|
|
37
54
|
|
|
38
55
|
clean:
|
|
39
|
-
rm -f *.o test test_fast test_g http_parser.tar tags
|
|
56
|
+
rm -f *.o *.a test test_fast test_g http_parser.tar tags libhttp_parser.so libhttp_parser.o
|
|
40
57
|
|
|
41
58
|
.PHONY: clean package test-run test-run-timed test-valgrind
|
|
@@ -24,7 +24,7 @@ The parser extracts the following information from HTTP messages:
|
|
|
24
24
|
* Response status code
|
|
25
25
|
* Transfer-Encoding
|
|
26
26
|
* HTTP version
|
|
27
|
-
* Request
|
|
27
|
+
* Request URL
|
|
28
28
|
* Message body
|
|
29
29
|
|
|
30
30
|
|
|
@@ -126,7 +126,7 @@ There are two types of callbacks:
|
|
|
126
126
|
* notification `typedef int (*http_cb) (http_parser*);`
|
|
127
127
|
Callbacks: on_message_begin, on_headers_complete, on_message_complete.
|
|
128
128
|
* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`
|
|
129
|
-
Callbacks: (requests only)
|
|
129
|
+
Callbacks: (requests only) on_uri,
|
|
130
130
|
(common) on_header_field, on_header_value, on_body;
|
|
131
131
|
|
|
132
132
|
Callbacks must return 0 on success. Returning a non-zero value indicates
|
|
@@ -164,6 +164,13 @@ and apply following logic:
|
|
|
164
164
|
------------------------ ------------ --------------------------------------------
|
|
165
165
|
|
|
166
166
|
|
|
167
|
+
Parsing URLs
|
|
168
|
+
------------
|
|
169
|
+
|
|
170
|
+
A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`.
|
|
171
|
+
Users of this library may wish to use it to parse URLs constructed from
|
|
172
|
+
consecutive `on_url` callbacks.
|
|
173
|
+
|
|
167
174
|
See examples of reading in headers:
|
|
168
175
|
|
|
169
176
|
* [partial example](http://gist.github.com/155877) in C
|