http_parser.rb 0.5.1-x86-mswin32-60 → 0.5.2-x86-mswin32-60

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 (47) hide show
  1. data/Gemfile.lock +16 -16
  2. data/LICENSE-MIT +20 -0
  3. data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +68 -11
  4. data/ext/ruby_http_parser/ruby_http_parser.c +74 -6
  5. data/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT +26 -1
  6. data/ext/ruby_http_parser/vendor/http-parser-java/README.md +23 -143
  7. data/ext/ruby_http_parser/vendor/http-parser-java/TODO +3 -0
  8. data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
  9. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +115 -61
  10. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +19 -3
  11. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
  12. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
  13. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
  14. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +4 -2
  15. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +64 -52
  16. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +5 -0
  17. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +323 -0
  18. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/{lolevel/Util.java → Util.java} +27 -28
  19. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +259 -85
  20. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +1 -0
  21. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +324 -0
  22. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java +69 -0
  23. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java +51 -0
  24. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java +15 -0
  25. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java +47 -0
  26. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java +183 -447
  27. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java +61 -0
  28. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java +2 -1
  29. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java +26 -0
  30. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java +165 -0
  31. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java +58 -0
  32. data/ext/ruby_http_parser/vendor/http-parser-java/test.c +232 -29
  33. data/ext/ruby_http_parser/vendor/http-parser-java/test_permutations +1 -1
  34. data/ext/ruby_http_parser/vendor/http-parser-java/test_unit +1 -1
  35. data/ext/ruby_http_parser/vendor/http-parser-java/test_utf8 +1 -0
  36. data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +154 -7
  37. data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
  38. data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +1 -1
  39. data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +52 -10
  40. data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +3 -1
  41. data/ext/ruby_http_parser/vendor/http-parser/test.c +89 -3
  42. data/http_parser.rb.gemspec +8 -2
  43. data/lib/http_parser.rb +17 -0
  44. data/spec/parser_spec.rb +97 -6
  45. data/tasks/compile.rake +3 -1
  46. metadata +83 -20
  47. data/ext/ruby_http_parser/vendor/http-parser-java/CONTRIBUTIONS +0 -4
@@ -33,6 +33,7 @@ public class ParserSettings {
33
33
  void call_on_error (HTTPParser p, String mes, ByteBuffer buf, int ini_pos) {
34
34
  if (null != on_error) {
35
35
  on_error.cb(p, mes, buf, ini_pos);
36
+ return;
36
37
  }
37
38
  // if on_error gets called it MUST throw an exception, else the parser
38
39
  // will attempt to continue parsing, which it can't because it's
@@ -0,0 +1,324 @@
1
+ package http_parser.lolevel;
2
+
3
+ import java.nio.*;
4
+ import java.io.*;
5
+ import java.util.*;
6
+
7
+ import http_parser.HTTPMethod;
8
+ import http_parser.ParserType;
9
+ import http_parser.lolevel.TestLoaderNG.TestSettings;
10
+ import http_parser.lolevel.TestLoaderNG.Header;
11
+ import http_parser.lolevel.TestLoaderNG.LastHeader;
12
+
13
+ import static http_parser.lolevel.Util.str;
14
+
15
+ public class Message {
16
+ String name;
17
+ byte [] raw;
18
+ ParserType type;
19
+ HTTPMethod method;
20
+ int status_code;
21
+ String request_path; // byte [] ?
22
+ String request_url;
23
+ String fragment ;
24
+ String query_string;
25
+ byte [] body;
26
+ int body_size;
27
+ int num_headers;
28
+ LastHeader last_header_element;
29
+ Map<String,String> header;
30
+ List<Header> headers;
31
+ boolean should_keep_alive;
32
+
33
+ boolean upgrade;
34
+
35
+ int http_major;
36
+ int http_minor;
37
+
38
+ boolean message_begin_called;
39
+ boolean headers_complete_called;
40
+ boolean message_complete_called;
41
+ boolean message_complete_on_eof;
42
+
43
+
44
+ Map<String,String> parsed_header;
45
+ String currHField;
46
+ String currHValue;
47
+ byte [] pbody;
48
+ int num_called;
49
+
50
+ public String toString() {
51
+ StringBuilder b = new StringBuilder();
52
+ b.append("type: "); b.append(type);b.append("\n");
53
+ b.append("method: "); b.append(method);b.append("\n");
54
+ b.append("status_code: "); b.append(status_code);b.append("\n");
55
+ b.append("request_path: "); b.append(request_path);b.append("\n");
56
+ b.append("request_url: "); b.append(request_url);b.append("\n");
57
+ b.append("fragment: "); b.append(fragment);b.append("\n");
58
+ b.append("query_string: "); b.append(query_string);b.append("\n");
59
+ b.append("body:\n"); b.append(new String(body));b.append("\n");
60
+ b.append("should_keep_alive: "); b.append(should_keep_alive);b.append("\n");
61
+ b.append("upgrade: "); b.append(upgrade);b.append("\n");
62
+ b.append("http_major: "); b.append(http_major);b.append("\n");
63
+ b.append("http_minor: "); b.append(http_minor);b.append("\n");
64
+ b.append("message_complete_called: "); b.append(message_complete_called);b.append("\n");
65
+ return b.toString();
66
+ }
67
+
68
+ Message () {
69
+ this.header = new HashMap<String, String>();
70
+ this.headers = new LinkedList<Header>();
71
+ reset();
72
+ }
73
+ /*
74
+ *prepare this Test Instance for reuse.
75
+ * */
76
+ void reset () {
77
+ this.parsed_header = new HashMap<String, String>();
78
+ this.pbody = null;
79
+ this.num_called = 0;
80
+
81
+ }
82
+ void check (boolean val, String mes) {
83
+ if (!val) {
84
+ //p(name+" : "+mes);
85
+ throw new RuntimeException(name+" : "+mes);
86
+ }
87
+ }
88
+
89
+
90
+ HTTPDataCallback getCB (final String value, final String mes, final TestSettings settings) {
91
+ return new HTTPDataCallback() {
92
+ public int cb (HTTPParser p, ByteBuffer b, int pos, int len){
93
+ // if ("url".equals(mes)){
94
+ // p("pos"+pos);
95
+ // p("len"+len);
96
+ // if (8==pos && 5 == len && "connect request".equals(name)) {
97
+ // //throw new RuntimeException(name);
98
+ // }
99
+ // }
100
+ String str = str(b, pos, len);
101
+ String prev_val = settings.map.get(mes);
102
+ settings.map.put(mes, prev_val + str);
103
+ //check(value.equals(str), "incorrect "+mes+": "+str);
104
+ if (-1 == pos) {
105
+ throw new RuntimeException("he?");
106
+ }
107
+ return 0;
108
+ }
109
+ };
110
+ }
111
+
112
+ void execute () {
113
+ p(name);
114
+ ByteBuffer buf = ByteBuffer.wrap(raw);
115
+ HTTPParser p = new HTTPParser();
116
+ TestSettings s = settings();
117
+
118
+
119
+
120
+ p.execute(s, buf);
121
+ if (!s.success) {
122
+ throw new RuntimeException("Test: "+name+"failed");
123
+ }
124
+ } // execute
125
+
126
+ void execute_permutations() {
127
+ /*
128
+ |-|---------------|
129
+ |--|--------------|
130
+ |---|-------------|
131
+ (...)
132
+ |---------------|-|
133
+ |-----------------|
134
+ */
135
+ p(name);
136
+ for (int i = 2; i != raw.length; ++i) {
137
+ // p(i);
138
+ HTTPParser p = new HTTPParser();
139
+ TestSettings s = settings();
140
+ ByteBuffer buf = ByteBuffer.wrap(raw);
141
+ int olimit = buf.limit();
142
+ buf.limit(i);
143
+
144
+ parse(p,s,buf);
145
+
146
+ buf.position(i);
147
+ buf.limit(olimit);
148
+
149
+ parse(p,s,buf);
150
+ parse(p,s,buf);
151
+
152
+ if (!s.success) {
153
+ p(this);
154
+ throw new RuntimeException("Test: "+name+" failed");
155
+ }
156
+ reset();
157
+ }
158
+ //System.exit(0);
159
+ } // execute_permutations
160
+ void parse(HTTPParser p, ParserSettings s, ByteBuffer b) {
161
+ //p("About to parse: "+b.position() + "->" + b.limit());
162
+ p.execute(s, b);
163
+ }
164
+
165
+ TestSettings settings() {
166
+ final TestSettings s = new TestSettings();
167
+ s.on_path = getCB(request_path, "path", s);
168
+ s.on_query_string = getCB(query_string, "query_string", s);
169
+ s.on_url = getCB(request_url, "url", s);
170
+ s.on_fragment = getCB(fragment, "fragment", s);
171
+ s.on_message_begin = new HTTPCallback() {
172
+ public int cb (HTTPParser p) {
173
+ message_begin_called = true;
174
+ return -1;
175
+ }
176
+ };
177
+ s.on_header_field = new HTTPDataCallback() {
178
+ public int cb (HTTPParser p, ByteBuffer b, int pos, int len){
179
+ if (null != currHValue && null == currHField) {
180
+ throw new RuntimeException(name+": shouldn't happen");
181
+ }
182
+ if (null != currHField) {
183
+ if (null == currHValue) {
184
+ currHField += str(b,pos,len);
185
+ return 0;
186
+ } else {
187
+ parsed_header.put(currHField, currHValue);
188
+ currHField = null;
189
+ currHValue = null;
190
+ }
191
+ }
192
+ currHField = str(b,pos,len);
193
+ return 0;
194
+ }
195
+ };
196
+ s.on_header_value = new HTTPDataCallback() {
197
+ public int cb (HTTPParser p, ByteBuffer b, int pos, int len){
198
+ if (null == currHField) {
199
+ throw new RuntimeException(name+" :shouldn't happen field");
200
+ }
201
+ if (null == currHValue) {
202
+ currHValue = str(b,pos,len);
203
+ } else {
204
+ currHValue += str(b, pos, len);
205
+ }
206
+ return 0;
207
+ }
208
+ };
209
+ s.on_headers_complete = new HTTPCallback() {
210
+ public int cb (HTTPParser p) {
211
+ headers_complete_called = true;
212
+ String parsed_path = s.map.get("path");
213
+ String parsed_query = s.map.get("query_string");
214
+ String parsed_url = s.map.get("url");
215
+ String parsed_frag = s.map.get("fragment");
216
+
217
+ if (!request_path.equals(parsed_path)) {
218
+ throw new RuntimeException(name+": invalid path: "+parsed_path+" should be: "+request_path);
219
+ }
220
+ if (!query_string.equals(parsed_query)) {
221
+ throw new RuntimeException(name+": invalid query: "+parsed_query+" should be: "+query_string);
222
+ }
223
+ if (!request_url.equals(parsed_url)) {
224
+ throw new RuntimeException(">"+name+"<: invalid url: >"+parsed_url+"< should be: >"+request_url+"<");
225
+ }
226
+ if (!fragment.equals(parsed_frag)) {
227
+ throw new RuntimeException(name+": invalid fragement: "+parsed_frag+" should be: "+fragment);
228
+ }
229
+ if (null != currHValue || null != currHField) {
230
+ if (null == currHField || null == currHValue) {
231
+ throw new RuntimeException("shouldn't happen");
232
+ }
233
+ }
234
+ if (null != currHField) {
235
+ //p(currHField);
236
+ //p(">"+currHValue+"<");
237
+ parsed_header.put(currHField, currHValue);
238
+ currHField = null;
239
+ currHValue = null;
240
+ }
241
+
242
+
243
+ return 0;
244
+ }
245
+ };
246
+ // s.on_headers_complete = new HTTPCallback() {
247
+ // public int cb (HTTPParser p) {
248
+ // p("Complete:"+name);
249
+ // return 0;
250
+ // }
251
+ // };
252
+
253
+ s.on_body = new HTTPDataCallback() {
254
+ public int cb (HTTPParser p, ByteBuffer b, int pos, int len){
255
+ int l = pbody == null ? len : len + pbody.length;
256
+ int off = pbody == null ? 0 : pbody.length;
257
+ byte [] nbody = new byte[l];
258
+
259
+ if (null != pbody) {
260
+ System.arraycopy(pbody, 0, nbody, 0, pbody.length);
261
+ }
262
+
263
+ int saved = b.position();
264
+ b.position(pos);
265
+ b.get(nbody, off, len);
266
+ b.position(saved);
267
+ pbody = nbody;
268
+ return 0;
269
+ }
270
+ };
271
+
272
+ s.on_message_complete = new HTTPCallback() {
273
+ public int cb(HTTPParser p) {
274
+ message_complete_called = true;
275
+ num_called += 1;
276
+ if ( p.http_minor != http_minor
277
+ || p.http_major != http_major
278
+ || p.status_code != status_code ) {
279
+
280
+ throw new RuntimeException("major/minor/status_code mismatch");
281
+ }
282
+
283
+ //check headers
284
+
285
+ if (header.keySet().size() != parsed_header.keySet().size()) {
286
+ p(parsed_header);
287
+ throw new RuntimeException(name+": different amount of headers");
288
+ }
289
+ for (String key : header.keySet()) {
290
+ String pvalue = parsed_header.get(key);
291
+ if (!header.get(key).equals(pvalue)) {
292
+ throw new RuntimeException(name+" : different values for :"+key+" is >"+pvalue+"< should: >"+header.get(key)+"<");
293
+ }
294
+ }
295
+ //check body
296
+ if (null == pbody && (null == body || body.length == 0 || body.length == 1)) {
297
+ s.success = true;
298
+ return 0;
299
+ }
300
+ if (null == pbody) {
301
+ throw new RuntimeException(name+": no body, should be: "+new String(body));
302
+ }
303
+ if (pbody.length != body.length) {
304
+ p(pbody.length);
305
+ p(body.length);
306
+ p(new String(pbody));
307
+ p(new String(body));
308
+ throw new RuntimeException(name+": incorrect body length");
309
+ }
310
+ for (int i = 0 ; i!= body.length; ++i) {
311
+ if (pbody[i] != body[i]) {
312
+ throw new RuntimeException("different body");
313
+ }
314
+ }
315
+ s.success = true;
316
+ return 0;
317
+ }
318
+ };
319
+ return s;
320
+ } // settings
321
+ static void p(Object o) {
322
+ System.out.println(o);
323
+ }
324
+ }
@@ -0,0 +1,69 @@
1
+ package http_parser.lolevel;
2
+
3
+ import java.nio.*;
4
+ import java.util.*;
5
+
6
+ import static http_parser.lolevel.Util.*;
7
+ import http_parser.*;
8
+
9
+ import primitive.collection.ByteList;
10
+
11
+ public class Requests {
12
+
13
+ static void test_simple(String req, boolean should_pass) {
14
+ HTTPParser parser = new HTTPParser(ParserType.HTTP_REQUEST);
15
+ ByteBuffer buf = buffer(req);
16
+ boolean passed = false;
17
+ int read = 0;
18
+ try {
19
+ parser.execute(Util.SETTINGS_NULL, buf);
20
+ passed = (read == req.length());
21
+ read = parser.execute(Util.SETTINGS_NULL, Util.empty());
22
+ passed &= (0 == read);
23
+ } catch (Throwable t) {
24
+ passed = false;
25
+ }
26
+ check(passed == should_pass);
27
+ }
28
+ static void simple_tests() {
29
+ test_simple("hello world", false);
30
+ test_simple("GET / HTP/1.1\r\n\r\n", false);
31
+
32
+ test_simple("ASDF / HTTP/1.1\r\n\r\n", false);
33
+ test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n", false);
34
+ test_simple("GETA / HTTP/1.1\r\n\r\n", false);
35
+ }
36
+
37
+ public static void test () {
38
+
39
+ simple_tests();
40
+
41
+ List<Message> all = TestLoaderNG.load("tests.dumped");
42
+ List<Message> requests = new LinkedList<Message>();
43
+ for (Message m : all) {
44
+ if (ParserType.HTTP_REQUEST == m.type) {
45
+ requests.add(m);
46
+ }
47
+ }
48
+ for (Message m : requests) {
49
+ test_message(m);
50
+ }
51
+
52
+ for (int i = 0; i!= requests.size(); ++i) {
53
+ if (!requests.get(i).should_keep_alive) continue;
54
+ for (int j = 0; j!=requests.size(); ++j) {
55
+ if (!requests.get(j).should_keep_alive) continue;
56
+ for (int k = 0; k!= requests.size(); ++k) {
57
+ test_multiple3(requests.get(i), requests.get(j), requests.get(k));
58
+ }
59
+ }
60
+ }
61
+
62
+ // postpone test_scan
63
+
64
+ }
65
+
66
+
67
+
68
+
69
+ }
@@ -0,0 +1,51 @@
1
+ package http_parser.lolevel;
2
+
3
+ import java.nio.*;
4
+ import java.util.*;
5
+
6
+ import static http_parser.lolevel.Util.*;
7
+ import http_parser.*;
8
+
9
+ import primitive.collection.ByteList;
10
+
11
+ public class Responses {
12
+
13
+
14
+
15
+ public static void test () {
16
+ List<Message> all = TestLoaderNG.load("tests.dumped");
17
+ List<Message> responses = new LinkedList<Message>();
18
+ for (Message m : all) {
19
+ if (ParserType.HTTP_RESPONSE == m.type) {
20
+ responses.add(m);
21
+ }
22
+ }
23
+ for (Message m : responses) {
24
+ test_message(m);
25
+ }
26
+
27
+ for (int i = 0; i!= responses.size(); ++i) {
28
+ if (!responses.get(i).should_keep_alive) continue;
29
+ for (int j = 0; j!=responses.size(); ++j) {
30
+ if (!responses.get(j).should_keep_alive) continue;
31
+ for (int k = 0; k!= responses.size(); ++k) {
32
+ test_multiple3(responses.get(i), responses.get(j), responses.get(k));
33
+ }
34
+ }
35
+ }
36
+
37
+ // not sure what test_message_count_body does that test_message doesn't...
38
+ // Message m = find(responses, "404 no headers no body");
39
+ // test_message_count_body(m);
40
+ // m = find(responses, "200 trailing space on chunked body");
41
+ // test_message_count_body(m);
42
+
43
+ // TODO test very large chunked response
44
+
45
+ // test_scan is more or less the same as test_permutations, will implement later...
46
+ }
47
+
48
+
49
+
50
+
51
+ }