puma 6.4.3 → 8.0.2

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +448 -8
  3. data/README.md +110 -51
  4. data/docs/5.0-Upgrade.md +98 -0
  5. data/docs/6.0-Upgrade.md +56 -0
  6. data/docs/7.0-Upgrade.md +52 -0
  7. data/docs/8.0-Upgrade.md +100 -0
  8. data/docs/deployment.md +58 -23
  9. data/docs/fork_worker.md +11 -1
  10. data/docs/grpc.md +62 -0
  11. data/docs/images/favicon.svg +1 -0
  12. data/docs/images/running-puma.svg +1 -0
  13. data/docs/images/standard-logo.svg +1 -0
  14. data/docs/java_options.md +54 -0
  15. data/docs/jungle/README.md +1 -1
  16. data/docs/kubernetes.md +11 -16
  17. data/docs/plugins.md +6 -2
  18. data/docs/restart.md +2 -2
  19. data/docs/signals.md +21 -21
  20. data/docs/stats.md +11 -5
  21. data/docs/systemd.md +14 -5
  22. data/ext/puma_http11/extconf.rb +20 -32
  23. data/ext/puma_http11/http11_parser.java.rl +51 -65
  24. data/ext/puma_http11/mini_ssl.c +29 -9
  25. data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
  26. data/ext/puma_http11/org/jruby/puma/Http11.java +194 -101
  27. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +71 -85
  28. data/ext/puma_http11/puma_http11.c +125 -118
  29. data/lib/puma/app/status.rb +11 -3
  30. data/lib/puma/binder.rb +22 -12
  31. data/lib/puma/cli.rb +11 -9
  32. data/lib/puma/client.rb +233 -136
  33. data/lib/puma/client_env.rb +171 -0
  34. data/lib/puma/cluster/worker.rb +24 -21
  35. data/lib/puma/cluster/worker_handle.rb +38 -8
  36. data/lib/puma/cluster.rb +74 -48
  37. data/lib/puma/cluster_accept_loop_delay.rb +91 -0
  38. data/lib/puma/commonlogger.rb +3 -3
  39. data/lib/puma/configuration.rb +197 -64
  40. data/lib/puma/const.rb +23 -12
  41. data/lib/puma/control_cli.rb +11 -7
  42. data/lib/puma/detect.rb +13 -0
  43. data/lib/puma/dsl.rb +483 -127
  44. data/lib/puma/error_logger.rb +7 -5
  45. data/lib/puma/events.rb +25 -10
  46. data/lib/puma/io_buffer.rb +8 -4
  47. data/lib/puma/jruby_restart.rb +0 -16
  48. data/lib/puma/launcher/bundle_pruner.rb +3 -5
  49. data/lib/puma/launcher.rb +76 -59
  50. data/lib/puma/log_writer.rb +17 -11
  51. data/lib/puma/minissl/context_builder.rb +1 -0
  52. data/lib/puma/minissl.rb +1 -1
  53. data/lib/puma/null_io.rb +26 -0
  54. data/lib/puma/plugin/systemd.rb +3 -3
  55. data/lib/puma/rack/urlmap.rb +1 -1
  56. data/lib/puma/reactor.rb +19 -13
  57. data/lib/puma/{request.rb → response.rb} +57 -209
  58. data/lib/puma/runner.rb +15 -17
  59. data/lib/puma/sd_notify.rb +1 -4
  60. data/lib/puma/server.rb +200 -104
  61. data/lib/puma/server_plugin_control.rb +32 -0
  62. data/lib/puma/single.rb +7 -4
  63. data/lib/puma/state_file.rb +3 -2
  64. data/lib/puma/thread_pool.rb +179 -96
  65. data/lib/puma/util.rb +0 -7
  66. data/lib/puma.rb +10 -0
  67. data/lib/rack/handler/puma.rb +11 -8
  68. data/tools/Dockerfile +15 -5
  69. metadata +26 -16
  70. data/ext/puma_http11/ext_help.h +0 -15
@@ -10,67 +10,73 @@ import org.jruby.RubyString;
10
10
 
11
11
  import org.jruby.anno.JRubyMethod;
12
12
 
13
- import org.jruby.runtime.ObjectAllocator;
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 = 1024 * 12;
30
- public final static String MAX_REQUEST_URI_LENGTH_ERR = "HTTP element REQUEST_URI is longer than the 12288 allowed length.";
31
- public final static int MAX_FRAGMENT_LENGTH = 1024;
32
- public final static String MAX_FRAGMENT_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 1024 allowed length.";
33
- public final static int MAX_REQUEST_PATH_LENGTH = 8192;
34
- public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 8192 allowed length.";
35
- public final static int MAX_QUERY_STRING_LENGTH = 1024 * 10;
36
- public final static String MAX_QUERY_STRING_LENGTH_ERR = "HTTP element QUERY_STRING is longer than the 10240 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
29
 
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
-
51
- private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
52
- public IRubyObject allocate(Ruby runtime, RubyClass klass) {
53
- return new Http11(runtime, klass);
30
+ public static String getEnvOrProperty(String name) {
31
+ String envValue = System.getenv(name);
32
+ return (envValue != null) ? envValue : System.getProperty(name);
33
+ }
34
+
35
+ public static int getConstLength(String name, Integer defaultValue) {
36
+ String stringValue = getEnvOrProperty(name);
37
+ if (stringValue == null || stringValue.isEmpty()) return defaultValue;
38
+
39
+ try {
40
+ int value = Integer.parseUnsignedInt(stringValue);
41
+ if (value <= 0) {
42
+ throw new NumberFormatException("The number is not positive.");
43
+ }
44
+ return value;
45
+ } catch (NumberFormatException e) {
46
+ System.err.println(String.format("The value %s for %s is invalid. Using default value %d instead.", stringValue, name, defaultValue));
47
+ return defaultValue;
54
48
  }
55
- };
49
+ }
56
50
 
57
51
  public static void createHttp11(Ruby runtime) {
58
52
  RubyModule mPuma = runtime.defineModule("Puma");
59
- mPuma.defineClassUnder("HttpParserError",runtime.getClass("IOError"),runtime.getClass("IOError").getAllocator());
53
+ mPuma.defineClassUnder("HttpParserError",runtime.getClass("StandardError"),runtime.getClass("StandardError").getAllocator());
60
54
 
61
- RubyClass cHttpParser = mPuma.defineClassUnder("HttpParser",runtime.getObject(),ALLOCATOR);
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));
62
62
  cHttpParser.defineAnnotatedMethods(Http11.class);
63
63
  }
64
64
 
65
- private Ruby runtime;
66
- private Http11Parser hp;
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;
67
72
  private RubyString body;
68
73
 
69
- public Http11(Ruby runtime, RubyClass clazz) {
74
+ public Http11(Ruby runtime, RubyClass clazz, RubyString[] envStrings) {
70
75
  super(runtime,clazz);
71
76
  this.runtime = runtime;
72
77
  this.hp = new Http11Parser();
73
- this.hp.parser.init();
78
+ this.envStrings = envStrings;
79
+ this.hp.init();
74
80
  }
75
81
 
76
82
  public static void validateMaxLength(Ruby runtime, int len, int max, String msg) {
@@ -88,141 +94,228 @@ public class Http11 extends RubyObject {
88
94
  return (RubyClass)runtime.getModule("Puma").getConstant("HttpParserError");
89
95
  }
90
96
 
91
- public static void http_field(Ruby runtime, RubyHash req, ByteList buffer, int field, int flen, int value, int vlen) {
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
+
103
+ private static boolean is_ows(int c) {
104
+ return c == ' ' || c == '\t';
105
+ }
106
+
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) {
92
112
  RubyString f;
93
113
  IRubyObject v;
94
- validateMaxLength(runtime, flen, MAX_FIELD_NAME_LENGTH, MAX_FIELD_NAME_LENGTH_ERR);
95
- validateMaxLength(runtime, vlen, MAX_FIELD_VALUE_LENGTH, MAX_FIELD_VALUE_LENGTH_ERR);
96
-
97
- ByteList b = new ByteList(buffer,field,flen);
98
- for(int i = 0,j = b.length();i<j;i++) {
99
- int bite = b.get(i) & 0xFF;
100
- if(bite == '-') {
101
- b.set(i, (byte)'_');
102
- } else if(bite == '_') {
103
- b.set(i, (byte)',');
104
- } else {
105
- b.set(i, (byte)Character.toUpperCase(bite));
106
- }
107
- }
114
+ int field_len = hp.field_len;
115
+ validateFieldNameLength(runtime, field_len);
116
+ validateFieldValueLength(runtime, vlen);
108
117
 
109
- while (vlen > 0 && Character.isWhitespace(buffer.get(value + vlen - 1))) vlen--;
118
+ byte[] buffer = hp.buffer;
119
+ int field_start = hp.field_start;
120
+ f = fstringForField(envStrings, buffer, field_start, field_len);
110
121
 
111
- if (b.equals(CONTENT_LENGTH_BYTELIST) || b.equals(CONTENT_TYPE_BYTELIST)) {
112
- f = RubyString.newString(runtime, b);
113
- } else {
114
- f = RubyString.newStringShared(runtime, HTTP_PREFIX_BYTELIST);
115
- f.cat(b);
122
+ if (f == null) {
123
+ f = newHttpHeader(runtime, buffer, field_start, field_len);
116
124
  }
117
125
 
118
- b = new ByteList(buffer, value, vlen);
126
+ int mark = hp.mark;
127
+ while (vlen > 0) {
128
+ if (!is_ows(buffer[mark + vlen - 1])) break;
129
+ vlen--;
130
+ }
131
+ while (vlen > 0 && is_ows(buffer[mark])) {
132
+ vlen--;
133
+ mark++;
134
+ }
135
+
136
+ RubyHash req = hp.data;
119
137
  v = req.fastARef(f);
120
138
  if (v == null || v.isNil()) {
121
- req.fastASet(f, RubyString.newString(runtime, b));
139
+ req.fastASet(f, RubyString.newStringShared(runtime, buffer, mark, vlen));
122
140
  } else {
123
141
  RubyString vs = v.convertToString();
124
142
  vs.cat(COMMA_SPACE_BYTELIST);
125
- vs.cat(b);
143
+ vs.cat(buffer, mark, vlen);
126
144
  }
127
145
  }
128
146
 
129
- public static void request_method(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
130
- RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
131
- req.fastASet(RubyString.newStringShared(runtime, REQUEST_METHOD_BYTELIST),val);
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);
132
152
  }
133
153
 
134
- public static void request_uri(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
135
- validateMaxLength(runtime, length, MAX_REQUEST_URI_LENGTH, MAX_REQUEST_URI_LENGTH_ERR);
136
- RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
137
- req.fastASet(RubyString.newStringShared(runtime, REQUEST_URI_BYTELIST),val);
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
+ }
138
162
  }
139
163
 
140
- public static void fragment(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
141
- validateMaxLength(runtime, length, MAX_FRAGMENT_LENGTH, MAX_FRAGMENT_LENGTH_ERR);
142
- RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
143
- req.fastASet(RubyString.newStringShared(runtime, FRAGMENT_BYTELIST),val);
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;
144
172
  }
145
173
 
146
- public static void request_path(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
147
- validateMaxLength(runtime, length, MAX_REQUEST_PATH_LENGTH, MAX_REQUEST_PATH_LENGTH_ERR);
148
- RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
149
- 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));
150
176
  }
151
177
 
152
- public static void query_string(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
153
- validateMaxLength(runtime, length, MAX_QUERY_STRING_LENGTH, MAX_QUERY_STRING_LENGTH_ERR);
154
- RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
155
- req.fastASet(RubyString.newStringShared(runtime, QUERY_STRING_BYTELIST),val);
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));
156
196
  }
157
197
 
158
- public static void server_protocol(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
159
- RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
160
- 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));
161
200
  }
162
201
 
163
- public void header_done(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
164
- body = RubyString.newStringShared(runtime, new ByteList(buffer, at, length));
202
+ public void header_done(Ruby runtime, Http11Parser hp, int at, int length) {
203
+ body = RubyString.newStringShared(runtime, hp.buffer, at, length);
165
204
  }
166
205
 
167
206
  @JRubyMethod
168
207
  public IRubyObject initialize() {
169
- this.hp.parser.init();
208
+ this.hp.init();
170
209
  return this;
171
210
  }
172
211
 
173
212
  @JRubyMethod
174
- public IRubyObject reset() {
175
- this.hp.parser.init();
176
- return runtime.getNil();
213
+ public IRubyObject reset(ThreadContext context) {
214
+ this.hp.init();
215
+ return context.nil;
177
216
  }
178
217
 
179
218
  @JRubyMethod
180
- public IRubyObject finish() {
181
- this.hp.finish();
182
- return this.hp.is_finished() ? runtime.getTrue() : runtime.getFalse();
219
+ public IRubyObject finish(ThreadContext context) {
220
+ Http11Parser hp = this.hp;
221
+ hp.finish();
222
+ return hp.is_finished() ? context.tru : context.fals;
183
223
  }
184
224
 
185
225
  @JRubyMethod
186
226
  public IRubyObject execute(IRubyObject req_hash, IRubyObject data, IRubyObject start) {
227
+ Ruby runtime = this.runtime;
187
228
  int from = RubyNumeric.fix2int(start);
188
- ByteList d = ((RubyString)data).getByteList();
229
+ RubyString dataString = (RubyString) data;
230
+ dataString.setByteListShared();
231
+ ByteList d = dataString.getByteList();
189
232
  if(from >= d.length()) {
190
233
  throw newHTTPParserError(runtime, "Requested start is after data buffer end.");
191
234
  } else {
192
235
  Http11Parser hp = this.hp;
193
- Http11Parser.HttpParser parser = hp.parser;
194
236
 
195
- parser.data = (RubyHash) req_hash;
237
+ hp.data = (RubyHash) req_hash;
196
238
 
197
239
  hp.execute(runtime, this, d,from);
198
240
 
199
- validateMaxLength(runtime, parser.nread,MAX_HEADER_LENGTH, MAX_HEADER_LENGTH_ERR);
241
+ validateMaxHeaderLength(runtime, hp);
200
242
 
201
243
  if(hp.has_error()) {
202
244
  throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?");
203
245
  } else {
204
- return runtime.newFixnum(parser.nread);
246
+ return runtime.newFixnum(hp.nread);
205
247
  }
206
248
  }
207
249
  }
208
250
 
209
251
  @JRubyMethod(name = "error?")
210
- public IRubyObject has_error() {
211
- return this.hp.has_error() ? runtime.getTrue() : runtime.getFalse();
252
+ public IRubyObject has_error(ThreadContext context) {
253
+ return this.hp.has_error() ? context.tru : context.fals;
212
254
  }
213
255
 
214
256
  @JRubyMethod(name = "finished?")
215
- public IRubyObject is_finished() {
216
- return this.hp.is_finished() ? runtime.getTrue() : runtime.getFalse();
257
+ public IRubyObject is_finished(ThreadContext context) {
258
+ return this.hp.is_finished() ? context.tru : context.fals;
217
259
  }
218
260
 
219
261
  @JRubyMethod
220
262
  public IRubyObject nread() {
221
- return runtime.newFixnum(this.hp.parser.nread);
263
+ return runtime.newFixnum(this.hp.nread);
222
264
  }
223
265
 
224
266
  @JRubyMethod
225
267
  public IRubyObject body() {
226
268
  return body;
227
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
+ }
228
321
  }// Http11