puma 5.6.4 → 6.3.0

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 +270 -4
  3. data/LICENSE +0 -0
  4. data/README.md +60 -20
  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 +0 -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 +0 -0
  21. data/docs/signals.md +0 -0
  22. data/docs/stats.md +0 -0
  23. data/docs/systemd.md +1 -2
  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 +18 -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 +93 -26
  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 +166 -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 +49 -52
  42. data/lib/puma/cli.rb +12 -18
  43. data/lib/puma/client.rb +55 -16
  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 +33 -30
  47. data/lib/puma/commonlogger.rb +21 -14
  48. data/lib/puma/configuration.rb +76 -58
  49. data/lib/puma/const.rb +129 -92
  50. data/lib/puma/control_cli.rb +21 -18
  51. data/lib/puma/detect.rb +4 -0
  52. data/lib/puma/dsl.rb +187 -49
  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 +24 -12
  62. data/lib/puma/minissl.rb +108 -15
  63. data/lib/puma/null_io.rb +5 -0
  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 +0 -0
  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 +52 -20
  73. data/lib/puma/sd_notify.rb +149 -0
  74. data/lib/puma/server.rb +73 -73
  75. data/lib/puma/single.rb +13 -11
  76. data/lib/puma/state_file.rb +2 -4
  77. data/lib/puma/thread_pool.rb +23 -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 +0 -0
  82. data/tools/trickletest.rb +0 -0
  83. metadata +10 -5
  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,18 @@ 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
44
50
  private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
45
51
  public IRubyObject allocate(Ruby runtime, RubyClass klass) {
46
52
  return new MiniSSL(runtime, klass);
@@ -51,11 +57,10 @@ public class MiniSSL extends RubyObject {
51
57
  RubyModule mPuma = runtime.defineModule("Puma");
52
58
  RubyModule ssl = mPuma.defineModuleUnder("MiniSSL");
53
59
 
54
- mPuma.defineClassUnder("SSLError",
55
- runtime.getClass("IOError"),
56
- runtime.getClass("IOError").getAllocator());
60
+ // Puma::MiniSSL::SSLError
61
+ ssl.defineClassUnder("SSLError", runtime.getStandardError(), runtime.getStandardError().getAllocator());
57
62
 
58
- RubyClass eng = ssl.defineClassUnder("Engine",runtime.getObject(),ALLOCATOR);
63
+ RubyClass eng = ssl.defineClassUnder("Engine", runtime.getObject(), ALLOCATOR);
59
64
  eng.defineAnnotatedMethods(MiniSSL.class);
60
65
  }
61
66
 
@@ -137,74 +142,116 @@ public class MiniSSL extends RubyObject {
137
142
  private static Map<String, KeyManagerFactory> keyManagerFactoryMap = new ConcurrentHashMap<String, KeyManagerFactory>();
138
143
  private static Map<String, TrustManagerFactory> trustManagerFactoryMap = new ConcurrentHashMap<String, TrustManagerFactory>();
139
144
 
140
- @JRubyMethod(meta = true)
145
+ @JRubyMethod(meta = true) // Engine.server
141
146
  public static synchronized IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext)
142
147
  throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
143
148
  // 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();
149
+ String keystoreFile = asStringValue(miniSSLContext.callMethod(context, "keystore"), null);
150
+ char[] keystorePass = asStringValue(miniSSLContext.callMethod(context, "keystore_pass"), null).toCharArray();
151
+ String keystoreType = asStringValue(miniSSLContext.callMethod(context, "keystore_type"), KeyStore::getDefaultType);
152
+
153
+ String truststoreFile;
154
+ char[] truststorePass;
155
+ String truststoreType;
156
+ IRubyObject truststore = miniSSLContext.callMethod(context, "truststore");
157
+ if (truststore.isNil()) {
158
+ truststoreFile = keystoreFile;
159
+ truststorePass = keystorePass;
160
+ truststoreType = keystoreType;
161
+ } else if (!isDefaultSymbol(context, truststore)) {
162
+ truststoreFile = truststore.convertToString().asJavaString();
163
+ IRubyObject pass = miniSSLContext.callMethod(context, "truststore_pass");
164
+ if (pass.isNil()) {
165
+ truststorePass = null;
166
+ } else {
167
+ truststorePass = asStringValue(pass, null).toCharArray();
168
+ }
169
+ truststoreType = asStringValue(miniSSLContext.callMethod(context, "truststore_type"), KeyStore::getDefaultType);
170
+ } else { // self.truststore = :default
171
+ truststoreFile = null;
172
+ truststorePass = null;
173
+ truststoreType = null;
174
+ }
146
175
 
147
- KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
176
+ KeyStore ks = KeyStore.getInstance(keystoreType);
148
177
  InputStream is = new FileInputStream(keystoreFile);
149
178
  try {
150
- ks.load(is, password);
179
+ ks.load(is, keystorePass);
151
180
  } finally {
152
181
  is.close();
153
182
  }
154
183
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
155
- kmf.init(ks, password);
184
+ kmf.init(ks, keystorePass);
156
185
  keyManagerFactoryMap.put(keystoreFile, kmf);
157
186
 
158
- KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
159
- is = new FileInputStream(keystoreFile);
160
- try {
161
- ts.load(is, password);
162
- } finally {
163
- is.close();
187
+ if (truststoreFile != null) {
188
+ KeyStore ts = KeyStore.getInstance(truststoreType);
189
+ is = new FileInputStream(truststoreFile);
190
+ try {
191
+ ts.load(is, truststorePass);
192
+ } finally {
193
+ is.close();
194
+ }
195
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
196
+ tmf.init(ts);
197
+ trustManagerFactoryMap.put(truststoreFile, tmf);
164
198
  }
165
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
166
- tmf.init(ts);
167
- trustManagerFactoryMap.put(keystoreFile, tmf);
168
199
 
169
200
  RubyClass klass = (RubyClass) recv;
170
- return klass.newInstance(context,
171
- new IRubyObject[] { miniSSLContext },
172
- Block.NULL_BLOCK);
201
+ return klass.newInstance(context, miniSSLContext, Block.NULL_BLOCK);
202
+ }
203
+
204
+ private static String asStringValue(IRubyObject value, Supplier<String> defaultValue) {
205
+ if (defaultValue != null && value.isNil()) return defaultValue.get();
206
+ return value.convertToString().asJavaString();
207
+ }
208
+
209
+ private static boolean isDefaultSymbol(ThreadContext context, IRubyObject truststore) {
210
+ return context.runtime.newSymbol("default").equals(truststore);
173
211
  }
174
212
 
175
213
  @JRubyMethod
176
- public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
214
+ public IRubyObject initialize(ThreadContext context, IRubyObject miniSSLContext)
177
215
  throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
178
216
 
179
- String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
217
+ String keystoreFile = miniSSLContext.callMethod(context, "keystore").convertToString().asJavaString();
180
218
  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);
219
+ IRubyObject truststore = miniSSLContext.callMethod(context, "truststore");
220
+ String truststoreFile = isDefaultSymbol(context, truststore) ? "" : asStringValue(truststore, () -> keystoreFile);
221
+ TrustManagerFactory tmf = trustManagerFactoryMap.get(truststoreFile); // null if self.truststore = :default
222
+ if (kmf == null) {
223
+ throw new KeyStoreException("Could not find KeyManagerFactory for keystore: " + keystoreFile + " truststore: " + truststoreFile);
184
224
  }
185
225
 
186
226
  SSLContext sslCtx = SSLContext.getInstance("TLS");
187
227
 
188
- sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
228
+ sslCtx.init(kmf.getKeyManagers(), getTrustManagers(tmf), null);
189
229
  closed = false;
190
230
  handshake = false;
191
231
  engine = sslCtx.createSSLEngine();
192
232
 
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
- }
233
+ String[] enabledProtocols;
234
+ IRubyObject protocols = miniSSLContext.callMethod(context, "protocols");
235
+ if (protocols.isNil()) {
236
+ if (miniSSLContext.callMethod(context, "no_tlsv1").isTrue()) {
237
+ enabledProtocols = new String[] { "TLSv1.1", "TLSv1.2", "TLSv1.3" };
238
+ } else {
239
+ enabledProtocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" };
240
+ }
199
241
 
200
- if(miniSSLContext.callMethod(threadContext, "no_tlsv1_1").isTrue()) {
201
- protocols = new String[] { "TLSv1.2" };
242
+ if (miniSSLContext.callMethod(context, "no_tlsv1_1").isTrue()) {
243
+ enabledProtocols = new String[] { "TLSv1.2", "TLSv1.3" };
244
+ }
245
+ } else if (protocols instanceof RubyArray) {
246
+ enabledProtocols = (String[]) ((RubyArray) protocols).toArray(new String[0]);
247
+ } else {
248
+ throw context.runtime.newTypeError(protocols, context.runtime.getArray());
202
249
  }
250
+ engine.setEnabledProtocols(enabledProtocols);
203
251
 
204
- engine.setEnabledProtocols(protocols);
205
252
  engine.setUseClientMode(false);
206
253
 
207
- long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger("to_i").getLongValue();
254
+ long verify_mode = miniSSLContext.callMethod(context, "verify_mode").convertToInteger("to_i").getLongValue();
208
255
  if ((verify_mode & 0x1) != 0) { // 'peer'
209
256
  engine.setWantClientAuth(true);
210
257
  }
@@ -212,10 +259,11 @@ public class MiniSSL extends RubyObject {
212
259
  engine.setNeedClientAuth(true);
213
260
  }
214
261
 
215
- IRubyObject sslCipherListObject = miniSSLContext.callMethod(threadContext, "ssl_cipher_list");
216
- if (!sslCipherListObject.isNil()) {
217
- String[] sslCipherList = sslCipherListObject.convertToString().asJavaString().split(",");
218
- engine.setEnabledCipherSuites(sslCipherList);
262
+ IRubyObject cipher_suites = miniSSLContext.callMethod(context, "cipher_suites");
263
+ if (cipher_suites instanceof RubyArray) {
264
+ engine.setEnabledCipherSuites((String[]) ((RubyArray) cipher_suites).toArray(new String[0]));
265
+ } else if (!cipher_suites.isNil()) {
266
+ throw context.runtime.newTypeError(cipher_suites, context.runtime.getArray());
219
267
  }
220
268
 
221
269
  SSLSession session = engine.getSession();
@@ -227,6 +275,48 @@ public class MiniSSL extends RubyObject {
227
275
  return this;
228
276
  }
229
277
 
278
+ private TrustManager[] getTrustManagers(TrustManagerFactory factory) {
279
+ if (factory == null) return null; // use JDK trust defaults
280
+ final TrustManager[] tms = factory.getTrustManagers();
281
+ if (tms != null) {
282
+ for (int i=0; i<tms.length; i++) {
283
+ final TrustManager tm = tms[i];
284
+ if (tm instanceof X509TrustManager) {
285
+ tms[i] = new TrustManagerWrapper((X509TrustManager) tm);
286
+ }
287
+ }
288
+ }
289
+ return tms;
290
+ }
291
+
292
+ private volatile transient X509Certificate lastCheckedCert0;
293
+
294
+ private class TrustManagerWrapper implements X509TrustManager {
295
+
296
+ private final X509TrustManager delegate;
297
+
298
+ TrustManagerWrapper(X509TrustManager delegate) {
299
+ this.delegate = delegate;
300
+ }
301
+
302
+ @Override
303
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
304
+ lastCheckedCert0 = chain.length > 0 ? chain[0] : null;
305
+ delegate.checkClientTrusted(chain, authType);
306
+ }
307
+
308
+ @Override
309
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
310
+ delegate.checkServerTrusted(chain, authType);
311
+ }
312
+
313
+ @Override
314
+ public X509Certificate[] getAcceptedIssuers() {
315
+ return delegate.getAcceptedIssuers();
316
+ }
317
+
318
+ }
319
+
230
320
  @JRubyMethod
231
321
  public IRubyObject inject(IRubyObject arg) {
232
322
  ByteList bytes = arg.convertToString().getByteList();
@@ -251,7 +341,7 @@ public class MiniSSL extends RubyObject {
251
341
  res = engine.unwrap(src.getRawBuffer(), dst.getRawBuffer());
252
342
  break;
253
343
  default:
254
- throw new IllegalStateException("Unknown SSLOperation: " + sslOp);
344
+ throw new AssertionError("Unknown SSLOperation: " + sslOp);
255
345
  }
256
346
 
257
347
  switch (res.getStatus()) {
@@ -279,14 +369,6 @@ public class MiniSSL extends RubyObject {
279
369
  }
280
370
  }
281
371
 
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
372
  return res;
291
373
  }
292
374
 
@@ -304,11 +386,12 @@ public class MiniSSL extends RubyObject {
304
386
 
305
387
  HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
306
388
  boolean done = false;
307
- SSLEngineResult res = null;
308
389
  while (!done) {
390
+ SSLEngineResult res;
309
391
  switch (handshakeStatus) {
310
392
  case NEED_WRAP:
311
393
  res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
394
+ handshakeStatus = res.getHandshakeStatus();
312
395
  break;
313
396
  case NEED_UNWRAP:
314
397
  res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
@@ -316,13 +399,18 @@ public class MiniSSL extends RubyObject {
316
399
  // need more data before we can shake more hands
317
400
  done = true;
318
401
  }
402
+ handshakeStatus = res.getHandshakeStatus();
403
+ break;
404
+ case NEED_TASK:
405
+ Runnable runnable;
406
+ while ((runnable = engine.getDelegatedTask()) != null) {
407
+ runnable.run();
408
+ }
409
+ handshakeStatus = engine.getHandshakeStatus();
319
410
  break;
320
411
  default:
321
412
  done = true;
322
413
  }
323
- if (!done) {
324
- handshakeStatus = res.getHandshakeStatus();
325
- }
326
414
  }
327
415
 
328
416
  if (inboundNetData.hasRemaining()) {
@@ -338,9 +426,7 @@ public class MiniSSL extends RubyObject {
338
426
 
339
427
  return RubyString.newString(getRuntime(), appDataByteList);
340
428
  } catch (SSLException e) {
341
- RaiseException re = getRuntime().newEOFError(e.getMessage());
342
- re.initCause(e);
343
- throw re;
429
+ throw newSSLError(getRuntime(), e);
344
430
  }
345
431
  }
346
432
 
@@ -373,19 +459,19 @@ public class MiniSSL extends RubyObject {
373
459
 
374
460
  return RubyString.newString(context.runtime, dataByteList);
375
461
  } catch (SSLException e) {
376
- RaiseException ex = context.runtime.newRuntimeError(e.toString());
377
- ex.initCause(e);
378
- throw ex;
462
+ throw newSSLError(getRuntime(), e);
379
463
  }
380
464
  }
381
465
 
382
466
  @JRubyMethod
383
- public IRubyObject peercert() throws CertificateEncodingException {
467
+ public IRubyObject peercert(ThreadContext context) throws CertificateEncodingException {
468
+ Certificate peerCert;
384
469
  try {
385
- return JavaEmbedUtils.javaToRuby(getRuntime(), engine.getSession().getPeerCertificates()[0].getEncoded());
470
+ peerCert = engine.getSession().getPeerCertificates()[0];
386
471
  } catch (SSLPeerUnverifiedException e) {
387
- return getRuntime().getNil();
472
+ peerCert = lastCheckedCert0; // null if trust check did not happen
388
473
  }
474
+ return peerCert == null ? context.nil : JavaEmbedUtils.javaToRuby(context.runtime, peerCert.getEncoded());
389
475
  }
390
476
 
391
477
  @JRubyMethod(name = "init?")
@@ -404,4 +490,19 @@ public class MiniSSL extends RubyObject {
404
490
  return getRuntime().getFalse();
405
491
  }
406
492
  }
493
+
494
+ private static RubyClass getSSLError(Ruby runtime) {
495
+ return (RubyClass) ((RubyModule) runtime.getModule("Puma").getConstantAt("MiniSSL")).getConstantAt("SSLError");
496
+ }
497
+
498
+ private static RaiseException newSSLError(Ruby runtime, SSLException cause) {
499
+ return newError(runtime, getSSLError(runtime), cause.toString(), cause);
500
+ }
501
+
502
+ private static RaiseException newError(Ruby runtime, RubyClass errorClass, String message, Throwable cause) {
503
+ RaiseException ex = new RaiseException(runtime, errorClass, message, true);
504
+ ex.initCause(cause);
505
+ return ex;
506
+ }
507
+
407
508
  }
@@ -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]]