http-parser-lite 0.2.0 → 0.3.0

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/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.3.0 (2012-06-27)
2
+
3
+ * Added optional type argument to Parser#initialize and Parser#reset
4
+ * Added Parser#error? and Parser#error
5
+
1
6
  == 0.2.0 (2012-06-25)
2
7
 
3
8
  * Added Parser#pause, Parser#resume and Parser#paused?
data/README.md CHANGED
@@ -52,10 +52,9 @@ parser << "GET http://www.google.com/ HTTP/1.1\r\n\r\n"
52
52
 
53
53
  ```
54
54
  HTTP::Parser
55
- .new
56
-
57
- #reset
55
+ .new(type = HTTP::Parser::TYPE_BOTH)
58
56
 
57
+ #reset(type = nil)
59
58
  #parse(data)
60
59
  #<<(data)
61
60
 
@@ -73,6 +72,19 @@ HTTP::Parser
73
72
  #pause
74
73
  #resume
75
74
  #paused?
75
+
76
+ #error?
77
+ #error
78
+
79
+ Constants:
80
+
81
+ * HTTP::Parser::TYPE_REQUEST
82
+ * HTTP::Parser::TYPE_RESPONSE
83
+ * HTTP::Parser::TYPE_BOTH
84
+
85
+ Exceptions:
86
+
87
+ * HTTP::Parser::Error
76
88
  ```
77
89
 
78
90
  ## License
@@ -25,17 +25,13 @@ http_parser* rb_http_parser_handle(VALUE self) {
25
25
  return parser;
26
26
  }
27
27
 
28
- VALUE rb_parser_callback_for(VALUE self, VALUE name) {
29
- return rb_hash_aref(rb_iv_get(self, "@callbacks"), name);
30
- }
31
-
32
28
  void rb_parser_callback_call(VALUE self, const char *name, char *data, size_t length) {
33
- VALUE func = rb_parser_callback_for(self, ID2SYM(rb_intern(name)));
34
- if (!NIL_P(func)) {
29
+ VALUE callback = rb_hash_aref(rb_iv_get(self, "@callbacks"), ID2SYM(rb_intern(name)));
30
+ if (!NIL_P(callback)) {
35
31
  VALUE args = rb_ary_new();
36
32
  if (data)
37
33
  rb_ary_push(args, rb_str_new(data, length));
38
- rb_proc_call(func, args);
34
+ rb_proc_call(callback, args);
39
35
  }
40
36
  }
41
37
 
@@ -92,9 +88,9 @@ VALUE rb_parser_parse(VALUE self, VALUE data) {
92
88
  return Qtrue;
93
89
  }
94
90
 
95
- VALUE rb_parser_reset(VALUE self) {
91
+ VALUE rb_parser_reset_bang(VALUE self, VALUE type) {
96
92
  http_parser *parser = rb_http_parser_handle(self);
97
- http_parser_init(parser, HTTP_BOTH);
93
+ http_parser_init(parser, FIX2INT(type));
98
94
  return Qtrue;
99
95
  }
100
96
 
@@ -132,6 +128,17 @@ VALUE rb_parser_http_status(VALUE self) {
132
128
  return INT2NUM(parser->status_code);
133
129
  }
134
130
 
131
+ VALUE rb_parser_error_q(VALUE self) {
132
+ http_parser *parser = rb_http_parser_handle(self);
133
+ return HTTP_PARSER_ERRNO(parser) != HPE_OK ? Qtrue : Qfalse;
134
+ }
135
+
136
+ VALUE rb_parser_error(VALUE self) {
137
+ http_parser *parser = rb_http_parser_handle(self);
138
+ int errno = HTTP_PARSER_ERRNO(parser);
139
+ return errno != HPE_OK ? rb_str_new2(http_errno_description(errno)) : Qnil;
140
+ }
141
+
135
142
  Init_http_parser() {
136
143
  mHTTP = rb_define_module("HTTP");
137
144
  cParser = rb_define_class_under(mHTTP, "Parser", rb_cObject);
@@ -144,8 +151,11 @@ Init_http_parser() {
144
151
  rb_define_method(cParser, "pause", rb_parser_pause, 0);
145
152
  rb_define_method(cParser, "resume", rb_parser_resume, 0);
146
153
  rb_define_method(cParser, "paused?", rb_parser_is_paused, 0);
147
- rb_define_method(cParser, "reset", rb_parser_reset, 0);
154
+ rb_define_method(cParser, "error?", rb_parser_error_q, 0);
155
+ rb_define_method(cParser, "error", rb_parser_error, 0);
148
156
  rb_define_method(cParser, "http_method", rb_parser_http_method, 0);
149
157
  rb_define_method(cParser, "http_version", rb_parser_http_version, 0);
150
158
  rb_define_method(cParser, "http_status", rb_parser_http_status, 0);
159
+
160
+ rb_define_private_method(cParser, "reset!", rb_parser_reset_bang, 1);
151
161
  }
data/lib/http-parser.rb CHANGED
@@ -2,7 +2,10 @@ require 'http-parser/http_parser'
2
2
 
3
3
  module HTTP
4
4
  class Parser
5
- CALLBACKS = %w(on_url on_header_field on_header_value on_body on_message_begin on_message_complete)
5
+ TYPE_REQUEST = 0
6
+ TYPE_RESPONSE = 1
7
+ TYPE_BOTH = 2
8
+ CALLBACKS = %w(on_url on_header_field on_header_value on_body on_message_begin on_message_complete)
6
9
 
7
10
  CALLBACKS.each do |name|
8
11
  define_method(name) do |&block|
@@ -11,8 +14,20 @@ module HTTP
11
14
  end
12
15
  end
13
16
 
14
- def initialize
17
+ attr_reader :type
18
+
19
+ def initialize type = TYPE_BOTH
15
20
  @callbacks = {}
21
+ reset(type)
22
+ end
23
+
24
+ def reset value = nil
25
+ if value
26
+ raise ArgumentError, "Invalid parser type #{value}" unless [0, 1, 2].include?(value)
27
+ @type = value
28
+ end
29
+
30
+ reset!(@type)
16
31
  end
17
32
  end
18
33
  end
@@ -106,4 +106,51 @@ describe 'http-parser' do
106
106
 
107
107
  assert %w(/hello X-Test-Field 1), got
108
108
  end
109
+
110
+ it 'should create parser of appropriate type' do
111
+ parser = HTTP::Parser.new(HTTP::Parser::TYPE_REQUEST)
112
+ assert parser << "GET /hello HTTP/1.1\r\n\r\n"
113
+ assert_raises(HTTP::Parser::Error) do
114
+ parser << "HTTP/1.1 200 OK\r\n\r\n"
115
+ end
116
+ end
117
+
118
+ it 'should be able to reset parser to another type' do
119
+ parser.reset(HTTP::Parser::TYPE_RESPONSE)
120
+ assert parser << "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"
121
+ assert_raises(HTTP::Parser::Error) do
122
+ parser << "GET / HTTP/1.1\r\n\r\n"
123
+ end
124
+
125
+ parser.reset(HTTP::Parser::TYPE_REQUEST)
126
+ assert parser << "GET / HTTP/1.1\r\n\r\n"
127
+ end
128
+
129
+ it '#reset should validate parser type' do
130
+ assert_raises(ArgumentError) do
131
+ parser.reset("foo")
132
+ end
133
+ assert_raises(ArgumentError) do
134
+ parser.reset(4)
135
+ end
136
+ assert parser.reset(0)
137
+ end
138
+
139
+ it 'should expose parser error status' do
140
+ parser.reset(HTTP::Parser::TYPE_REQUEST)
141
+
142
+ assert parser << "GET / HTTP/1.1\r\n\r\n"
143
+ assert !parser.error?
144
+
145
+ assert_raises(HTTP::Parser::Error) do
146
+ parser << "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"
147
+ end
148
+ assert parser.error?
149
+ assert_match %r{invalid http method}i, parser.error
150
+
151
+ # reset should give you a clean slate
152
+ parser.reset(HTTP::Parser::TYPE_REQUEST)
153
+ assert !parser.error?
154
+ assert !parser.error
155
+ end
109
156
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-parser-lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-25 00:00:00.000000000 Z
12
+ date: 2012-06-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake