puma 7.2.0-java → 8.0.0-java
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.
- checksums.yaml +4 -4
- data/History.md +45 -0
- data/README.md +1 -2
- data/docs/5.0-Upgrade.md +98 -0
- data/docs/6.0-Upgrade.md +56 -0
- data/docs/7.0-Upgrade.md +52 -0
- data/docs/8.0-Upgrade.md +100 -0
- data/docs/grpc.md +62 -0
- data/docs/images/favicon.svg +1 -0
- data/docs/images/running-puma.svg +1 -0
- data/docs/images/standard-logo.svg +1 -0
- data/docs/signals.md +1 -1
- data/ext/puma_http11/http11_parser.java.rl +51 -65
- data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +168 -104
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +71 -85
- data/lib/puma/cli.rb +1 -1
- data/lib/puma/client.rb +90 -66
- data/lib/puma/client_env.rb +171 -0
- data/lib/puma/cluster.rb +1 -1
- data/lib/puma/configuration.rb +69 -7
- data/lib/puma/const.rb +2 -2
- data/lib/puma/control_cli.rb +1 -1
- data/lib/puma/detect.rb +11 -0
- data/lib/puma/dsl.rb +74 -8
- data/lib/puma/launcher.rb +3 -4
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/{request.rb → response.rb} +15 -186
- data/lib/puma/server.rb +69 -34
- data/lib/puma/server_plugin_control.rb +32 -0
- data/lib/puma/thread_pool.rb +129 -23
- data/lib/rack/handler/puma.rb +1 -1
- metadata +14 -3
|
@@ -10,43 +10,22 @@ import org.jruby.RubyString;
|
|
|
10
10
|
|
|
11
11
|
import org.jruby.anno.JRubyMethod;
|
|
12
12
|
|
|
13
|
-
import org.jruby.runtime.
|
|
13
|
+
import org.jruby.runtime.ThreadContext;
|
|
14
14
|
import org.jruby.runtime.builtin.IRubyObject;
|
|
15
15
|
|
|
16
16
|
import org.jruby.exceptions.RaiseException;
|
|
17
17
|
|
|
18
18
|
import org.jruby.util.ByteList;
|
|
19
19
|
|
|
20
|
+
import java.util.Arrays;
|
|
21
|
+
|
|
22
|
+
import static java.util.Arrays.stream;
|
|
23
|
+
|
|
20
24
|
/**
|
|
21
25
|
* @author <a href="mailto:ola.bini@ki.se">Ola Bini</a>
|
|
22
26
|
* @author <a href="mailto:headius@headius.com">Charles Oliver Nutter</a>
|
|
23
27
|
*/
|
|
24
28
|
public class Http11 extends RubyObject {
|
|
25
|
-
public final static int MAX_FIELD_NAME_LENGTH = 256;
|
|
26
|
-
public final static String MAX_FIELD_NAME_LENGTH_ERR = "HTTP element FIELD_NAME is longer than the 256 allowed length.";
|
|
27
|
-
public final static int MAX_FIELD_VALUE_LENGTH = 80 * 1024;
|
|
28
|
-
public final static String MAX_FIELD_VALUE_LENGTH_ERR = "HTTP element FIELD_VALUE is longer than the 81920 allowed length.";
|
|
29
|
-
public final static int MAX_REQUEST_URI_LENGTH = getConstLength("PUMA_REQUEST_URI_MAX_LENGTH", 1024 * 12);
|
|
30
|
-
public final static String MAX_REQUEST_URI_LENGTH_ERR = "HTTP element REQUEST_URI is longer than the " + MAX_REQUEST_URI_LENGTH + " allowed length.";
|
|
31
|
-
public final static int MAX_FRAGMENT_LENGTH = 1024;
|
|
32
|
-
public final static String MAX_FRAGMENT_LENGTH_ERR = "HTTP element FRAGMENT is longer than the 1024 allowed length.";
|
|
33
|
-
public final static int MAX_REQUEST_PATH_LENGTH = getConstLength("PUMA_REQUEST_PATH_MAX_LENGTH", 8192);
|
|
34
|
-
public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the " + MAX_REQUEST_PATH_LENGTH + " allowed length.";
|
|
35
|
-
public final static int MAX_QUERY_STRING_LENGTH = getConstLength("PUMA_QUERY_STRING_MAX_LENGTH", 10 * 1024);
|
|
36
|
-
public final static String MAX_QUERY_STRING_LENGTH_ERR = "HTTP element QUERY_STRING is longer than the " + MAX_QUERY_STRING_LENGTH +" allowed length.";
|
|
37
|
-
public final static int MAX_HEADER_LENGTH = 1024 * (80 + 32);
|
|
38
|
-
public final static String MAX_HEADER_LENGTH_ERR = "HTTP element HEADER is longer than the 114688 allowed length.";
|
|
39
|
-
|
|
40
|
-
public static final ByteList CONTENT_TYPE_BYTELIST = new ByteList(ByteList.plain("CONTENT_TYPE"));
|
|
41
|
-
public static final ByteList CONTENT_LENGTH_BYTELIST = new ByteList(ByteList.plain("CONTENT_LENGTH"));
|
|
42
|
-
public static final ByteList HTTP_PREFIX_BYTELIST = new ByteList(ByteList.plain("HTTP_"));
|
|
43
|
-
public static final ByteList COMMA_SPACE_BYTELIST = new ByteList(ByteList.plain(", "));
|
|
44
|
-
public static final ByteList REQUEST_METHOD_BYTELIST = new ByteList(ByteList.plain("REQUEST_METHOD"));
|
|
45
|
-
public static final ByteList REQUEST_URI_BYTELIST = new ByteList(ByteList.plain("REQUEST_URI"));
|
|
46
|
-
public static final ByteList FRAGMENT_BYTELIST = new ByteList(ByteList.plain("FRAGMENT"));
|
|
47
|
-
public static final ByteList REQUEST_PATH_BYTELIST = new ByteList(ByteList.plain("REQUEST_PATH"));
|
|
48
|
-
public static final ByteList QUERY_STRING_BYTELIST = new ByteList(ByteList.plain("QUERY_STRING"));
|
|
49
|
-
public static final ByteList SERVER_PROTOCOL_BYTELIST = new ByteList(ByteList.plain("SERVER_PROTOCOL"));
|
|
50
29
|
|
|
51
30
|
public static String getEnvOrProperty(String name) {
|
|
52
31
|
String envValue = System.getenv(name);
|
|
@@ -69,29 +48,35 @@ public class Http11 extends RubyObject {
|
|
|
69
48
|
}
|
|
70
49
|
}
|
|
71
50
|
|
|
72
|
-
private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
|
73
|
-
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
|
74
|
-
return new Http11(runtime, klass);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
51
|
public static void createHttp11(Ruby runtime) {
|
|
79
52
|
RubyModule mPuma = runtime.defineModule("Puma");
|
|
80
53
|
mPuma.defineClassUnder("HttpParserError",runtime.getClass("StandardError"),runtime.getClass("StandardError").getAllocator());
|
|
81
54
|
|
|
82
|
-
|
|
55
|
+
// Set up pre-allocated strings for HTTP/1.1 headers and CGI variables
|
|
56
|
+
RubyString[] envStrings =
|
|
57
|
+
stream(EnvKey.values())
|
|
58
|
+
.map((key) -> internRubyString(runtime, key))
|
|
59
|
+
.toArray(RubyString[]::new);
|
|
60
|
+
|
|
61
|
+
RubyClass cHttpParser = mPuma.defineClassUnder("HttpParser",runtime.getObject(),(r, c) -> new Http11(r, c, envStrings));
|
|
83
62
|
cHttpParser.defineAnnotatedMethods(Http11.class);
|
|
84
63
|
}
|
|
85
64
|
|
|
86
|
-
private Ruby runtime
|
|
87
|
-
|
|
65
|
+
private static RubyString internRubyString(Ruby runtime, EnvKey key) {
|
|
66
|
+
return runtime.freezeAndDedupString(RubyString.newStringShared(runtime, key.httpName));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private final Ruby runtime;
|
|
70
|
+
private final Http11Parser hp;
|
|
71
|
+
final RubyString[] envStrings;
|
|
88
72
|
private RubyString body;
|
|
89
73
|
|
|
90
|
-
public Http11(Ruby runtime, RubyClass clazz) {
|
|
74
|
+
public Http11(Ruby runtime, RubyClass clazz, RubyString[] envStrings) {
|
|
91
75
|
super(runtime,clazz);
|
|
92
76
|
this.runtime = runtime;
|
|
93
77
|
this.hp = new Http11Parser();
|
|
94
|
-
this.
|
|
78
|
+
this.envStrings = envStrings;
|
|
79
|
+
this.hp.init();
|
|
95
80
|
}
|
|
96
81
|
|
|
97
82
|
public static void validateMaxLength(Ruby runtime, int len, int max, String msg) {
|
|
@@ -109,149 +94,228 @@ public class Http11 extends RubyObject {
|
|
|
109
94
|
return (RubyClass)runtime.getModule("Puma").getConstant("HttpParserError");
|
|
110
95
|
}
|
|
111
96
|
|
|
97
|
+
private static RubyString fstringForField(RubyString[] envStrings, byte[] buffer, int field, int flen) {
|
|
98
|
+
EnvKey key = EnvKey.keyForField(buffer, field, flen);
|
|
99
|
+
if (key != null) return envStrings[key.ordinal()];
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
112
103
|
private static boolean is_ows(int c) {
|
|
113
104
|
return c == ' ' || c == '\t';
|
|
114
105
|
}
|
|
115
106
|
|
|
116
|
-
public static
|
|
107
|
+
public static final byte[] HTTP_PREFIX_BYTELIST = ByteList.plain("HTTP_");
|
|
108
|
+
private static final int HTTP_PREFIX_LENGTH = 5;
|
|
109
|
+
public static final byte[] COMMA_SPACE_BYTELIST = ByteList.plain(", ");
|
|
110
|
+
|
|
111
|
+
public static void http_field(Ruby runtime, RubyString[] envStrings, Http11Parser hp, int vlen) {
|
|
117
112
|
RubyString f;
|
|
118
113
|
IRubyObject v;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
} else {
|
|
130
|
-
b.set(i, (byte)Character.toUpperCase(bite));
|
|
131
|
-
}
|
|
114
|
+
int field_len = hp.field_len;
|
|
115
|
+
validateFieldNameLength(runtime, field_len);
|
|
116
|
+
validateFieldValueLength(runtime, vlen);
|
|
117
|
+
|
|
118
|
+
byte[] buffer = hp.buffer;
|
|
119
|
+
int field_start = hp.field_start;
|
|
120
|
+
f = fstringForField(envStrings, buffer, field_start, field_len);
|
|
121
|
+
|
|
122
|
+
if (f == null) {
|
|
123
|
+
f = newHttpHeader(runtime, buffer, field_start, field_len);
|
|
132
124
|
}
|
|
133
125
|
|
|
134
|
-
|
|
135
|
-
while (vlen > 0
|
|
126
|
+
int mark = hp.mark;
|
|
127
|
+
while (vlen > 0) {
|
|
128
|
+
if (!is_ows(buffer[mark + vlen - 1])) break;
|
|
136
129
|
vlen--;
|
|
137
|
-
value++;
|
|
138
130
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
} else {
|
|
143
|
-
f = RubyString.newStringShared(runtime, HTTP_PREFIX_BYTELIST);
|
|
144
|
-
f.cat(b);
|
|
131
|
+
while (vlen > 0 && is_ows(buffer[mark])) {
|
|
132
|
+
vlen--;
|
|
133
|
+
mark++;
|
|
145
134
|
}
|
|
146
135
|
|
|
147
|
-
|
|
136
|
+
RubyHash req = hp.data;
|
|
148
137
|
v = req.fastARef(f);
|
|
149
138
|
if (v == null || v.isNil()) {
|
|
150
|
-
req.fastASet(f, RubyString.
|
|
139
|
+
req.fastASet(f, RubyString.newStringShared(runtime, buffer, mark, vlen));
|
|
151
140
|
} else {
|
|
152
141
|
RubyString vs = v.convertToString();
|
|
153
142
|
vs.cat(COMMA_SPACE_BYTELIST);
|
|
154
|
-
vs.cat(
|
|
143
|
+
vs.cat(buffer, mark, vlen);
|
|
155
144
|
}
|
|
156
145
|
}
|
|
157
146
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
147
|
+
private static RubyString newHttpHeader(Ruby runtime, byte[] buffer, int field_start, int field_len) {
|
|
148
|
+
byte[] bytes = new byte[HTTP_PREFIX_LENGTH + field_len];
|
|
149
|
+
System.arraycopy(HTTP_PREFIX_BYTELIST, 0, bytes, 0, HTTP_PREFIX_LENGTH);
|
|
150
|
+
snakeCaseCopy(buffer, field_start, field_len, bytes, HTTP_PREFIX_LENGTH);
|
|
151
|
+
return RubyString.newStringNoCopy(runtime, bytes);
|
|
161
152
|
}
|
|
162
153
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
154
|
+
static void snakeCaseCopy(byte[] s, int soff, int slen, byte[] d, int doff) {
|
|
155
|
+
for (int i = 0; i < slen; i++) {
|
|
156
|
+
int si = soff + i;
|
|
157
|
+
byte sch = s[si];
|
|
158
|
+
int di = doff + i;
|
|
159
|
+
byte dch = snakeUpcase(sch);
|
|
160
|
+
d[di] = dch;
|
|
161
|
+
}
|
|
167
162
|
}
|
|
168
163
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
164
|
+
static byte snakeUpcase(byte ch) {
|
|
165
|
+
if (ch >= 'a' && ch <= 'z')
|
|
166
|
+
ch = (byte) (ch & ~0x20);
|
|
167
|
+
else if (ch == '_')
|
|
168
|
+
ch = ',';
|
|
169
|
+
else if (ch == '-')
|
|
170
|
+
ch = '_';
|
|
171
|
+
return ch;
|
|
173
172
|
}
|
|
174
173
|
|
|
175
|
-
public static void
|
|
176
|
-
|
|
177
|
-
RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
|
|
178
|
-
req.fastASet(RubyString.newStringShared(runtime, REQUEST_PATH_BYTELIST),val);
|
|
174
|
+
public static void request_method(Ruby runtime, RubyString[] envStrings, Http11Parser hp, int length) {
|
|
175
|
+
hp.data.fastASet(envStrings[EnvKey.REQUEST_METHOD.ordinal()], newValueString(runtime, hp, length));
|
|
179
176
|
}
|
|
180
177
|
|
|
181
|
-
public static void
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
178
|
+
public static void request_uri(Ruby runtime, RubyString[] envStrings, Http11Parser hp, int length) {
|
|
179
|
+
validateRequestURILength(runtime, length);
|
|
180
|
+
hp.data.fastASet(envStrings[EnvKey.REQUEST_URI.ordinal()], newValueString(runtime, hp, length));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public static void fragment(Ruby runtime, RubyString[] envStrings, Http11Parser hp, int length) {
|
|
184
|
+
validateFragmentLength(runtime, length);
|
|
185
|
+
hp.data.fastASet(envStrings[EnvKey.FRAGMENT.ordinal()], newValueString(runtime, hp, length));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
public static void request_path(Ruby runtime, RubyString[] envStrings, Http11Parser hp, int length) {
|
|
189
|
+
validateRequestPathLength(runtime, length);
|
|
190
|
+
hp.data.fastASet(envStrings[EnvKey.REQUEST_PATH.ordinal()], newValueString(runtime, hp, length));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public static void query_string(Ruby runtime, RubyString[] envStrings, Http11Parser hp, int length) {
|
|
194
|
+
validateQueryStringLength(runtime, length);
|
|
195
|
+
hp.data.fastASet(envStrings[EnvKey.QUERY_STRING.ordinal()], newQueryString(runtime, hp, length));
|
|
185
196
|
}
|
|
186
197
|
|
|
187
|
-
public static void server_protocol(Ruby runtime,
|
|
188
|
-
|
|
189
|
-
req.fastASet(RubyString.newStringShared(runtime, SERVER_PROTOCOL_BYTELIST),val);
|
|
198
|
+
public static void server_protocol(Ruby runtime, RubyString[] envStrings, Http11Parser hp, int length) {
|
|
199
|
+
hp.data.fastASet(envStrings[EnvKey.SERVER_PROTOCOL.ordinal()], newValueString(runtime, hp, length));
|
|
190
200
|
}
|
|
191
201
|
|
|
192
|
-
public void header_done(Ruby runtime,
|
|
193
|
-
body = RubyString.newStringShared(runtime,
|
|
202
|
+
public void header_done(Ruby runtime, Http11Parser hp, int at, int length) {
|
|
203
|
+
body = RubyString.newStringShared(runtime, hp.buffer, at, length);
|
|
194
204
|
}
|
|
195
205
|
|
|
196
206
|
@JRubyMethod
|
|
197
207
|
public IRubyObject initialize() {
|
|
198
|
-
this.hp.
|
|
208
|
+
this.hp.init();
|
|
199
209
|
return this;
|
|
200
210
|
}
|
|
201
211
|
|
|
202
212
|
@JRubyMethod
|
|
203
|
-
public IRubyObject reset() {
|
|
204
|
-
this.hp.
|
|
205
|
-
return
|
|
213
|
+
public IRubyObject reset(ThreadContext context) {
|
|
214
|
+
this.hp.init();
|
|
215
|
+
return context.nil;
|
|
206
216
|
}
|
|
207
217
|
|
|
208
218
|
@JRubyMethod
|
|
209
|
-
public IRubyObject finish() {
|
|
210
|
-
this.hp
|
|
211
|
-
|
|
219
|
+
public IRubyObject finish(ThreadContext context) {
|
|
220
|
+
Http11Parser hp = this.hp;
|
|
221
|
+
hp.finish();
|
|
222
|
+
return hp.is_finished() ? context.tru : context.fals;
|
|
212
223
|
}
|
|
213
224
|
|
|
214
225
|
@JRubyMethod
|
|
215
226
|
public IRubyObject execute(IRubyObject req_hash, IRubyObject data, IRubyObject start) {
|
|
227
|
+
Ruby runtime = this.runtime;
|
|
216
228
|
int from = RubyNumeric.fix2int(start);
|
|
217
|
-
|
|
229
|
+
RubyString dataString = (RubyString) data;
|
|
230
|
+
dataString.setByteListShared();
|
|
231
|
+
ByteList d = dataString.getByteList();
|
|
218
232
|
if(from >= d.length()) {
|
|
219
233
|
throw newHTTPParserError(runtime, "Requested start is after data buffer end.");
|
|
220
234
|
} else {
|
|
221
235
|
Http11Parser hp = this.hp;
|
|
222
|
-
Http11Parser.HttpParser parser = hp.parser;
|
|
223
236
|
|
|
224
|
-
|
|
237
|
+
hp.data = (RubyHash) req_hash;
|
|
225
238
|
|
|
226
239
|
hp.execute(runtime, this, d,from);
|
|
227
240
|
|
|
228
|
-
|
|
241
|
+
validateMaxHeaderLength(runtime, hp);
|
|
229
242
|
|
|
230
243
|
if(hp.has_error()) {
|
|
231
244
|
throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?");
|
|
232
245
|
} else {
|
|
233
|
-
return runtime.newFixnum(
|
|
246
|
+
return runtime.newFixnum(hp.nread);
|
|
234
247
|
}
|
|
235
248
|
}
|
|
236
249
|
}
|
|
237
250
|
|
|
238
251
|
@JRubyMethod(name = "error?")
|
|
239
|
-
public IRubyObject has_error() {
|
|
240
|
-
return this.hp.has_error() ?
|
|
252
|
+
public IRubyObject has_error(ThreadContext context) {
|
|
253
|
+
return this.hp.has_error() ? context.tru : context.fals;
|
|
241
254
|
}
|
|
242
255
|
|
|
243
256
|
@JRubyMethod(name = "finished?")
|
|
244
|
-
public IRubyObject is_finished() {
|
|
245
|
-
return this.hp.is_finished() ?
|
|
257
|
+
public IRubyObject is_finished(ThreadContext context) {
|
|
258
|
+
return this.hp.is_finished() ? context.tru : context.fals;
|
|
246
259
|
}
|
|
247
260
|
|
|
248
261
|
@JRubyMethod
|
|
249
262
|
public IRubyObject nread() {
|
|
250
|
-
return runtime.newFixnum(this.hp.
|
|
263
|
+
return runtime.newFixnum(this.hp.nread);
|
|
251
264
|
}
|
|
252
265
|
|
|
253
266
|
@JRubyMethod
|
|
254
267
|
public IRubyObject body() {
|
|
255
268
|
return body;
|
|
256
269
|
}
|
|
270
|
+
|
|
271
|
+
public final static int MAX_FIELD_NAME_LENGTH = 256;
|
|
272
|
+
public final static String MAX_FIELD_NAME_LENGTH_ERR = "HTTP element FIELD_NAME is longer than the 256 allowed length.";
|
|
273
|
+
public final static int MAX_FIELD_VALUE_LENGTH = 80 * 1024;
|
|
274
|
+
public final static String MAX_FIELD_VALUE_LENGTH_ERR = "HTTP element FIELD_VALUE is longer than the 81920 allowed length.";
|
|
275
|
+
public final static int MAX_REQUEST_URI_LENGTH = getConstLength("PUMA_REQUEST_URI_MAX_LENGTH", 1024 * 12);
|
|
276
|
+
public final static String MAX_REQUEST_URI_LENGTH_ERR = "HTTP element REQUEST_URI is longer than the " + MAX_REQUEST_URI_LENGTH + " allowed length.";
|
|
277
|
+
public final static int MAX_FRAGMENT_LENGTH = 1024;
|
|
278
|
+
public final static String MAX_FRAGMENT_LENGTH_ERR = "HTTP element FRAGMENT is longer than the 1024 allowed length.";
|
|
279
|
+
public final static int MAX_REQUEST_PATH_LENGTH = getConstLength("PUMA_REQUEST_PATH_MAX_LENGTH", 8192);
|
|
280
|
+
public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the " + MAX_REQUEST_PATH_LENGTH + " allowed length.";
|
|
281
|
+
public final static int MAX_QUERY_STRING_LENGTH = getConstLength("PUMA_QUERY_STRING_MAX_LENGTH", 10 * 1024);
|
|
282
|
+
public final static String MAX_QUERY_STRING_LENGTH_ERR = "HTTP element QUERY_STRING is longer than the " + MAX_QUERY_STRING_LENGTH +" allowed length.";
|
|
283
|
+
public final static int MAX_HEADER_LENGTH = 1024 * (80 + 32);
|
|
284
|
+
public final static String MAX_HEADER_LENGTH_ERR = "HTTP element HEADER is longer than the 114688 allowed length.";
|
|
285
|
+
|
|
286
|
+
private static void validateFieldNameLength(Ruby runtime, int field_len) {
|
|
287
|
+
validateMaxLength(runtime, field_len, MAX_FIELD_NAME_LENGTH, MAX_FIELD_NAME_LENGTH_ERR);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private static void validateFieldValueLength(Ruby runtime, int field_len) {
|
|
291
|
+
validateMaxLength(runtime, field_len, MAX_FIELD_VALUE_LENGTH, MAX_FIELD_VALUE_LENGTH_ERR);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private static void validateRequestURILength(Ruby runtime, int length) {
|
|
295
|
+
validateMaxLength(runtime, length, MAX_REQUEST_URI_LENGTH, MAX_REQUEST_URI_LENGTH_ERR);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
private static void validateFragmentLength(Ruby runtime, int length) {
|
|
299
|
+
validateMaxLength(runtime, length, MAX_FRAGMENT_LENGTH, MAX_FRAGMENT_LENGTH_ERR);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private static void validateRequestPathLength(Ruby runtime, int length) {
|
|
303
|
+
validateMaxLength(runtime, length, MAX_REQUEST_PATH_LENGTH, MAX_REQUEST_PATH_LENGTH_ERR);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private static void validateQueryStringLength(Ruby runtime, int length) {
|
|
307
|
+
validateMaxLength(runtime, length, MAX_QUERY_STRING_LENGTH, MAX_QUERY_STRING_LENGTH_ERR);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private static RubyString newValueString(Ruby runtime, Http11Parser hp, int length) {
|
|
311
|
+
return RubyString.newStringShared(runtime, hp.buffer, hp.mark, length);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private static RubyString newQueryString(Ruby runtime, Http11Parser hp, int length) {
|
|
315
|
+
return RubyString.newStringShared(runtime, hp.buffer, hp.query_start, length);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
private static void validateMaxHeaderLength(Ruby runtime, Http11Parser hp) {
|
|
319
|
+
validateMaxLength(runtime, hp.nread, MAX_HEADER_LENGTH, MAX_HEADER_LENGTH_ERR);
|
|
320
|
+
}
|
|
257
321
|
}// Http11
|
|
@@ -4,6 +4,7 @@ package org.jruby.puma;
|
|
|
4
4
|
|
|
5
5
|
import org.jruby.Ruby;
|
|
6
6
|
import org.jruby.RubyHash;
|
|
7
|
+
import org.jruby.RubyString;
|
|
7
8
|
import org.jruby.util.ByteList;
|
|
8
9
|
|
|
9
10
|
public class Http11Parser {
|
|
@@ -11,12 +12,12 @@ public class Http11Parser {
|
|
|
11
12
|
/** Machine **/
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
// line
|
|
15
|
+
// line 59 "ext/puma_http11/http11_parser.java.rl"
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
/** Data **/
|
|
18
19
|
|
|
19
|
-
// line
|
|
20
|
+
// line 21 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
|
20
21
|
private static byte[] init__puma_parser_actions_0()
|
|
21
22
|
{
|
|
22
23
|
return new byte [] {
|
|
@@ -185,66 +186,51 @@ static final int puma_parser_first_final = 46;
|
|
|
185
186
|
static final int puma_parser_error = 0;
|
|
186
187
|
|
|
187
188
|
|
|
188
|
-
// line
|
|
189
|
+
// line 63 "ext/puma_http11/http11_parser.java.rl"
|
|
189
190
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
public static class HttpParser {
|
|
199
|
-
int cs;
|
|
200
|
-
int body_start;
|
|
201
|
-
int content_len;
|
|
202
|
-
int nread;
|
|
203
|
-
int mark;
|
|
204
|
-
int field_start;
|
|
205
|
-
int field_len;
|
|
206
|
-
int query_start;
|
|
191
|
+
int cs;
|
|
192
|
+
int body_start;
|
|
193
|
+
int nread;
|
|
194
|
+
int mark;
|
|
195
|
+
int field_start;
|
|
196
|
+
int field_len;
|
|
197
|
+
int query_start;
|
|
207
198
|
|
|
208
|
-
|
|
209
|
-
|
|
199
|
+
RubyHash data;
|
|
200
|
+
byte[] buffer;
|
|
210
201
|
|
|
211
|
-
|
|
212
|
-
cs = 0;
|
|
202
|
+
public void init() {
|
|
213
203
|
|
|
214
|
-
|
|
215
|
-
// line
|
|
204
|
+
|
|
205
|
+
// line 206 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
|
216
206
|
{
|
|
217
207
|
cs = puma_parser_start;
|
|
218
208
|
}
|
|
219
209
|
|
|
220
|
-
// line
|
|
210
|
+
// line 78 "ext/puma_http11/http11_parser.java.rl"
|
|
221
211
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
field_start = 0;
|
|
228
|
-
}
|
|
212
|
+
body_start = 0;
|
|
213
|
+
mark = 0;
|
|
214
|
+
nread = 0;
|
|
215
|
+
field_len = 0;
|
|
216
|
+
field_start = 0;
|
|
229
217
|
}
|
|
230
218
|
|
|
231
|
-
public final HttpParser parser = new HttpParser();
|
|
232
|
-
|
|
233
219
|
public int execute(Ruby runtime, Http11 http, ByteList buffer, int off) {
|
|
234
220
|
int p, pe;
|
|
235
|
-
int cs =
|
|
221
|
+
int cs = this.cs;
|
|
236
222
|
int len = buffer.length();
|
|
223
|
+
int beg = buffer.begin();
|
|
224
|
+
RubyString[] envStrings = http.envStrings;
|
|
237
225
|
assert off<=len : "offset past end of buffer";
|
|
238
226
|
|
|
239
|
-
p = off;
|
|
240
|
-
pe = len;
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
byte[] data = buffer.bytes();
|
|
244
|
-
parser.buffer = buffer;
|
|
227
|
+
p = beg + off;
|
|
228
|
+
pe = beg + len;
|
|
229
|
+
byte[] data = buffer.unsafeBytes();
|
|
230
|
+
this.buffer = data;
|
|
245
231
|
|
|
246
232
|
|
|
247
|
-
// line
|
|
233
|
+
// line 234 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
|
248
234
|
{
|
|
249
235
|
int _klen;
|
|
250
236
|
int _trans = 0;
|
|
@@ -325,82 +311,82 @@ case 1:
|
|
|
325
311
|
switch ( _puma_parser_actions[_acts++] )
|
|
326
312
|
{
|
|
327
313
|
case 0:
|
|
328
|
-
// line
|
|
329
|
-
{
|
|
314
|
+
// line 16 "ext/puma_http11/http11_parser.java.rl"
|
|
315
|
+
{this.mark = p; }
|
|
330
316
|
break;
|
|
331
317
|
case 1:
|
|
332
|
-
// line
|
|
333
|
-
{
|
|
318
|
+
// line 18 "ext/puma_http11/http11_parser.java.rl"
|
|
319
|
+
{ this.field_start = p; }
|
|
334
320
|
break;
|
|
335
321
|
case 2:
|
|
336
|
-
// line
|
|
337
|
-
{ /*
|
|
322
|
+
// line 19 "ext/puma_http11/http11_parser.java.rl"
|
|
323
|
+
{ /* done lazily as needed */ }
|
|
338
324
|
break;
|
|
339
325
|
case 3:
|
|
340
|
-
// line
|
|
326
|
+
// line 20 "ext/puma_http11/http11_parser.java.rl"
|
|
341
327
|
{
|
|
342
|
-
|
|
328
|
+
this.field_len = p-this.field_start;
|
|
343
329
|
}
|
|
344
330
|
break;
|
|
345
331
|
case 4:
|
|
346
|
-
// line
|
|
347
|
-
{
|
|
332
|
+
// line 24 "ext/puma_http11/http11_parser.java.rl"
|
|
333
|
+
{ this.mark = p; }
|
|
348
334
|
break;
|
|
349
335
|
case 5:
|
|
350
|
-
// line
|
|
336
|
+
// line 25 "ext/puma_http11/http11_parser.java.rl"
|
|
351
337
|
{
|
|
352
|
-
Http11.http_field(runtime,
|
|
338
|
+
Http11.http_field(runtime, envStrings, this, p-this.mark);
|
|
353
339
|
}
|
|
354
340
|
break;
|
|
355
341
|
case 6:
|
|
356
|
-
// line
|
|
342
|
+
// line 28 "ext/puma_http11/http11_parser.java.rl"
|
|
357
343
|
{
|
|
358
|
-
Http11.request_method(runtime,
|
|
344
|
+
Http11.request_method(runtime, envStrings, this, p-this.mark);
|
|
359
345
|
}
|
|
360
346
|
break;
|
|
361
347
|
case 7:
|
|
362
|
-
// line
|
|
348
|
+
// line 31 "ext/puma_http11/http11_parser.java.rl"
|
|
363
349
|
{
|
|
364
|
-
Http11.request_uri(runtime,
|
|
350
|
+
Http11.request_uri(runtime, envStrings, this, p-this.mark);
|
|
365
351
|
}
|
|
366
352
|
break;
|
|
367
353
|
case 8:
|
|
368
|
-
// line
|
|
354
|
+
// line 34 "ext/puma_http11/http11_parser.java.rl"
|
|
369
355
|
{
|
|
370
|
-
Http11.fragment(runtime,
|
|
356
|
+
Http11.fragment(runtime, envStrings, this, p-this.mark);
|
|
371
357
|
}
|
|
372
358
|
break;
|
|
373
359
|
case 9:
|
|
374
|
-
// line
|
|
375
|
-
{
|
|
360
|
+
// line 38 "ext/puma_http11/http11_parser.java.rl"
|
|
361
|
+
{this.query_start = p; }
|
|
376
362
|
break;
|
|
377
363
|
case 10:
|
|
378
|
-
// line
|
|
364
|
+
// line 39 "ext/puma_http11/http11_parser.java.rl"
|
|
379
365
|
{
|
|
380
|
-
Http11.query_string(runtime,
|
|
366
|
+
Http11.query_string(runtime, envStrings, this, p-this.query_start);
|
|
381
367
|
}
|
|
382
368
|
break;
|
|
383
369
|
case 11:
|
|
384
|
-
// line
|
|
370
|
+
// line 43 "ext/puma_http11/http11_parser.java.rl"
|
|
385
371
|
{
|
|
386
|
-
Http11.server_protocol(runtime,
|
|
372
|
+
Http11.server_protocol(runtime, envStrings, this, p-this.mark);
|
|
387
373
|
}
|
|
388
374
|
break;
|
|
389
375
|
case 12:
|
|
390
|
-
// line
|
|
376
|
+
// line 47 "ext/puma_http11/http11_parser.java.rl"
|
|
391
377
|
{
|
|
392
|
-
Http11.request_path(runtime,
|
|
378
|
+
Http11.request_path(runtime, envStrings, this, p-this.mark);
|
|
393
379
|
}
|
|
394
380
|
break;
|
|
395
381
|
case 13:
|
|
396
|
-
// line
|
|
382
|
+
// line 51 "ext/puma_http11/http11_parser.java.rl"
|
|
397
383
|
{
|
|
398
|
-
|
|
399
|
-
http.header_done(runtime,
|
|
384
|
+
this.body_start = p + 1;
|
|
385
|
+
http.header_done(runtime, this, p + 1, pe - p - 1);
|
|
400
386
|
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
|
|
401
387
|
}
|
|
402
388
|
break;
|
|
403
|
-
// line
|
|
389
|
+
// line 390 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
|
404
390
|
}
|
|
405
391
|
}
|
|
406
392
|
}
|
|
@@ -420,19 +406,19 @@ case 5:
|
|
|
420
406
|
break; }
|
|
421
407
|
}
|
|
422
408
|
|
|
423
|
-
// line
|
|
409
|
+
// line 100 "ext/puma_http11/http11_parser.java.rl"
|
|
424
410
|
|
|
425
|
-
|
|
426
|
-
|
|
411
|
+
this.cs = cs;
|
|
412
|
+
this.nread += (p - off);
|
|
427
413
|
|
|
428
414
|
assert p <= pe : "buffer overflow after parsing execute";
|
|
429
|
-
assert
|
|
430
|
-
assert
|
|
431
|
-
assert
|
|
432
|
-
assert
|
|
433
|
-
assert
|
|
415
|
+
assert this.nread <= len : "nread longer than length";
|
|
416
|
+
assert this.body_start <= len : "body starts after buffer end";
|
|
417
|
+
assert this.mark < len : "mark is after buffer end";
|
|
418
|
+
assert this.field_len <= len : "field has length longer than whole buffer";
|
|
419
|
+
assert this.field_start < len : "field starts after buffer end";
|
|
434
420
|
|
|
435
|
-
return
|
|
421
|
+
return this.nread;
|
|
436
422
|
}
|
|
437
423
|
|
|
438
424
|
public int finish() {
|
|
@@ -446,10 +432,10 @@ case 5:
|
|
|
446
432
|
}
|
|
447
433
|
|
|
448
434
|
public boolean has_error() {
|
|
449
|
-
return
|
|
435
|
+
return this.cs == puma_parser_error;
|
|
450
436
|
}
|
|
451
437
|
|
|
452
438
|
public boolean is_finished() {
|
|
453
|
-
return
|
|
439
|
+
return this.cs == puma_parser_first_final;
|
|
454
440
|
}
|
|
455
441
|
}
|