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.
- data/.gitmodules +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +11 -4
- data/LICENSE-MIT +20 -0
- data/README.md +51 -46
- data/bench/standalone.rb +23 -0
- data/bench/thin.rb +1 -0
- data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +121 -56
- data/ext/ruby_http_parser/ruby_http_parser.c +89 -48
- data/ext/ruby_http_parser/vendor/http-parser/AUTHORS +32 -0
- data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +5 -1
- data/ext/ruby_http_parser/vendor/http-parser/Makefile +34 -17
- data/ext/ruby_http_parser/vendor/http-parser/README.md +9 -2
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +1045 -589
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.gyp +79 -0
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +148 -17
- data/ext/ruby_http_parser/vendor/http-parser/test.c +1138 -128
- data/ext/ruby_http_parser/vendor/http-parser-java/AUTHORS +32 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT +30 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/Makefile +34 -17
- data/ext/ruby_http_parser/vendor/http-parser-java/README.md +30 -18
- data/ext/ruby_http_parser/vendor/http-parser-java/TODO +9 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/ext/primitives.jar +0 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +1075 -607
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.gyp +79 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +190 -40
- data/ext/ruby_http_parser/vendor/http-parser-java/src/Http-parser.java.iml +22 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/FieldData.java +41 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +4 -2
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPHeadersCompleteCallback.java +13 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +67 -52
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +5 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParserUrl.java +76 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +323 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/{lolevel/Util.java → Util.java} +34 -35
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPHeadersCompleteCallback.java +12 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +839 -587
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +2 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +374 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/ParseUrl.java +51 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java +69 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java +52 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java +16 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java +48 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java +171 -446
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java +62 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java +3 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java +27 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Url.java +127 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java +236 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java +59 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/test.c +1318 -184
- data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +355 -49
- data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
- data/http_parser.rb.gemspec +10 -2
- data/lib/http_parser.rb +17 -0
- data/spec/parser_spec.rb +157 -23
- data/spec/support/requests.json +236 -24
- data/spec/support/responses.json +182 -36
- data/tasks/compile.rake +5 -3
- data/tasks/fixtures.rake +8 -2
- metadata +209 -127
- data/ext/ruby_http_parser/vendor/http-parser-java/CONTRIBUTIONS +0 -4
- data/ext/ruby_http_parser/vendor/http-parser-java/compile +0 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test_permutations +0 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test_unit +0 -1
data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java
CHANGED
|
@@ -2,6 +2,7 @@ package http_parser.lolevel;
|
|
|
2
2
|
|
|
3
3
|
import java.nio.ByteBuffer;
|
|
4
4
|
import http_parser.HTTPException;
|
|
5
|
+
import http_parser.Util;
|
|
5
6
|
|
|
6
7
|
public class UnitTest {
|
|
7
8
|
|
|
@@ -108,7 +109,8 @@ public class UnitTest {
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
|
|
111
|
-
public static void
|
|
112
|
+
public static void test () {
|
|
113
|
+
p(UnitTest.class);
|
|
112
114
|
testErrorFormat();
|
|
113
115
|
testErrorCallback();
|
|
114
116
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package http_parser.lolevel;
|
|
2
|
+
|
|
3
|
+
import java.nio.*;
|
|
4
|
+
import java.util.*;
|
|
5
|
+
|
|
6
|
+
import http_parser.ParserType;
|
|
7
|
+
|
|
8
|
+
import static http_parser.lolevel.Util.*;
|
|
9
|
+
|
|
10
|
+
public class Upgrade {
|
|
11
|
+
static final String upgrade = "GET /demo HTTP/1.1\r\n" +
|
|
12
|
+
"Connection: Upgrade\r\n" +
|
|
13
|
+
"Upgrade: WebSocket\r\n\r\n" +
|
|
14
|
+
"third key data";
|
|
15
|
+
static void test () {
|
|
16
|
+
p(Upgrade.class);
|
|
17
|
+
HTTPParser parser = new HTTPParser(ParserType.HTTP_REQUEST);
|
|
18
|
+
ByteBuffer buf = buffer(upgrade);
|
|
19
|
+
|
|
20
|
+
int read = parser.execute(Util.SETTINGS_NULL, buf);
|
|
21
|
+
check (63 == read);
|
|
22
|
+
String s = str(buf);
|
|
23
|
+
check ("third key data".equals(str(buf)));
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
package http_parser.lolevel;
|
|
2
|
+
|
|
3
|
+
import http_parser.FieldData;
|
|
4
|
+
import http_parser.HTTPParserUrl;
|
|
5
|
+
|
|
6
|
+
import static http_parser.HTTPParserUrl.*;
|
|
7
|
+
import static http_parser.lolevel.HTTPParser.*;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*/
|
|
11
|
+
public class Url {
|
|
12
|
+
|
|
13
|
+
public static Url[] URL_TESTS = new Url[]{
|
|
14
|
+
new Url("proxy request", "http://hostname/", false,
|
|
15
|
+
new HTTPParserUrl(
|
|
16
|
+
(1 << UrlFields.UF_SCHEMA.getIndex()) | (1 << UrlFields.UF_HOST.getIndex()) | (1 << UrlFields.UF_PATH.getIndex()),
|
|
17
|
+
0,
|
|
18
|
+
new FieldData[]{
|
|
19
|
+
new FieldData(0,4),
|
|
20
|
+
new FieldData(7,8),
|
|
21
|
+
new FieldData(0,0),
|
|
22
|
+
new FieldData(15,1),
|
|
23
|
+
new FieldData(0,0),
|
|
24
|
+
new FieldData(0,0)
|
|
25
|
+
}),
|
|
26
|
+
0),
|
|
27
|
+
new Url("CONNECT request", "hostname:443", true,
|
|
28
|
+
new HTTPParserUrl(
|
|
29
|
+
(1 << UrlFields.UF_HOST.getIndex()) | (1 << UrlFields.UF_PORT.getIndex()),
|
|
30
|
+
443,
|
|
31
|
+
new FieldData[]{
|
|
32
|
+
new FieldData(0,0),
|
|
33
|
+
new FieldData(0,8),
|
|
34
|
+
new FieldData(9,3),
|
|
35
|
+
new FieldData(0,0),
|
|
36
|
+
new FieldData(0,0),
|
|
37
|
+
new FieldData(0,0)
|
|
38
|
+
}),
|
|
39
|
+
0),
|
|
40
|
+
new Url("proxy ipv6 request", "http://[1:2::3:4]/", false,
|
|
41
|
+
new HTTPParserUrl(
|
|
42
|
+
(1 << UrlFields.UF_SCHEMA.getIndex()) | (1 << UrlFields.UF_HOST.getIndex()) | (1 << UrlFields.UF_PATH.getIndex()),
|
|
43
|
+
0,
|
|
44
|
+
new FieldData[]{
|
|
45
|
+
new FieldData(0,4),
|
|
46
|
+
new FieldData(8,8),
|
|
47
|
+
new FieldData(0,0),
|
|
48
|
+
new FieldData(17,1),
|
|
49
|
+
new FieldData(0,0),
|
|
50
|
+
new FieldData(0,0)
|
|
51
|
+
}),
|
|
52
|
+
0),
|
|
53
|
+
new Url("CONNECT ipv6 address", "[1:2::3:4]:443", true,
|
|
54
|
+
new HTTPParserUrl(
|
|
55
|
+
(1 << UrlFields.UF_HOST.getIndex()) | (1 << UrlFields.UF_PORT.getIndex()),
|
|
56
|
+
443,
|
|
57
|
+
new FieldData[]{
|
|
58
|
+
new FieldData(0,0),
|
|
59
|
+
new FieldData(1,8),
|
|
60
|
+
new FieldData(11,3),
|
|
61
|
+
new FieldData(0,0),
|
|
62
|
+
new FieldData(0,0),
|
|
63
|
+
new FieldData(0,0)
|
|
64
|
+
}),
|
|
65
|
+
0),
|
|
66
|
+
new Url("extra ? in query string",
|
|
67
|
+
"http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css",
|
|
68
|
+
false,
|
|
69
|
+
new HTTPParserUrl(
|
|
70
|
+
(1 << UrlFields.UF_SCHEMA.getIndex()) |
|
|
71
|
+
(1 << UrlFields.UF_HOST.getIndex()) |
|
|
72
|
+
(1 << UrlFields.UF_PATH.getIndex()) |
|
|
73
|
+
(1 << UrlFields.UF_QUERY.getIndex()),
|
|
74
|
+
0,
|
|
75
|
+
new FieldData[]{
|
|
76
|
+
new FieldData(0,4),
|
|
77
|
+
new FieldData(7,10),
|
|
78
|
+
new FieldData(0,0),
|
|
79
|
+
new FieldData(17,12),
|
|
80
|
+
new FieldData(30,187),
|
|
81
|
+
new FieldData(0,0)
|
|
82
|
+
}),
|
|
83
|
+
0),
|
|
84
|
+
new Url("proxy empty host",
|
|
85
|
+
"http://:443/",
|
|
86
|
+
false,
|
|
87
|
+
null,
|
|
88
|
+
1),
|
|
89
|
+
new Url("proxy empty port",
|
|
90
|
+
"http://hostname:/",
|
|
91
|
+
false,
|
|
92
|
+
null,
|
|
93
|
+
1),
|
|
94
|
+
new Url("CONNECT empty host",
|
|
95
|
+
":443",
|
|
96
|
+
true,
|
|
97
|
+
null,
|
|
98
|
+
1),
|
|
99
|
+
new Url("CONNECT empty port",
|
|
100
|
+
"hostname:",
|
|
101
|
+
true,
|
|
102
|
+
null,
|
|
103
|
+
1),
|
|
104
|
+
new Url("CONNECT with extra bits",
|
|
105
|
+
"hostname:443/",
|
|
106
|
+
true,
|
|
107
|
+
null,
|
|
108
|
+
1),
|
|
109
|
+
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
String name;
|
|
113
|
+
String url;
|
|
114
|
+
boolean is_connect;
|
|
115
|
+
HTTPParserUrl u;
|
|
116
|
+
int rv;
|
|
117
|
+
|
|
118
|
+
public Url(String name, String url, boolean is_connect, HTTPParserUrl u, int rv) {
|
|
119
|
+
this.name = name;
|
|
120
|
+
this.url = url;
|
|
121
|
+
this.is_connect = is_connect;
|
|
122
|
+
this.u = u;
|
|
123
|
+
this.rv = rv;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
package http_parser.lolevel;
|
|
2
|
+
|
|
3
|
+
import java.nio.*;
|
|
4
|
+
import java.util.*;
|
|
5
|
+
|
|
6
|
+
import primitive.collection.ByteList;
|
|
7
|
+
|
|
8
|
+
import http_parser.*;
|
|
9
|
+
|
|
10
|
+
public class Util {
|
|
11
|
+
|
|
12
|
+
static final ParserSettings SETTINGS_NULL = new ParserSettings();
|
|
13
|
+
|
|
14
|
+
static String str (ByteBuffer b, int pos, int len) {
|
|
15
|
+
byte [] by = new byte[len];
|
|
16
|
+
int saved = b.position();
|
|
17
|
+
b.position(pos);
|
|
18
|
+
b.get(by);
|
|
19
|
+
b.position(saved);
|
|
20
|
+
return new String(by);
|
|
21
|
+
}
|
|
22
|
+
static String str (ByteBuffer b) {
|
|
23
|
+
int len = b.limit() - b.position();
|
|
24
|
+
byte [] by = new byte[len];
|
|
25
|
+
int saved = b.position();
|
|
26
|
+
b.get(by);
|
|
27
|
+
b.position(saved);
|
|
28
|
+
return new String(by);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static ByteBuffer buffer(String str) {
|
|
32
|
+
return ByteBuffer.wrap(str.getBytes());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static ByteBuffer empty() {
|
|
36
|
+
return ByteBuffer.wrap(new byte[0]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static void check(boolean betterBtrue) {
|
|
40
|
+
if (!betterBtrue) {
|
|
41
|
+
throw new RuntimeException("!");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
static void check (int should, int is) {
|
|
45
|
+
if (should != is) {
|
|
46
|
+
throw new RuntimeException("should be: "+should+" is:"+is);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static void test_message(Message mes) {
|
|
51
|
+
int raw_len = mes.raw.length;
|
|
52
|
+
for (int msg1len = 0; msg1len != raw_len; ++msg1len) {
|
|
53
|
+
mes.reset();
|
|
54
|
+
ByteBuffer msg1 = ByteBuffer.wrap(mes.raw, 0, msg1len);
|
|
55
|
+
ByteBuffer msg2 = ByteBuffer.wrap(mes.raw, msg1len, mes.raw.length - msg1len);
|
|
56
|
+
|
|
57
|
+
HTTPParser parser = new HTTPParser(mes.type);
|
|
58
|
+
ParserSettings settings = mes.settings();
|
|
59
|
+
|
|
60
|
+
int read = 0;
|
|
61
|
+
if (msg1len !=0) {
|
|
62
|
+
read = parser.execute(settings, msg1);
|
|
63
|
+
if (mes.upgrade() && parser.upgrade) {
|
|
64
|
+
// Messages have a settings() that checks itself...
|
|
65
|
+
check(1 == mes.num_called);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
check(read == msg1len);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
read = parser.execute(settings, msg2);
|
|
72
|
+
if (mes.upgrade() && parser.upgrade) {
|
|
73
|
+
check(1 == mes.num_called);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
check( mes.raw.length - msg1len, read);
|
|
78
|
+
|
|
79
|
+
ByteBuffer empty = Util.empty();
|
|
80
|
+
read = parser.execute(settings, empty);
|
|
81
|
+
|
|
82
|
+
if (mes.upgrade() && parser.upgrade) {
|
|
83
|
+
check(1 == mes.num_called);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
check(empty.position() == empty.limit());
|
|
87
|
+
check(0 == read);
|
|
88
|
+
check(1 == mes.num_called);
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static void test_multiple3(Message r1, Message r2, Message r3) {
|
|
94
|
+
int message_count = 1;
|
|
95
|
+
if (!r1.upgrade()) {
|
|
96
|
+
message_count++;
|
|
97
|
+
if (!r2.upgrade()) {
|
|
98
|
+
message_count++;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
boolean has_upgrade = (message_count < 3 || r3.upgrade());
|
|
102
|
+
|
|
103
|
+
ByteList blist = new ByteList();
|
|
104
|
+
blist.addAll(r1.raw);
|
|
105
|
+
blist.addAll(r2.raw);
|
|
106
|
+
blist.addAll(r3.raw);
|
|
107
|
+
|
|
108
|
+
byte [] raw = blist.toArray();
|
|
109
|
+
ByteBuffer buf = ByteBuffer.wrap(raw);
|
|
110
|
+
|
|
111
|
+
Util.Settings settings = Util.settings();
|
|
112
|
+
HTTPParser parser = new HTTPParser(r1.type);
|
|
113
|
+
|
|
114
|
+
int read = parser.execute(settings, buf);
|
|
115
|
+
if (has_upgrade && parser.upgrade) {
|
|
116
|
+
raw = upgrade_message_fix(raw, read, r1,r2,r3);
|
|
117
|
+
check(settings.numCalled == message_count);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
check(read == raw.length);
|
|
122
|
+
|
|
123
|
+
buf = Util.empty();
|
|
124
|
+
read = parser.execute(settings, buf);
|
|
125
|
+
if (has_upgrade && parser.upgrade) {
|
|
126
|
+
check(settings.numCalled == message_count);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
check(0 == read);
|
|
131
|
+
check(settings.numCalled == message_count);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Given a sequence of bytes and the number of these that we were able to
|
|
135
|
+
* parse, verify that upgrade bodies are correct.
|
|
136
|
+
*/
|
|
137
|
+
static byte [] upgrade_message_fix(byte[] body, int nread, Message... msgs) {
|
|
138
|
+
int off = 0;
|
|
139
|
+
for (Message m : msgs) {
|
|
140
|
+
off += m.raw.length;
|
|
141
|
+
if (m.upgrade()) {
|
|
142
|
+
off -= m.upgrade.length;
|
|
143
|
+
// Original C:
|
|
144
|
+
// Check the portion of the response after its specified upgrade
|
|
145
|
+
// if (!check_str_eq(m, "upgrade", body + off, body + nread)) {
|
|
146
|
+
// abort();
|
|
147
|
+
// }
|
|
148
|
+
// to me, this seems to be equivalent to comparing off and nread ...
|
|
149
|
+
check (off, nread);
|
|
150
|
+
|
|
151
|
+
// Original C:
|
|
152
|
+
// Fix up the response so that message_eq() will verify the beginning
|
|
153
|
+
// of the upgrade */
|
|
154
|
+
//
|
|
155
|
+
// *(body + nread + strlen(m->upgrade)) = '\0';
|
|
156
|
+
// This only shortens body so the strlen check passes.
|
|
157
|
+
return new byte[off];
|
|
158
|
+
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
//upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
|
|
164
|
+
// va_list ap;
|
|
165
|
+
// size_t i;
|
|
166
|
+
// size_t off = 0;
|
|
167
|
+
//
|
|
168
|
+
// va_start(ap, nmsgs);
|
|
169
|
+
//
|
|
170
|
+
// for (i = 0; i < nmsgs; i++) {
|
|
171
|
+
// struct message *m = va_arg(ap, struct message *);
|
|
172
|
+
//
|
|
173
|
+
// off += strlen(m->raw);
|
|
174
|
+
//
|
|
175
|
+
// if (m->upgrade) {
|
|
176
|
+
// off -= strlen(m->upgrade);
|
|
177
|
+
//
|
|
178
|
+
// /* Check the portion of the response after its specified upgrade */
|
|
179
|
+
// if (!check_str_eq(m, "upgrade", body + off, body + nread)) {
|
|
180
|
+
// abort();
|
|
181
|
+
// }
|
|
182
|
+
//
|
|
183
|
+
// /* Fix up the response so that message_eq() will verify the beginning
|
|
184
|
+
// * of the upgrade */
|
|
185
|
+
// *(body + nread + strlen(m->upgrade)) = '\0';
|
|
186
|
+
// messages[num_messages -1 ].upgrade = body + nread;
|
|
187
|
+
//
|
|
188
|
+
// va_end(ap);
|
|
189
|
+
// return;
|
|
190
|
+
// }
|
|
191
|
+
// }
|
|
192
|
+
//
|
|
193
|
+
// va_end(ap);
|
|
194
|
+
// printf("\n\n*** Error: expected a message with upgrade ***\n");
|
|
195
|
+
//
|
|
196
|
+
// abort();
|
|
197
|
+
//}
|
|
198
|
+
static void p (Object o) {
|
|
199
|
+
System.out.println(o);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
static Settings settings() {
|
|
203
|
+
return new Settings();
|
|
204
|
+
}
|
|
205
|
+
static Message find(List<Message> list, String name) {
|
|
206
|
+
for (Message m : list) {
|
|
207
|
+
if (name.equals(m.name)) {
|
|
208
|
+
return m;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static class Settings extends ParserSettings {
|
|
215
|
+
public int numCalled;
|
|
216
|
+
public int bodyCount;
|
|
217
|
+
Settings() {
|
|
218
|
+
this.on_message_complete = new HTTPCallback() {
|
|
219
|
+
public int cb (HTTPParser parser) {
|
|
220
|
+
numCalled++;
|
|
221
|
+
return 0;
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
this.on_body = new HTTPDataCallback() {
|
|
225
|
+
public int cb (HTTPParser p, ByteBuffer b, int pos, int len) {
|
|
226
|
+
bodyCount += len;
|
|
227
|
+
return 0;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
int numCalled () {
|
|
233
|
+
return this.numCalled;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
package http_parser.lolevel;
|
|
2
|
+
|
|
3
|
+
import java.nio.*;
|
|
4
|
+
import java.util.*;
|
|
5
|
+
|
|
6
|
+
import http_parser.ParserType;
|
|
7
|
+
|
|
8
|
+
import static http_parser.lolevel.Util.*;
|
|
9
|
+
|
|
10
|
+
public class WrongContentLength {
|
|
11
|
+
static final String contentLength = "GET / HTTP/1.0\r\n" +
|
|
12
|
+
"Content-Length: 5\r\n" +
|
|
13
|
+
"\r\n" +
|
|
14
|
+
"hello" +
|
|
15
|
+
"hello_again";
|
|
16
|
+
static void test () {
|
|
17
|
+
p(WrongContentLength.class);
|
|
18
|
+
HTTPParser parser = new HTTPParser(ParserType.HTTP_REQUEST);
|
|
19
|
+
ByteBuffer buf = buffer(contentLength);
|
|
20
|
+
|
|
21
|
+
Settings settings = new Settings();
|
|
22
|
+
|
|
23
|
+
int read = parser.execute(settings, buf);
|
|
24
|
+
check (settings.msg_cmplt_called);
|
|
25
|
+
check ("invalid method".equals(settings.err));
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
public static void main(String [] args) {
|
|
29
|
+
test();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static class Settings extends ParserSettings {
|
|
33
|
+
public int bodyCount;
|
|
34
|
+
public boolean msg_cmplt_called;
|
|
35
|
+
public String err;
|
|
36
|
+
Settings () {
|
|
37
|
+
this.on_message_complete = new HTTPCallback () {
|
|
38
|
+
public int cb (HTTPParser p) {
|
|
39
|
+
check (5 == bodyCount);
|
|
40
|
+
msg_cmplt_called = true;
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
this.on_body = new HTTPDataCallback() {
|
|
45
|
+
public int cb (HTTPParser p, ByteBuffer b, int pos, int len) {
|
|
46
|
+
bodyCount += len;
|
|
47
|
+
check ("hello".equals(str(b, pos, len)));
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
this.on_error = new HTTPErrorCallback() {
|
|
52
|
+
public void cb (HTTPParser p, String mes, ByteBuffer b, int i) {
|
|
53
|
+
err = mes;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|