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.
Files changed (70) hide show
  1. data/.gitmodules +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +11 -4
  4. data/LICENSE-MIT +20 -0
  5. data/README.md +51 -46
  6. data/bench/standalone.rb +23 -0
  7. data/bench/thin.rb +1 -0
  8. data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +121 -56
  9. data/ext/ruby_http_parser/ruby_http_parser.c +89 -48
  10. data/ext/ruby_http_parser/vendor/http-parser/AUTHORS +32 -0
  11. data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +5 -1
  12. data/ext/ruby_http_parser/vendor/http-parser/Makefile +34 -17
  13. data/ext/ruby_http_parser/vendor/http-parser/README.md +9 -2
  14. data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +1045 -589
  15. data/ext/ruby_http_parser/vendor/http-parser/http_parser.gyp +79 -0
  16. data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +148 -17
  17. data/ext/ruby_http_parser/vendor/http-parser/test.c +1138 -128
  18. data/ext/ruby_http_parser/vendor/http-parser-java/AUTHORS +32 -0
  19. data/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT +30 -1
  20. data/ext/ruby_http_parser/vendor/http-parser-java/Makefile +34 -17
  21. data/ext/ruby_http_parser/vendor/http-parser-java/README.md +30 -18
  22. data/ext/ruby_http_parser/vendor/http-parser-java/TODO +9 -0
  23. data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
  24. data/ext/ruby_http_parser/vendor/http-parser-java/ext/primitives.jar +0 -0
  25. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +1075 -607
  26. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.gyp +79 -0
  27. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +190 -40
  28. data/ext/ruby_http_parser/vendor/http-parser-java/src/Http-parser.java.iml +22 -0
  29. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/FieldData.java +41 -0
  30. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
  31. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
  32. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
  33. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +4 -2
  34. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPHeadersCompleteCallback.java +13 -0
  35. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +67 -52
  36. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +5 -0
  37. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParserUrl.java +76 -0
  38. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +323 -0
  39. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/{lolevel/Util.java → Util.java} +34 -35
  40. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPHeadersCompleteCallback.java +12 -0
  41. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +839 -587
  42. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +2 -1
  43. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +374 -0
  44. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/ParseUrl.java +51 -0
  45. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java +69 -0
  46. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java +52 -0
  47. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java +16 -0
  48. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java +48 -0
  49. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java +171 -446
  50. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java +62 -0
  51. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java +3 -1
  52. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java +27 -0
  53. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Url.java +127 -0
  54. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java +236 -0
  55. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java +59 -0
  56. data/ext/ruby_http_parser/vendor/http-parser-java/test.c +1318 -184
  57. data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +355 -49
  58. data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
  59. data/http_parser.rb.gemspec +10 -2
  60. data/lib/http_parser.rb +17 -0
  61. data/spec/parser_spec.rb +157 -23
  62. data/spec/support/requests.json +236 -24
  63. data/spec/support/responses.json +182 -36
  64. data/tasks/compile.rake +5 -3
  65. data/tasks/fixtures.rake +8 -2
  66. metadata +209 -127
  67. data/ext/ruby_http_parser/vendor/http-parser-java/CONTRIBUTIONS +0 -4
  68. data/ext/ruby_http_parser/vendor/http-parser-java/compile +0 -1
  69. data/ext/ruby_http_parser/vendor/http-parser-java/test_permutations +0 -1
  70. 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
- wrapper->request_path = Qnil;
49
- wrapper->query_string = Qnil;
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->request_path);
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
- VALUE val = rb_hash_aref(wrapper->headers, wrapper->last_field_name);
169
- if (val != Qnil) {
170
- rb_str_cat(val, ", ", 2);
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
- HASH_CAT(wrapper->headers, wrapper->last_field_name, at, length);
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
- if (argc == 1)
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
- // upgrade request
303
- } else if (nparsed != len) {
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 == 1 ? Qtrue : Qfalse;
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
- Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
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) $(OPT_DEBUG) http_parser_g.o test_g.o -o $@
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) $(OPT_DEBUG) -c test.c -o $@
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) $(OPT_DEBUG) -c http_parser.c -o $@
26
+ $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c http_parser.c -o $@
21
27
 
22
- test-valgrind: test_g
23
- valgrind ./test_g
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
- http_parser.o: http_parser.c http_parser.h Makefile
26
- $(CC) $(OPT_FAST) -c http_parser.c
31
+ test.o: test.c http_parser.h Makefile
32
+ $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@
27
33
 
28
- test_fast: http_parser.o test.c http_parser.h
29
- $(CC) $(OPT_FAST) http_parser.o test.c -o $@
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 path, query string, fragment
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) on_path, on_query_string, on_uri, on_fragment,
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