midori_http_parser 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.gitmodules +6 -0
  4. data/.travis.yml +33 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE-MIT +20 -0
  7. data/README.md +90 -0
  8. data/Rakefile +6 -0
  9. data/bench/standalone.rb +23 -0
  10. data/bench/thin.rb +58 -0
  11. data/ext/ruby_http_parser/.gitignore +1 -0
  12. data/ext/ruby_http_parser/RubyHttpParserService.java +18 -0
  13. data/ext/ruby_http_parser/ext_help.h +18 -0
  14. data/ext/ruby_http_parser/extconf.rb +24 -0
  15. data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +495 -0
  16. data/ext/ruby_http_parser/ruby_http_parser.c +516 -0
  17. data/ext/ruby_http_parser/vendor/.gitkeep +0 -0
  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 +48 -0
  20. data/ext/ruby_http_parser/vendor/http-parser-java/README.md +183 -0
  21. data/ext/ruby_http_parser/vendor/http-parser-java/TODO +28 -0
  22. data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
  23. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +2175 -0
  24. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.gyp +79 -0
  25. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +304 -0
  26. data/ext/ruby_http_parser/vendor/http-parser-java/src/Http-parser.java.iml +22 -0
  27. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/FieldData.java +41 -0
  28. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
  29. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
  30. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
  31. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +9 -0
  32. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +113 -0
  33. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +36 -0
  34. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParserUrl.java +76 -0
  35. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +256 -0
  36. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserType.java +13 -0
  37. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/Util.java +111 -0
  38. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPCallback.java +5 -0
  39. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPDataCallback.java +25 -0
  40. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPErrorCallback.java +7 -0
  41. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +2171 -0
  42. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +83 -0
  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 +212 -0
  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 +117 -0
  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 +3425 -0
  57. data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +845 -0
  58. data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
  59. data/ext/ruby_http_parser/vendor/http-parser-java/tools/byte_constants.rb +6 -0
  60. data/ext/ruby_http_parser/vendor/http-parser-java/tools/const_char.rb +13 -0
  61. data/ext/ruby_http_parser/vendor/http-parser-java/tools/lowcase.rb +15 -0
  62. data/ext/ruby_http_parser/vendor/http-parser-java/tools/parse_tests.rb +33 -0
  63. data/ext/ruby_http_parser/vendor/http-parser/AUTHORS +68 -0
  64. data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +23 -0
  65. data/ext/ruby_http_parser/vendor/http-parser/README.md +246 -0
  66. data/ext/ruby_http_parser/vendor/http-parser/bench.c +111 -0
  67. data/ext/ruby_http_parser/vendor/http-parser/contrib/parsertrace.c +160 -0
  68. data/ext/ruby_http_parser/vendor/http-parser/contrib/url_parser.c +47 -0
  69. data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +2470 -0
  70. data/ext/ruby_http_parser/vendor/http-parser/http_parser.gyp +111 -0
  71. data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +432 -0
  72. data/ext/ruby_http_parser/vendor/http-parser/test.c +4226 -0
  73. data/ext/ruby_http_parser/vendor/http-parser/test_fast +0 -0
  74. data/ext/ruby_http_parser/vendor/http-parser/test_g +0 -0
  75. data/lib/http/parser.rb +1 -0
  76. data/lib/http_parser.rb +21 -0
  77. data/midori_http_parser.gemspec +24 -0
  78. data/spec/parser_spec.rb +376 -0
  79. data/spec/spec_helper.rb +1 -0
  80. data/spec/support/requests.json +631 -0
  81. data/spec/support/responses.json +375 -0
  82. data/tasks/compile.rake +42 -0
  83. data/tasks/fixtures.rake +71 -0
  84. data/tasks/spec.rake +5 -0
  85. data/tasks/submodules.rake +7 -0
  86. metadata +206 -0
@@ -0,0 +1,51 @@
1
+ package http_parser.lolevel;
2
+
3
+ import http_parser.HTTPParserUrl;
4
+ import static http_parser.lolevel.Util.*;
5
+
6
+ public class ParseUrl {
7
+ public static void test(int i) {
8
+ HTTPParserUrl u = new HTTPParserUrl();
9
+ HTTPParser p = new HTTPParser();
10
+ Url test = Url.URL_TESTS[i];
11
+ // System.out.println(":: " + test.name);
12
+ int rv = p.parse_url(Util.buffer(test.url),test.is_connect,u);
13
+ UnitTest.check_equals(rv, test.rv);
14
+ if(test.rv == 0){
15
+ UnitTest.check_equals(u, test.u);
16
+ }
17
+
18
+ }
19
+ public static void test() {
20
+ p(ParseUrl.class);
21
+
22
+ for (int i = 0; i < Url.URL_TESTS.length; i++) {
23
+ test(i);
24
+ }
25
+ }
26
+
27
+ static void usage() {
28
+ p("usage: [jre] http_parser.lolevel.ParseUrl [i]");
29
+ p(" i : optional test case id");
30
+ p("---------------------------------------------");
31
+ p("Test Cases:");
32
+ for (int i =0; i!= Url.URL_TESTS.length; ++i) {
33
+ p(" "+i+": "+Url.URL_TESTS[i].name);
34
+ }
35
+ }
36
+
37
+ public static void main (String [] args) {
38
+ if (0 == args.length) {
39
+ test();
40
+ } else {
41
+ try {
42
+ int i = Integer.parseInt(args[0]);
43
+ test(i);
44
+ } catch (Throwable t) {
45
+ t.printStackTrace();
46
+ usage();
47
+ }
48
+
49
+ }
50
+ }
51
+ }
@@ -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
+ p(Requests.class);
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,52 @@
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
+ p(Responses.class);
17
+ List<Message> all = TestLoaderNG.load("tests.dumped");
18
+ List<Message> responses = new LinkedList<Message>();
19
+ for (Message m : all) {
20
+ if (ParserType.HTTP_RESPONSE == m.type) {
21
+ responses.add(m);
22
+ }
23
+ }
24
+ for (Message m : responses) {
25
+ test_message(m);
26
+ }
27
+
28
+ for (int i = 0; i!= responses.size(); ++i) {
29
+ if (!responses.get(i).should_keep_alive) continue;
30
+ for (int j = 0; j!=responses.size(); ++j) {
31
+ if (!responses.get(j).should_keep_alive) continue;
32
+ for (int k = 0; k!= responses.size(); ++k) {
33
+ test_multiple3(responses.get(i), responses.get(j), responses.get(k));
34
+ }
35
+ }
36
+ }
37
+
38
+ // not sure what test_message_count_body does that test_message doesn't...
39
+ // Message m = find(responses, "404 no headers no body");
40
+ // test_message_count_body(m);
41
+ // m = find(responses, "200 trailing space on chunked body");
42
+ // test_message_count_body(m);
43
+
44
+ // TODO test very large chunked response
45
+
46
+ // test_scan is more or less the same as test_permutations, will implement later...
47
+ }
48
+
49
+
50
+
51
+
52
+ }
@@ -0,0 +1,16 @@
1
+ package http_parser.lolevel;
2
+
3
+
4
+ public class Test {
5
+ public static void main (String [] args) {
6
+ UnitTest.test();
7
+ TestHeaderOverflowError.test();
8
+ TestNoOverflowLongBody.test();
9
+ Responses.test();
10
+ ParseUrl.test();
11
+ Requests.test();
12
+ Upgrade.test();
13
+ WrongContentLength.test();
14
+ }
15
+
16
+ }
@@ -0,0 +1,48 @@
1
+ package http_parser.lolevel;
2
+
3
+ import java.nio.*;
4
+
5
+ import static http_parser.lolevel.Util.*;
6
+
7
+ public class TestHeaderOverflowError {
8
+
9
+ public static void test (http_parser.ParserType type) {
10
+ HTTPParser parser = new HTTPParser(type);
11
+ ByteBuffer buf = getBytes(type);
12
+
13
+ int numbytes = buf.limit();
14
+
15
+ parser.execute(Util.SETTINGS_NULL, buf);
16
+
17
+ check(numbytes == buf.position());
18
+
19
+ buf = buffer("header-key: header-value\r\n");
20
+ numbytes = buf.limit();
21
+ for (int i = 0; i!= 1000; ++i) {
22
+ parser.execute(Util.SETTINGS_NULL, buf);
23
+ check(numbytes == buf.position());
24
+
25
+ buf.rewind();
26
+
27
+ }
28
+ }
29
+
30
+ static ByteBuffer getBytes (http_parser.ParserType type) {
31
+ if (http_parser.ParserType.HTTP_BOTH == type) {
32
+ throw new RuntimeException("only HTTP_REQUEST and HTTP_RESPONSE");
33
+ }
34
+
35
+ if (http_parser.ParserType.HTTP_REQUEST == type) {
36
+ return buffer("GET / HTTP/1.1\r\n");
37
+ }
38
+ return buffer("HTTP/1.0 200 OK\r\n");
39
+ }
40
+
41
+ public static void test () {
42
+ p(TestHeaderOverflowError.class);
43
+ test(http_parser.ParserType.HTTP_REQUEST);
44
+ test(http_parser.ParserType.HTTP_RESPONSE);
45
+ }
46
+
47
+
48
+ }
@@ -0,0 +1,212 @@
1
+ package http_parser.lolevel;
2
+ // name : 200 trailing space on chunked body
3
+ // raw : "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n\r\n25 \r\nThis is the data in the first chunk\r\n\r\n1C\r\nand this is the second one\r\n\r\n0 \r\n\r\n"
4
+ // type : HTTP_RESPONSE
5
+ // method: HTTP_DELETE
6
+ // status code :200
7
+ // request_path:
8
+ // request_url :
9
+ // fragment :
10
+ // query_string:
11
+ // body :"This is the data in the first chunk\r\nand this is the second one\r\n"
12
+ // body_size :65
13
+ // header_0 :{ "Content-Type": "text/plain"}
14
+ // header_1 :{ "Transfer-Encoding": "chunked"}
15
+ // should_keep_alive :1
16
+ // upgrade :0
17
+ // http_major :1
18
+ // http_minor :1
19
+
20
+
21
+ import java.io.FileReader;
22
+ import java.io.BufferedReader;
23
+ import java.io.StringReader;
24
+ import java.io.Reader;
25
+ import java.io.Reader;
26
+ import java.io.IOException;
27
+
28
+ import java.util.*;
29
+ import java.util.regex.*;
30
+
31
+ import java.nio.ByteBuffer;
32
+
33
+ import http_parser.HTTPMethod;
34
+ import http_parser.ParserType;
35
+
36
+ public class TestLoaderNG {
37
+ String fn;
38
+ public TestLoaderNG(String filename) {
39
+ this.fn = filename;
40
+ }
41
+ static void p(Object o) {
42
+ System.out.println(o);
43
+ }
44
+ public static List<Message> load (String fn) {
45
+ List<Message> list = null;
46
+ try {
47
+ BufferedReader buf = new BufferedReader(new FileReader(fn));
48
+ list = load(buf);
49
+ } catch (Throwable t) {
50
+ throw new RuntimeException(t);
51
+ }
52
+ return list;
53
+
54
+ }
55
+ public static Message parse (String message) {
56
+ List<Message> list = load(new BufferedReader(new StringReader(message)));
57
+ if (null == list || 0 == list.size() ) {
58
+ return null;
59
+ }
60
+ return list.get(0);
61
+ }
62
+
63
+ public static List<Message> load (BufferedReader buf) {
64
+ List<Message> list = new LinkedList<Message>();
65
+ String line = null;
66
+ Message curr = new Message();
67
+ Pattern pattern = Pattern.compile("(\\S+)\\s*:(.*)");
68
+ try {
69
+ while (null != (line = buf.readLine()) ){
70
+ if ("".equals(line.trim())) {
71
+ list.add (curr);
72
+ curr = new Message();
73
+ continue;
74
+ }
75
+ Matcher m = pattern.matcher(line);
76
+ if (m.matches()) {
77
+ // you can not be fucking serious!?
78
+ // this has got to be the most retarded regex
79
+ // interface in the history of the world ...
80
+ // (though I'm sure there's worse c++ regexp libs...)
81
+ MatchResult r = m.toMatchResult();
82
+ String key = r.group(1).trim();
83
+ String value = r.group(2).trim();
84
+ if ("name".equals(key)) {curr.name = value;}
85
+ else if ("raw".equals(key)) {curr.raw = toByteArray(value);} //!
86
+ else if ("type".equals(key)) {curr.type = ParserType.parse(value);}
87
+ else if ("method".equals(key)) {curr.method = HTTPMethod.parse(value);}
88
+ else if ("status_code".equals(key)) {curr.status_code = Integer.parseInt(value);}
89
+ else if ("request_path".equals(key)) {curr.request_path = value;}
90
+ else if ("request_url".equals(key)) {curr.request_url = value;}
91
+
92
+ else if ("fragment".equals(key)) {curr.fragment = value;}
93
+ else if ("query_string".equals(key)) {curr.query_string = value;}
94
+ else if ("body".equals(key)) {curr.body = toByteArray(value);} //!
95
+ else if ("body_size".equals(key)) {curr.body_size = Integer.parseInt(value);}
96
+ else if (key.startsWith("header")) {
97
+ String [] h = getHeader(value);
98
+ curr.header.put(h[0], h[1]);
99
+ }
100
+ else if ("should_keep_alive".equals(key))
101
+ {curr.should_keep_alive = (1 == Integer.parseInt(value));}
102
+ else if ("upgrade".equals(key)) { curr.upgrade = toByteArray(value);}
103
+ else if ("http_major".equals(key)) {curr.http_major = Integer.parseInt(value);}
104
+ else if ("http_minor".equals(key)) {curr.http_minor = Integer.parseInt(value);}
105
+ } else {
106
+ p("WTF?"+line);
107
+ }
108
+
109
+ }
110
+ } catch (Throwable t) {
111
+ throw new RuntimeException(t);
112
+ }
113
+ return list;
114
+ }
115
+
116
+ static String [] getHeader(String value) {
117
+ // { "Host": "0.0.0.0=5000"}
118
+ Pattern p = Pattern.compile("\\{ ?\"([^\"]*)\": ?\"(.*)\"}");
119
+ Matcher m = p.matcher(value);
120
+ if (!m.matches()) {
121
+ p(value);
122
+ throw new RuntimeException("something wrong");
123
+ }
124
+ String [] result = new String[2];
125
+ MatchResult r = m.toMatchResult();
126
+ result[0] = r.group(1).trim();
127
+ result[1] = r.group(2); //.trim();
128
+ return result;
129
+ }
130
+
131
+ static final byte BSLASH = 0x5c;
132
+ static final byte QUOT = 0x22;
133
+ static final byte CR = 0x0d;
134
+ static final byte LF = 0x0a;
135
+ static final byte n = 0x6e;
136
+ static final byte r = 0x72;
137
+
138
+ static final Byte[] JAVA_GENERICS_ROCK_HARD = new Byte[0];
139
+
140
+
141
+ static byte [] toByteArray (String quotedString) {
142
+ ArrayList<Byte> bytes = new ArrayList<Byte>();
143
+ String s = quotedString.substring(1, quotedString.length()-1);
144
+ byte [] byts = s.getBytes(java.nio.charset.Charset.forName("UTF8"));
145
+ boolean escaped = false;
146
+ for (byte b : byts) {
147
+ switch (b) {
148
+ case BSLASH:
149
+ escaped = true;
150
+ break;
151
+ case n:
152
+ if (escaped) {
153
+ bytes.add(LF);
154
+ escaped = false;
155
+ } else {
156
+ bytes.add(b);
157
+ }
158
+ break;
159
+ case r:
160
+ if (escaped) {
161
+ escaped = false;
162
+ bytes.add(CR);
163
+ } else {
164
+ bytes.add(b);
165
+ }
166
+ break;
167
+ case QUOT:
168
+ escaped = false;
169
+ bytes.add(QUOT);
170
+ break;
171
+ default:
172
+ bytes.add(b);
173
+ }
174
+
175
+ }
176
+
177
+ byts = new byte[bytes.size()];
178
+ int i = 0;
179
+ for (Byte b : bytes) {
180
+ byts[i++]=b;
181
+ }
182
+ return byts;
183
+ }
184
+
185
+ public static void main(String [] args) throws Throwable {
186
+ //TestLoaderNG l = new TestLoaderNG(args[0]);
187
+ List<Message> ts = load(args[0]);
188
+ for (Message t : ts) {
189
+ // for (int i =0; i!= t.raw.length; ++i) {
190
+ // p(i+":"+t.raw[i]);
191
+ // }
192
+ // try {
193
+ t.execute_permutations();
194
+ // } catch (Throwable th) {
195
+ // p("failed: "+t.name);
196
+ // }
197
+ t.execute();
198
+ // System.exit(0);
199
+ }
200
+ }
201
+
202
+ class Header {
203
+ String field;
204
+ String value;
205
+ }
206
+ enum LastHeader {
207
+ NONE
208
+ ,FIELD
209
+ ,VALUE
210
+ }
211
+
212
+ }