puma 5.6.4 → 6.4.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +372 -6
  3. data/LICENSE +0 -0
  4. data/README.md +79 -29
  5. data/bin/puma-wild +1 -1
  6. data/docs/architecture.md +0 -0
  7. data/docs/compile_options.md +34 -0
  8. data/docs/deployment.md +0 -0
  9. data/docs/fork_worker.md +1 -3
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +12 -0
  17. data/docs/nginx.md +1 -1
  18. data/docs/plugins.md +0 -0
  19. data/docs/rails_dev_mode.md +0 -0
  20. data/docs/restart.md +1 -0
  21. data/docs/signals.md +0 -0
  22. data/docs/stats.md +0 -0
  23. data/docs/systemd.md +3 -6
  24. data/docs/testing_benchmarks_local_files.md +150 -0
  25. data/docs/testing_test_rackup_ci_files.md +36 -0
  26. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  27. data/ext/puma_http11/ext_help.h +0 -0
  28. data/ext/puma_http11/extconf.rb +22 -10
  29. data/ext/puma_http11/http11_parser.c +1 -1
  30. data/ext/puma_http11/http11_parser.h +1 -1
  31. data/ext/puma_http11/http11_parser.java.rl +2 -2
  32. data/ext/puma_http11/http11_parser.rl +2 -2
  33. data/ext/puma_http11/http11_parser_common.rl +2 -2
  34. data/ext/puma_http11/mini_ssl.c +153 -27
  35. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  37. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
  38. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +167 -65
  39. data/ext/puma_http11/puma_http11.c +17 -9
  40. data/lib/puma/app/status.rb +7 -4
  41. data/lib/puma/binder.rb +51 -54
  42. data/lib/puma/cli.rb +16 -18
  43. data/lib/puma/client.rb +100 -26
  44. data/lib/puma/cluster/worker.rb +18 -11
  45. data/lib/puma/cluster/worker_handle.rb +4 -1
  46. data/lib/puma/cluster.rb +102 -40
  47. data/lib/puma/commonlogger.rb +21 -14
  48. data/lib/puma/configuration.rb +77 -59
  49. data/lib/puma/const.rb +129 -92
  50. data/lib/puma/control_cli.rb +33 -23
  51. data/lib/puma/detect.rb +7 -4
  52. data/lib/puma/dsl.rb +251 -53
  53. data/lib/puma/error_logger.rb +18 -9
  54. data/lib/puma/events.rb +6 -126
  55. data/lib/puma/io_buffer.rb +39 -4
  56. data/lib/puma/jruby_restart.rb +2 -1
  57. data/lib/puma/json_serialization.rb +0 -0
  58. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  59. data/lib/puma/launcher.rb +113 -175
  60. data/lib/puma/log_writer.rb +147 -0
  61. data/lib/puma/minissl/context_builder.rb +26 -12
  62. data/lib/puma/minissl.rb +113 -15
  63. data/lib/puma/null_io.rb +21 -2
  64. data/lib/puma/plugin/systemd.rb +90 -0
  65. data/lib/puma/plugin/tmp_restart.rb +1 -1
  66. data/lib/puma/plugin.rb +0 -0
  67. data/lib/puma/rack/builder.rb +6 -6
  68. data/lib/puma/rack/urlmap.rb +1 -1
  69. data/lib/puma/rack_default.rb +19 -4
  70. data/lib/puma/reactor.rb +19 -10
  71. data/lib/puma/request.rb +365 -166
  72. data/lib/puma/runner.rb +56 -20
  73. data/lib/puma/sd_notify.rb +149 -0
  74. data/lib/puma/server.rb +137 -87
  75. data/lib/puma/single.rb +13 -11
  76. data/lib/puma/state_file.rb +4 -6
  77. data/lib/puma/thread_pool.rb +57 -19
  78. data/lib/puma/util.rb +12 -14
  79. data/lib/puma.rb +12 -11
  80. data/lib/rack/handler/puma.rb +113 -86
  81. data/tools/Dockerfile +2 -2
  82. data/tools/trickletest.rb +0 -0
  83. metadata +11 -6
  84. data/lib/puma/queue_close.rb +0 -26
  85. data/lib/puma/systemd.rb +0 -46
@@ -1,6 +1,7 @@
1
1
  package org.jruby.puma;
2
2
 
3
3
  import org.jruby.Ruby;
4
+ import org.jruby.RubyArray;
4
5
  import org.jruby.RubyClass;
5
6
  import org.jruby.RubyModule;
6
7
  import org.jruby.RubyObject;
@@ -15,6 +16,7 @@ import org.jruby.runtime.builtin.IRubyObject;
15
16
  import org.jruby.util.ByteList;
16
17
 
17
18
  import javax.net.ssl.KeyManagerFactory;
19
+ import javax.net.ssl.TrustManager;
18
20
  import javax.net.ssl.TrustManagerFactory;
19
21
  import javax.net.ssl.SSLContext;
20
22
  import javax.net.ssl.SSLEngine;
@@ -22,6 +24,7 @@ import javax.net.ssl.SSLEngineResult;
22
24
  import javax.net.ssl.SSLException;
23
25
  import javax.net.ssl.SSLPeerUnverifiedException;
24
26
  import javax.net.ssl.SSLSession;
27
+ import javax.net.ssl.X509TrustManager;
25
28
  import java.io.FileInputStream;
26
29
  import java.io.InputStream;
27
30
  import java.io.IOException;
@@ -32,15 +35,19 @@ import java.security.KeyStore;
32
35
  import java.security.KeyStoreException;
33
36
  import java.security.NoSuchAlgorithmException;
34
37
  import java.security.UnrecoverableKeyException;
38
+ import java.security.cert.Certificate;
35
39
  import java.security.cert.CertificateEncodingException;
36
40
  import java.security.cert.CertificateException;
41
+ import java.security.cert.X509Certificate;
37
42
  import java.util.concurrent.ConcurrentHashMap;
38
43
  import java.util.Map;
44
+ import java.util.function.Supplier;
39
45
 
40
46
  import static javax.net.ssl.SSLEngineResult.Status;
41
47
  import static javax.net.ssl.SSLEngineResult.HandshakeStatus;
42
48
 
43
- public class MiniSSL extends RubyObject {
49
+ public class MiniSSL extends RubyObject { // MiniSSL::Engine
50
+ private static final long serialVersionUID = -6903439483039141234L;
44
51
  private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
45
52
  public IRubyObject allocate(Ruby runtime, RubyClass klass) {
46
53
  return new MiniSSL(runtime, klass);
@@ -51,11 +58,10 @@ public class MiniSSL extends RubyObject {
51
58
  RubyModule mPuma = runtime.defineModule("Puma");
52
59
  RubyModule ssl = mPuma.defineModuleUnder("MiniSSL");
53
60
 
54
- mPuma.defineClassUnder("SSLError",
55
- runtime.getClass("IOError"),
56
- runtime.getClass("IOError").getAllocator());
61
+ // Puma::MiniSSL::SSLError
62
+ ssl.defineClassUnder("SSLError", runtime.getStandardError(), runtime.getStandardError().getAllocator());
57
63
 
58
- RubyClass eng = ssl.defineClassUnder("Engine",runtime.getObject(),ALLOCATOR);
64
+ RubyClass eng = ssl.defineClassUnder("Engine", runtime.getObject(), ALLOCATOR);
59
65
  eng.defineAnnotatedMethods(MiniSSL.class);
60
66
  }
61
67
 
@@ -137,74 +143,116 @@ public class MiniSSL extends RubyObject {
137
143
  private static Map<String, KeyManagerFactory> keyManagerFactoryMap = new ConcurrentHashMap<String, KeyManagerFactory>();
138
144
  private static Map<String, TrustManagerFactory> trustManagerFactoryMap = new ConcurrentHashMap<String, TrustManagerFactory>();
139
145
 
140
- @JRubyMethod(meta = true)
146
+ @JRubyMethod(meta = true) // Engine.server
141
147
  public static synchronized IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext)
142
148
  throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
143
149
  // Create the KeyManagerFactory and TrustManagerFactory for this server
144
- String keystoreFile = miniSSLContext.callMethod(context, "keystore").convertToString().asJavaString();
145
- char[] password = miniSSLContext.callMethod(context, "keystore_pass").convertToString().asJavaString().toCharArray();
150
+ String keystoreFile = asStringValue(miniSSLContext.callMethod(context, "keystore"), null);
151
+ char[] keystorePass = asStringValue(miniSSLContext.callMethod(context, "keystore_pass"), null).toCharArray();
152
+ String keystoreType = asStringValue(miniSSLContext.callMethod(context, "keystore_type"), KeyStore::getDefaultType);
153
+
154
+ String truststoreFile;
155
+ char[] truststorePass;
156
+ String truststoreType;
157
+ IRubyObject truststore = miniSSLContext.callMethod(context, "truststore");
158
+ if (truststore.isNil()) {
159
+ truststoreFile = keystoreFile;
160
+ truststorePass = keystorePass;
161
+ truststoreType = keystoreType;
162
+ } else if (!isDefaultSymbol(context, truststore)) {
163
+ truststoreFile = truststore.convertToString().asJavaString();
164
+ IRubyObject pass = miniSSLContext.callMethod(context, "truststore_pass");
165
+ if (pass.isNil()) {
166
+ truststorePass = null;
167
+ } else {
168
+ truststorePass = asStringValue(pass, null).toCharArray();
169
+ }
170
+ truststoreType = asStringValue(miniSSLContext.callMethod(context, "truststore_type"), KeyStore::getDefaultType);
171
+ } else { // self.truststore = :default
172
+ truststoreFile = null;
173
+ truststorePass = null;
174
+ truststoreType = null;
175
+ }
146
176
 
147
- KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
177
+ KeyStore ks = KeyStore.getInstance(keystoreType);
148
178
  InputStream is = new FileInputStream(keystoreFile);
149
179
  try {
150
- ks.load(is, password);
180
+ ks.load(is, keystorePass);
151
181
  } finally {
152
182
  is.close();
153
183
  }
154
184
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
155
- kmf.init(ks, password);
185
+ kmf.init(ks, keystorePass);
156
186
  keyManagerFactoryMap.put(keystoreFile, kmf);
157
187
 
158
- KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
159
- is = new FileInputStream(keystoreFile);
160
- try {
161
- ts.load(is, password);
162
- } finally {
163
- is.close();
188
+ if (truststoreFile != null) {
189
+ KeyStore ts = KeyStore.getInstance(truststoreType);
190
+ is = new FileInputStream(truststoreFile);
191
+ try {
192
+ ts.load(is, truststorePass);
193
+ } finally {
194
+ is.close();
195
+ }
196
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
197
+ tmf.init(ts);
198
+ trustManagerFactoryMap.put(truststoreFile, tmf);
164
199
  }
165
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
166
- tmf.init(ts);
167
- trustManagerFactoryMap.put(keystoreFile, tmf);
168
200
 
169
201
  RubyClass klass = (RubyClass) recv;
170
- return klass.newInstance(context,
171
- new IRubyObject[] { miniSSLContext },
172
- Block.NULL_BLOCK);
202
+ return klass.newInstance(context, miniSSLContext, Block.NULL_BLOCK);
203
+ }
204
+
205
+ private static String asStringValue(IRubyObject value, Supplier<String> defaultValue) {
206
+ if (defaultValue != null && value.isNil()) return defaultValue.get();
207
+ return value.convertToString().asJavaString();
208
+ }
209
+
210
+ private static boolean isDefaultSymbol(ThreadContext context, IRubyObject truststore) {
211
+ return context.runtime.newSymbol("default").equals(truststore);
173
212
  }
174
213
 
175
214
  @JRubyMethod
176
- public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
215
+ public IRubyObject initialize(ThreadContext context, IRubyObject miniSSLContext)
177
216
  throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
178
217
 
179
- String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
218
+ String keystoreFile = miniSSLContext.callMethod(context, "keystore").convertToString().asJavaString();
180
219
  KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
181
- TrustManagerFactory tmf = trustManagerFactoryMap.get(keystoreFile);
182
- if(kmf == null || tmf == null) {
183
- throw new KeyStoreException("Could not find KeyManagerFactory/TrustManagerFactory for keystore: " + keystoreFile);
220
+ IRubyObject truststore = miniSSLContext.callMethod(context, "truststore");
221
+ String truststoreFile = isDefaultSymbol(context, truststore) ? "" : asStringValue(truststore, () -> keystoreFile);
222
+ TrustManagerFactory tmf = trustManagerFactoryMap.get(truststoreFile); // null if self.truststore = :default
223
+ if (kmf == null) {
224
+ throw new KeyStoreException("Could not find KeyManagerFactory for keystore: " + keystoreFile + " truststore: " + truststoreFile);
184
225
  }
185
226
 
186
227
  SSLContext sslCtx = SSLContext.getInstance("TLS");
187
228
 
188
- sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
229
+ sslCtx.init(kmf.getKeyManagers(), getTrustManagers(tmf), null);
189
230
  closed = false;
190
231
  handshake = false;
191
232
  engine = sslCtx.createSSLEngine();
192
233
 
193
- String[] protocols;
194
- if(miniSSLContext.callMethod(threadContext, "no_tlsv1").isTrue()) {
195
- protocols = new String[] { "TLSv1.1", "TLSv1.2" };
196
- } else {
197
- protocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" };
198
- }
234
+ String[] enabledProtocols;
235
+ IRubyObject protocols = miniSSLContext.callMethod(context, "protocols");
236
+ if (protocols.isNil()) {
237
+ if (miniSSLContext.callMethod(context, "no_tlsv1").isTrue()) {
238
+ enabledProtocols = new String[] { "TLSv1.1", "TLSv1.2", "TLSv1.3" };
239
+ } else {
240
+ enabledProtocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" };
241
+ }
199
242
 
200
- if(miniSSLContext.callMethod(threadContext, "no_tlsv1_1").isTrue()) {
201
- protocols = new String[] { "TLSv1.2" };
243
+ if (miniSSLContext.callMethod(context, "no_tlsv1_1").isTrue()) {
244
+ enabledProtocols = new String[] { "TLSv1.2", "TLSv1.3" };
245
+ }
246
+ } else if (protocols instanceof RubyArray) {
247
+ enabledProtocols = (String[]) ((RubyArray) protocols).toArray(new String[0]);
248
+ } else {
249
+ throw context.runtime.newTypeError(protocols, context.runtime.getArray());
202
250
  }
251
+ engine.setEnabledProtocols(enabledProtocols);
203
252
 
204
- engine.setEnabledProtocols(protocols);
205
253
  engine.setUseClientMode(false);
206
254
 
207
- long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger("to_i").getLongValue();
255
+ long verify_mode = miniSSLContext.callMethod(context, "verify_mode").convertToInteger("to_i").getLongValue();
208
256
  if ((verify_mode & 0x1) != 0) { // 'peer'
209
257
  engine.setWantClientAuth(true);
210
258
  }
@@ -212,10 +260,11 @@ public class MiniSSL extends RubyObject {
212
260
  engine.setNeedClientAuth(true);
213
261
  }
214
262
 
215
- IRubyObject sslCipherListObject = miniSSLContext.callMethod(threadContext, "ssl_cipher_list");
216
- if (!sslCipherListObject.isNil()) {
217
- String[] sslCipherList = sslCipherListObject.convertToString().asJavaString().split(",");
218
- engine.setEnabledCipherSuites(sslCipherList);
263
+ IRubyObject cipher_suites = miniSSLContext.callMethod(context, "cipher_suites");
264
+ if (cipher_suites instanceof RubyArray) {
265
+ engine.setEnabledCipherSuites((String[]) ((RubyArray) cipher_suites).toArray(new String[0]));
266
+ } else if (!cipher_suites.isNil()) {
267
+ throw context.runtime.newTypeError(cipher_suites, context.runtime.getArray());
219
268
  }
220
269
 
221
270
  SSLSession session = engine.getSession();
@@ -227,6 +276,48 @@ public class MiniSSL extends RubyObject {
227
276
  return this;
228
277
  }
229
278
 
279
+ private TrustManager[] getTrustManagers(TrustManagerFactory factory) {
280
+ if (factory == null) return null; // use JDK trust defaults
281
+ final TrustManager[] tms = factory.getTrustManagers();
282
+ if (tms != null) {
283
+ for (int i=0; i<tms.length; i++) {
284
+ final TrustManager tm = tms[i];
285
+ if (tm instanceof X509TrustManager) {
286
+ tms[i] = new TrustManagerWrapper((X509TrustManager) tm);
287
+ }
288
+ }
289
+ }
290
+ return tms;
291
+ }
292
+
293
+ private volatile transient X509Certificate lastCheckedCert0;
294
+
295
+ private class TrustManagerWrapper implements X509TrustManager {
296
+
297
+ private final X509TrustManager delegate;
298
+
299
+ TrustManagerWrapper(X509TrustManager delegate) {
300
+ this.delegate = delegate;
301
+ }
302
+
303
+ @Override
304
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
305
+ lastCheckedCert0 = chain.length > 0 ? chain[0] : null;
306
+ delegate.checkClientTrusted(chain, authType);
307
+ }
308
+
309
+ @Override
310
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
311
+ delegate.checkServerTrusted(chain, authType);
312
+ }
313
+
314
+ @Override
315
+ public X509Certificate[] getAcceptedIssuers() {
316
+ return delegate.getAcceptedIssuers();
317
+ }
318
+
319
+ }
320
+
230
321
  @JRubyMethod
231
322
  public IRubyObject inject(IRubyObject arg) {
232
323
  ByteList bytes = arg.convertToString().getByteList();
@@ -251,7 +342,7 @@ public class MiniSSL extends RubyObject {
251
342
  res = engine.unwrap(src.getRawBuffer(), dst.getRawBuffer());
252
343
  break;
253
344
  default:
254
- throw new IllegalStateException("Unknown SSLOperation: " + sslOp);
345
+ throw new AssertionError("Unknown SSLOperation: " + sslOp);
255
346
  }
256
347
 
257
348
  switch (res.getStatus()) {
@@ -279,14 +370,6 @@ public class MiniSSL extends RubyObject {
279
370
  }
280
371
  }
281
372
 
282
- // after each op, run any delegated tasks if needed
283
- if(res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
284
- Runnable runnable;
285
- while ((runnable = engine.getDelegatedTask()) != null) {
286
- runnable.run();
287
- }
288
- }
289
-
290
373
  return res;
291
374
  }
292
375
 
@@ -304,11 +387,12 @@ public class MiniSSL extends RubyObject {
304
387
 
305
388
  HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
306
389
  boolean done = false;
307
- SSLEngineResult res = null;
308
390
  while (!done) {
391
+ SSLEngineResult res;
309
392
  switch (handshakeStatus) {
310
393
  case NEED_WRAP:
311
394
  res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
395
+ handshakeStatus = res.getHandshakeStatus();
312
396
  break;
313
397
  case NEED_UNWRAP:
314
398
  res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
@@ -316,13 +400,18 @@ public class MiniSSL extends RubyObject {
316
400
  // need more data before we can shake more hands
317
401
  done = true;
318
402
  }
403
+ handshakeStatus = res.getHandshakeStatus();
404
+ break;
405
+ case NEED_TASK:
406
+ Runnable runnable;
407
+ while ((runnable = engine.getDelegatedTask()) != null) {
408
+ runnable.run();
409
+ }
410
+ handshakeStatus = engine.getHandshakeStatus();
319
411
  break;
320
412
  default:
321
413
  done = true;
322
414
  }
323
- if (!done) {
324
- handshakeStatus = res.getHandshakeStatus();
325
- }
326
415
  }
327
416
 
328
417
  if (inboundNetData.hasRemaining()) {
@@ -338,9 +427,7 @@ public class MiniSSL extends RubyObject {
338
427
 
339
428
  return RubyString.newString(getRuntime(), appDataByteList);
340
429
  } catch (SSLException e) {
341
- RaiseException re = getRuntime().newEOFError(e.getMessage());
342
- re.initCause(e);
343
- throw re;
430
+ throw newSSLError(getRuntime(), e);
344
431
  }
345
432
  }
346
433
 
@@ -373,19 +460,19 @@ public class MiniSSL extends RubyObject {
373
460
 
374
461
  return RubyString.newString(context.runtime, dataByteList);
375
462
  } catch (SSLException e) {
376
- RaiseException ex = context.runtime.newRuntimeError(e.toString());
377
- ex.initCause(e);
378
- throw ex;
463
+ throw newSSLError(getRuntime(), e);
379
464
  }
380
465
  }
381
466
 
382
467
  @JRubyMethod
383
- public IRubyObject peercert() throws CertificateEncodingException {
468
+ public IRubyObject peercert(ThreadContext context) throws CertificateEncodingException {
469
+ Certificate peerCert;
384
470
  try {
385
- return JavaEmbedUtils.javaToRuby(getRuntime(), engine.getSession().getPeerCertificates()[0].getEncoded());
471
+ peerCert = engine.getSession().getPeerCertificates()[0];
386
472
  } catch (SSLPeerUnverifiedException e) {
387
- return getRuntime().getNil();
473
+ peerCert = lastCheckedCert0; // null if trust check did not happen
388
474
  }
475
+ return peerCert == null ? context.nil : JavaEmbedUtils.javaToRuby(context.runtime, peerCert.getEncoded());
389
476
  }
390
477
 
391
478
  @JRubyMethod(name = "init?")
@@ -404,4 +491,19 @@ public class MiniSSL extends RubyObject {
404
491
  return getRuntime().getFalse();
405
492
  }
406
493
  }
494
+
495
+ private static RubyClass getSSLError(Ruby runtime) {
496
+ return (RubyClass) ((RubyModule) runtime.getModule("Puma").getConstantAt("MiniSSL")).getConstantAt("SSLError");
497
+ }
498
+
499
+ private static RaiseException newSSLError(Ruby runtime, SSLException cause) {
500
+ return newError(runtime, getSSLError(runtime), cause.toString(), cause);
501
+ }
502
+
503
+ private static RaiseException newError(Ruby runtime, RubyClass errorClass, String message, Throwable cause) {
504
+ RaiseException ex = RaiseException.from(runtime, errorClass, message);
505
+ ex.initCause(cause);
506
+ return ex;
507
+ }
508
+
407
509
  }
@@ -36,13 +36,13 @@ static VALUE global_request_method;
36
36
  static VALUE global_request_uri;
37
37
  static VALUE global_fragment;
38
38
  static VALUE global_query_string;
39
- static VALUE global_http_version;
39
+ static VALUE global_server_protocol;
40
40
  static VALUE global_request_path;
41
41
 
42
42
  /** Defines common length and error messages for input length validation. */
43
43
  #define QUOTE(s) #s
44
- #define EXPLAIN_MAX_LENGTH_VALUE(s) QUOTE(s)
45
- #define DEF_MAX_LENGTH(N,length) const size_t MAX_##N##_LENGTH = length; const char *MAX_##N##_LENGTH_ERR = "HTTP element " # N " is longer than the " EXPLAIN_MAX_LENGTH_VALUE(length) " allowed length (was %d)"
44
+ #define EXPAND_MAX_LENGTH_VALUE(s) QUOTE(s)
45
+ #define DEF_MAX_LENGTH(N,length) const size_t MAX_##N##_LENGTH = length; const char *MAX_##N##_LENGTH_ERR = "HTTP element " # N " is longer than the " EXPAND_MAX_LENGTH_VALUE(length) " allowed length (was %d)"
46
46
 
47
47
  /** Validates the max length of given input and throws an HttpParserError exception if over. */
48
48
  #define VALIDATE_MAX_LENGTH(len, N) if(len > MAX_##N##_LENGTH) { rb_raise(eHttpParserError, MAX_##N##_LENGTH_ERR, len); }
@@ -52,15 +52,23 @@ static VALUE global_request_path;
52
52
 
53
53
 
54
54
  /* Defines the maximum allowed lengths for various input elements.*/
55
+ #ifndef PUMA_REQUEST_URI_MAX_LENGTH
56
+ #define PUMA_REQUEST_URI_MAX_LENGTH (1024 * 12)
57
+ #endif
58
+
59
+ #ifndef PUMA_REQUEST_PATH_MAX_LENGTH
60
+ #define PUMA_REQUEST_PATH_MAX_LENGTH (8192)
61
+ #endif
62
+
55
63
  #ifndef PUMA_QUERY_STRING_MAX_LENGTH
56
64
  #define PUMA_QUERY_STRING_MAX_LENGTH (1024 * 10)
57
65
  #endif
58
66
 
59
67
  DEF_MAX_LENGTH(FIELD_NAME, 256);
60
68
  DEF_MAX_LENGTH(FIELD_VALUE, 80 * 1024);
61
- DEF_MAX_LENGTH(REQUEST_URI, 1024 * 12);
69
+ DEF_MAX_LENGTH(REQUEST_URI, PUMA_REQUEST_URI_MAX_LENGTH);
62
70
  DEF_MAX_LENGTH(FRAGMENT, 1024); /* Don't know if this length is specified somewhere or not */
63
- DEF_MAX_LENGTH(REQUEST_PATH, 8192);
71
+ DEF_MAX_LENGTH(REQUEST_PATH, PUMA_REQUEST_PATH_MAX_LENGTH);
64
72
  DEF_MAX_LENGTH(QUERY_STRING, PUMA_QUERY_STRING_MAX_LENGTH);
65
73
  DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
66
74
 
@@ -236,10 +244,10 @@ void query_string(puma_parser* hp, const char *at, size_t length)
236
244
  rb_hash_aset(hp->request, global_query_string, val);
237
245
  }
238
246
 
239
- void http_version(puma_parser* hp, const char *at, size_t length)
247
+ void server_protocol(puma_parser* hp, const char *at, size_t length)
240
248
  {
241
249
  VALUE val = rb_str_new(at, length);
242
- rb_hash_aset(hp->request, global_http_version, val);
250
+ rb_hash_aset(hp->request, global_server_protocol, val);
243
251
  }
244
252
 
245
253
  /** Finalizes the request header to have a bunch of stuff that's
@@ -281,7 +289,7 @@ VALUE HttpParser_alloc(VALUE klass)
281
289
  hp->fragment = fragment;
282
290
  hp->request_path = request_path;
283
291
  hp->query_string = query_string;
284
- hp->http_version = http_version;
292
+ hp->server_protocol = server_protocol;
285
293
  hp->header_done = header_done;
286
294
  hp->request = Qnil;
287
295
 
@@ -461,7 +469,7 @@ void Init_puma_http11(void)
461
469
  DEF_GLOBAL(request_uri, "REQUEST_URI");
462
470
  DEF_GLOBAL(fragment, "FRAGMENT");
463
471
  DEF_GLOBAL(query_string, "QUERY_STRING");
464
- DEF_GLOBAL(http_version, "HTTP_VERSION");
472
+ DEF_GLOBAL(server_protocol, "SERVER_PROTOCOL");
465
473
  DEF_GLOBAL(request_path, "REQUEST_PATH");
466
474
 
467
475
  eHttpParserError = rb_define_class_under(mPuma, "HttpParserError", rb_eIOError);
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'puma/json_serialization'
2
+ require_relative '../json_serialization'
3
3
 
4
4
  module Puma
5
5
  module App
@@ -39,6 +39,9 @@ module Puma
39
39
  when 'phased-restart'
40
40
  @launcher.phased_restart ? 200 : 404
41
41
 
42
+ when 'refork'
43
+ @launcher.refork ? 200 : 404
44
+
42
45
  when 'reload-worker-directory'
43
46
  @launcher.send(:reload_worker_directory) ? 200 : 404
44
47
 
@@ -77,13 +80,13 @@ module Puma
77
80
 
78
81
  def authenticate(env)
79
82
  return true unless @auth_token
80
- env['QUERY_STRING'].to_s.split(/&;/).include?("token=#{@auth_token}")
83
+ env['QUERY_STRING'].to_s.split('&;').include? "token=#{@auth_token}"
81
84
  end
82
85
 
83
86
  def rack_response(status, body, content_type='application/json')
84
87
  headers = {
85
- 'Content-Type' => content_type,
86
- 'Content-Length' => body.bytesize.to_s
88
+ 'content-type' => content_type,
89
+ 'content-length' => body.bytesize.to_s
87
90
  }
88
91
 
89
92
  [status, headers, [body]]