puma 2.2.0 → 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 (136) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +3334 -0
  3. data/LICENSE +23 -20
  4. data/README.md +387 -100
  5. data/bin/puma-wild +25 -0
  6. data/bin/pumactl +1 -1
  7. data/docs/5.0-Upgrade.md +98 -0
  8. data/docs/6.0-Upgrade.md +56 -0
  9. data/docs/7.0-Upgrade.md +52 -0
  10. data/docs/8.0-Upgrade.md +100 -0
  11. data/docs/architecture.md +74 -0
  12. data/docs/compile_options.md +55 -0
  13. data/docs/deployment.md +137 -0
  14. data/docs/fork_worker.md +41 -0
  15. data/docs/grpc.md +62 -0
  16. data/docs/images/favicon.svg +1 -0
  17. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  18. data/docs/images/puma-connection-flow.png +0 -0
  19. data/docs/images/puma-general-arch.png +0 -0
  20. data/docs/images/running-puma.svg +1 -0
  21. data/docs/images/standard-logo.svg +1 -0
  22. data/docs/java_options.md +54 -0
  23. data/docs/jungle/README.md +9 -0
  24. data/docs/jungle/rc.d/README.md +74 -0
  25. data/docs/jungle/rc.d/puma +61 -0
  26. data/docs/jungle/rc.d/puma.conf +10 -0
  27. data/docs/kubernetes.md +73 -0
  28. data/docs/nginx.md +5 -5
  29. data/docs/plugins.md +42 -0
  30. data/docs/rails_dev_mode.md +28 -0
  31. data/docs/restart.md +65 -0
  32. data/docs/signals.md +98 -0
  33. data/docs/stats.md +148 -0
  34. data/docs/systemd.md +253 -0
  35. data/docs/testing_benchmarks_local_files.md +150 -0
  36. data/docs/testing_test_rackup_ci_files.md +36 -0
  37. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  38. data/ext/puma_http11/extconf.rb +59 -2
  39. data/ext/puma_http11/http11_parser.c +319 -487
  40. data/ext/puma_http11/http11_parser.h +15 -13
  41. data/ext/puma_http11/http11_parser.java.rl +64 -94
  42. data/ext/puma_http11/http11_parser.rl +27 -24
  43. data/ext/puma_http11/http11_parser_common.rl +8 -8
  44. data/ext/puma_http11/mini_ssl.c +696 -38
  45. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  46. data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
  47. data/ext/puma_http11/org/jruby/puma/Http11.java +241 -145
  48. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +174 -221
  49. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +413 -193
  50. data/ext/puma_http11/puma_http11.c +183 -175
  51. data/lib/puma/app/status.rb +77 -29
  52. data/lib/puma/binder.rb +349 -119
  53. data/lib/puma/cli.rb +163 -801
  54. data/lib/puma/client.rb +627 -144
  55. data/lib/puma/client_env.rb +171 -0
  56. data/lib/puma/cluster/worker.rb +183 -0
  57. data/lib/puma/cluster/worker_handle.rb +127 -0
  58. data/lib/puma/cluster.rb +634 -0
  59. data/lib/puma/cluster_accept_loop_delay.rb +91 -0
  60. data/lib/puma/commonlogger.rb +115 -0
  61. data/lib/puma/configuration.rb +420 -198
  62. data/lib/puma/const.rb +266 -115
  63. data/lib/puma/control_cli.rb +219 -120
  64. data/lib/puma/detect.rb +56 -2
  65. data/lib/puma/dsl.rb +1562 -0
  66. data/lib/puma/error_logger.rb +115 -0
  67. data/lib/puma/events.rb +44 -60
  68. data/lib/puma/io_buffer.rb +48 -5
  69. data/lib/puma/jruby_restart.rb +2 -51
  70. data/lib/puma/json_serialization.rb +96 -0
  71. data/lib/puma/launcher/bundle_pruner.rb +102 -0
  72. data/lib/puma/launcher.rb +501 -0
  73. data/lib/puma/log_writer.rb +153 -0
  74. data/lib/puma/minissl/context_builder.rb +96 -0
  75. data/lib/puma/minissl.rb +355 -37
  76. data/lib/puma/null_io.rb +79 -12
  77. data/lib/puma/plugin/systemd.rb +90 -0
  78. data/lib/puma/plugin/tmp_restart.rb +36 -0
  79. data/lib/puma/plugin.rb +111 -0
  80. data/lib/puma/rack/builder.rb +297 -0
  81. data/lib/puma/rack/urlmap.rb +93 -0
  82. data/lib/puma/rack_default.rb +21 -4
  83. data/lib/puma/reactor.rb +102 -133
  84. data/lib/puma/response.rb +532 -0
  85. data/lib/puma/runner.rb +211 -0
  86. data/lib/puma/sd_notify.rb +146 -0
  87. data/lib/puma/server.rb +582 -445
  88. data/lib/puma/server_plugin_control.rb +32 -0
  89. data/lib/puma/single.rb +72 -0
  90. data/lib/puma/state_file.rb +69 -0
  91. data/lib/puma/thread_pool.rb +389 -57
  92. data/lib/puma/util.rb +125 -0
  93. data/lib/puma.rb +80 -6
  94. data/lib/rack/handler/puma.rb +125 -47
  95. data/tools/Dockerfile +26 -0
  96. data/tools/trickletest.rb +44 -0
  97. metadata +88 -148
  98. data/COPYING +0 -55
  99. data/Gemfile +0 -10
  100. data/History.txt +0 -302
  101. data/Manifest.txt +0 -60
  102. data/Rakefile +0 -165
  103. data/TODO +0 -5
  104. data/docs/config.md +0 -0
  105. data/ext/puma_http11/ext_help.h +0 -15
  106. data/ext/puma_http11/io_buffer.c +0 -154
  107. data/lib/puma/accept_nonblock.rb +0 -23
  108. data/lib/puma/capistrano.rb +0 -34
  109. data/lib/puma/compat.rb +0 -11
  110. data/lib/puma/daemon_ext.rb +0 -20
  111. data/lib/puma/delegation.rb +0 -11
  112. data/lib/puma/java_io_buffer.rb +0 -45
  113. data/lib/puma/rack_patch.rb +0 -25
  114. data/puma.gemspec +0 -45
  115. data/test/test_app_status.rb +0 -88
  116. data/test/test_cli.rb +0 -171
  117. data/test/test_config.rb +0 -16
  118. data/test/test_http10.rb +0 -27
  119. data/test/test_http11.rb +0 -126
  120. data/test/test_integration.rb +0 -154
  121. data/test/test_iobuffer.rb +0 -38
  122. data/test/test_minissl.rb +0 -25
  123. data/test/test_null_io.rb +0 -31
  124. data/test/test_persistent.rb +0 -238
  125. data/test/test_puma_server.rb +0 -224
  126. data/test/test_rack_handler.rb +0 -10
  127. data/test/test_rack_server.rb +0 -141
  128. data/test/test_thread_pool.rb +0 -146
  129. data/test/test_unix_socket.rb +0 -39
  130. data/test/test_ws.rb +0 -89
  131. data/tools/jungle/init.d/README.md +0 -54
  132. data/tools/jungle/init.d/puma +0 -332
  133. data/tools/jungle/init.d/run-puma +0 -3
  134. data/tools/jungle/upstart/README.md +0 -61
  135. data/tools/jungle/upstart/puma-manager.conf +0 -31
  136. data/tools/jungle/upstart/puma.conf +0 -52
@@ -10,7 +10,6 @@ import org.jruby.RubyString;
10
10
 
11
11
  import org.jruby.anno.JRubyMethod;
12
12
 
13
- import org.jruby.runtime.ObjectAllocator;
14
13
  import org.jruby.runtime.ThreadContext;
15
14
  import org.jruby.runtime.builtin.IRubyObject;
16
15
 
@@ -18,208 +17,305 @@ import org.jruby.exceptions.RaiseException;
18
17
 
19
18
  import org.jruby.util.ByteList;
20
19
 
20
+ import java.util.Arrays;
21
+
22
+ import static java.util.Arrays.stream;
23
+
21
24
  /**
22
25
  * @author <a href="mailto:ola.bini@ki.se">Ola Bini</a>
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 = 1024;
34
- public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 1024 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
 
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;
40
38
 
41
- private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
42
- public IRubyObject allocate(Ruby runtime, RubyClass klass) {
43
- return new Http11(runtime, klass);
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;
44
48
  }
45
- };
49
+ }
46
50
 
47
51
  public static void createHttp11(Ruby runtime) {
48
52
  RubyModule mPuma = runtime.defineModule("Puma");
49
- mPuma.defineClassUnder("HttpParserError",runtime.getClass("IOError"),runtime.getClass("IOError").getAllocator());
53
+ mPuma.defineClassUnder("HttpParserError",runtime.getClass("StandardError"),runtime.getClass("StandardError").getAllocator());
54
+
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);
50
60
 
51
- RubyClass cHttpParser = mPuma.defineClassUnder("HttpParser",runtime.getObject(),ALLOCATOR);
61
+ RubyClass cHttpParser = mPuma.defineClassUnder("HttpParser",runtime.getObject(),(r, c) -> new Http11(r, c, envStrings));
52
62
  cHttpParser.defineAnnotatedMethods(Http11.class);
53
63
  }
54
64
 
55
- private Ruby runtime;
56
- private RubyClass eHttpParserError;
57
- 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;
58
72
  private RubyString body;
59
73
 
60
- public Http11(Ruby runtime, RubyClass clazz) {
74
+ public Http11(Ruby runtime, RubyClass clazz, RubyString[] envStrings) {
61
75
  super(runtime,clazz);
62
76
  this.runtime = runtime;
63
- this.eHttpParserError = (RubyClass)runtime.getModule("Puma").getConstant("HttpParserError");
64
77
  this.hp = new Http11Parser();
65
- this.hp.parser.http_field = http_field;
66
- this.hp.parser.request_method = request_method;
67
- this.hp.parser.request_uri = request_uri;
68
- this.hp.parser.fragment = fragment;
69
- this.hp.parser.request_path = request_path;
70
- this.hp.parser.query_string = query_string;
71
- this.hp.parser.http_version = http_version;
72
- this.hp.parser.header_done = header_done;
73
- this.hp.parser.init();
74
- }
75
-
76
- public void validateMaxLength(int len, int max, String msg) {
78
+ this.envStrings = envStrings;
79
+ this.hp.init();
80
+ }
81
+
82
+ public static void validateMaxLength(Ruby runtime, int len, int max, String msg) {
77
83
  if(len>max) {
78
- throw new RaiseException(runtime, eHttpParserError, msg, true);
84
+ throw newHTTPParserError(runtime, msg);
79
85
  }
80
86
  }
81
87
 
82
- private Http11Parser.FieldCB http_field = new Http11Parser.FieldCB() {
83
- public void call(Object data, int field, int flen, int value, int vlen) {
84
- RubyHash req = (RubyHash)data;
85
- RubyString v,f;
86
- validateMaxLength(flen, MAX_FIELD_NAME_LENGTH, MAX_FIELD_NAME_LENGTH_ERR);
87
- validateMaxLength(vlen, MAX_FIELD_VALUE_LENGTH, MAX_FIELD_VALUE_LENGTH_ERR);
88
-
89
- v = RubyString.newString(runtime, new ByteList(Http11.this.hp.parser.buffer,value,vlen));
90
- ByteList b = new ByteList(Http11.this.hp.parser.buffer,field,flen);
91
- for(int i = 0,j = b.length();i<j;i++) {
92
- if((b.get(i) & 0xFF) == '-') {
93
- b.set(i, (byte)'_');
94
- } else {
95
- b.set(i, (byte)Character.toUpperCase((char)b.get(i)));
96
- }
97
- }
98
-
99
- String as = b.toString();
100
-
101
- if(as.equals("CONTENT_LENGTH") || as.equals("CONTENT_TYPE")) {
102
- f = RubyString.newString(runtime, b);
103
- } else {
104
- f = RubyString.newString(runtime, "HTTP_");
105
- f.cat(b);
106
- }
107
- req.op_aset(req.getRuntime().getCurrentContext(), f,v);
108
- }
109
- };
88
+ private static RaiseException newHTTPParserError(Ruby runtime, String msg) {
89
+ return runtime.newRaiseException(getHTTPParserError(runtime), msg);
90
+ }
110
91
 
111
- private Http11Parser.ElementCB request_method = new Http11Parser.ElementCB() {
112
- public void call(Object data, int at, int length) {
113
- RubyHash req = (RubyHash)data;
114
- RubyString val = RubyString.newString(runtime,new ByteList(hp.parser.buffer,at,length));
115
- req.op_aset(req.getRuntime().getCurrentContext(), runtime.newString("REQUEST_METHOD"),val);
116
- }
117
- };
118
-
119
- private Http11Parser.ElementCB request_uri = new Http11Parser.ElementCB() {
120
- public void call(Object data, int at, int length) {
121
- RubyHash req = (RubyHash)data;
122
- validateMaxLength(length, MAX_REQUEST_URI_LENGTH, MAX_REQUEST_URI_LENGTH_ERR);
123
- RubyString val = RubyString.newString(runtime,new ByteList(hp.parser.buffer,at,length));
124
- req.op_aset(req.getRuntime().getCurrentContext(), runtime.newString("REQUEST_URI"),val);
125
- }
126
- };
127
-
128
- private Http11Parser.ElementCB fragment = new Http11Parser.ElementCB() {
129
- public void call(Object data, int at, int length) {
130
- RubyHash req = (RubyHash)data;
131
- validateMaxLength(length, MAX_FRAGMENT_LENGTH, MAX_FRAGMENT_LENGTH_ERR);
132
- RubyString val = RubyString.newString(runtime,new ByteList(hp.parser.buffer,at,length));
133
- req.op_aset(req.getRuntime().getCurrentContext(), runtime.newString("FRAGMENT"),val);
134
- }
135
- };
136
-
137
- private Http11Parser.ElementCB request_path = new Http11Parser.ElementCB() {
138
- public void call(Object data, int at, int length) {
139
- RubyHash req = (RubyHash)data;
140
- validateMaxLength(length, MAX_REQUEST_PATH_LENGTH, MAX_REQUEST_PATH_LENGTH_ERR);
141
- RubyString val = RubyString.newString(runtime,new ByteList(hp.parser.buffer,at,length));
142
- req.op_aset(req.getRuntime().getCurrentContext(), runtime.newString("REQUEST_PATH"),val);
143
- }
144
- };
145
-
146
- private Http11Parser.ElementCB query_string = new Http11Parser.ElementCB() {
147
- public void call(Object data, int at, int length) {
148
- RubyHash req = (RubyHash)data;
149
- validateMaxLength(length, MAX_QUERY_STRING_LENGTH, MAX_QUERY_STRING_LENGTH_ERR);
150
- RubyString val = RubyString.newString(runtime,new ByteList(hp.parser.buffer,at,length));
151
- req.op_aset(req.getRuntime().getCurrentContext(), runtime.newString("QUERY_STRING"),val);
152
- }
153
- };
92
+ private static RubyClass getHTTPParserError(Ruby runtime) {
93
+ // Cheaper to look this up lazily than cache eagerly and consume a field, since it's rarely encountered
94
+ return (RubyClass)runtime.getModule("Puma").getConstant("HttpParserError");
95
+ }
154
96
 
155
- private Http11Parser.ElementCB http_version = new Http11Parser.ElementCB() {
156
- public void call(Object data, int at, int length) {
157
- RubyHash req = (RubyHash)data;
158
- RubyString val = RubyString.newString(runtime,new ByteList(hp.parser.buffer,at,length));
159
- req.op_aset(req.getRuntime().getCurrentContext(), runtime.newString("HTTP_VERSION"),val);
160
- }
161
- };
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
+ }
162
102
 
163
- private Http11Parser.ElementCB header_done = new Http11Parser.ElementCB() {
164
- public void call(Object data, int at, int length) {
165
- body = RubyString.newString(runtime, new ByteList(hp.parser.buffer, at, length));
166
- }
167
- };
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) {
112
+ RubyString f;
113
+ IRubyObject v;
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);
124
+ }
125
+
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;
137
+ v = req.fastARef(f);
138
+ if (v == null || v.isNil()) {
139
+ req.fastASet(f, RubyString.newStringShared(runtime, buffer, mark, vlen));
140
+ } else {
141
+ RubyString vs = v.convertToString();
142
+ vs.cat(COMMA_SPACE_BYTELIST);
143
+ vs.cat(buffer, mark, vlen);
144
+ }
145
+ }
146
+
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);
152
+ }
153
+
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
+ }
162
+ }
163
+
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;
172
+ }
173
+
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));
176
+ }
177
+
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));
196
+ }
197
+
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));
200
+ }
201
+
202
+ public void header_done(Ruby runtime, Http11Parser hp, int at, int length) {
203
+ body = RubyString.newStringShared(runtime, hp.buffer, at, length);
204
+ }
168
205
 
169
206
  @JRubyMethod
170
207
  public IRubyObject initialize() {
171
- this.hp.parser.init();
208
+ this.hp.init();
172
209
  return this;
173
210
  }
174
211
 
175
212
  @JRubyMethod
176
- public IRubyObject reset() {
177
- this.hp.parser.init();
178
- return runtime.getNil();
213
+ public IRubyObject reset(ThreadContext context) {
214
+ this.hp.init();
215
+ return context.nil;
179
216
  }
180
217
 
181
218
  @JRubyMethod
182
- public IRubyObject finish() {
183
- this.hp.finish();
184
- 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;
185
223
  }
186
224
 
187
225
  @JRubyMethod
188
226
  public IRubyObject execute(IRubyObject req_hash, IRubyObject data, IRubyObject start) {
189
- int from = 0;
190
- from = RubyNumeric.fix2int(start);
191
- ByteList d = ((RubyString)data).getByteList();
227
+ Ruby runtime = this.runtime;
228
+ int from = RubyNumeric.fix2int(start);
229
+ RubyString dataString = (RubyString) data;
230
+ dataString.setByteListShared();
231
+ ByteList d = dataString.getByteList();
192
232
  if(from >= d.length()) {
193
- throw new RaiseException(runtime, eHttpParserError, "Requested start is after data buffer end.", true);
233
+ throw newHTTPParserError(runtime, "Requested start is after data buffer end.");
194
234
  } else {
195
- this.hp.parser.data = req_hash;
196
- this.hp.execute(d,from);
197
- validateMaxLength(this.hp.parser.nread,MAX_HEADER_LENGTH, MAX_HEADER_LENGTH_ERR);
198
- if(this.hp.has_error()) {
199
- throw new RaiseException(runtime, eHttpParserError, "Invalid HTTP format, parsing fails.", true);
235
+ Http11Parser hp = this.hp;
236
+
237
+ hp.data = (RubyHash) req_hash;
238
+
239
+ hp.execute(runtime, this, d,from);
240
+
241
+ validateMaxHeaderLength(runtime, hp);
242
+
243
+ if(hp.has_error()) {
244
+ throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?");
200
245
  } else {
201
- return runtime.newFixnum(this.hp.parser.nread);
246
+ return runtime.newFixnum(hp.nread);
202
247
  }
203
248
  }
204
249
  }
205
250
 
206
251
  @JRubyMethod(name = "error?")
207
- public IRubyObject has_error() {
208
- 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;
209
254
  }
210
255
 
211
256
  @JRubyMethod(name = "finished?")
212
- public IRubyObject is_finished() {
213
- 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;
214
259
  }
215
260
 
216
261
  @JRubyMethod
217
262
  public IRubyObject nread() {
218
- return runtime.newFixnum(this.hp.parser.nread);
263
+ return runtime.newFixnum(this.hp.nread);
219
264
  }
220
-
265
+
221
266
  @JRubyMethod
222
267
  public IRubyObject body() {
223
268
  return body;
224
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
+ }
225
321
  }// Http11