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

Sign up to get free protection for your applications and to get access to all the features.
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
+ }