puma 5.6.9-java → 6.6.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +465 -18
  3. data/README.md +152 -42
  4. data/bin/puma-wild +1 -1
  5. data/docs/compile_options.md +34 -0
  6. data/docs/fork_worker.md +12 -4
  7. data/docs/java_options.md +54 -0
  8. data/docs/kubernetes.md +12 -0
  9. data/docs/nginx.md +1 -1
  10. data/docs/plugins.md +4 -0
  11. data/docs/restart.md +1 -0
  12. data/docs/signals.md +2 -2
  13. data/docs/stats.md +8 -3
  14. data/docs/systemd.md +13 -7
  15. data/docs/testing_benchmarks_local_files.md +150 -0
  16. data/docs/testing_test_rackup_ci_files.md +36 -0
  17. data/ext/puma_http11/extconf.rb +27 -17
  18. data/ext/puma_http11/http11_parser.c +1 -1
  19. data/ext/puma_http11/http11_parser.h +1 -1
  20. data/ext/puma_http11/http11_parser.java.rl +2 -2
  21. data/ext/puma_http11/http11_parser.rl +2 -2
  22. data/ext/puma_http11/http11_parser_common.rl +2 -2
  23. data/ext/puma_http11/mini_ssl.c +137 -19
  24. data/ext/puma_http11/org/jruby/puma/Http11.java +31 -10
  25. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
  26. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +157 -53
  27. data/ext/puma_http11/puma_http11.c +21 -10
  28. data/lib/puma/app/status.rb +4 -4
  29. data/lib/puma/binder.rb +60 -55
  30. data/lib/puma/cli.rb +22 -20
  31. data/lib/puma/client.rb +93 -30
  32. data/lib/puma/cluster/worker.rb +27 -17
  33. data/lib/puma/cluster/worker_handle.rb +8 -6
  34. data/lib/puma/cluster.rb +121 -47
  35. data/lib/puma/commonlogger.rb +21 -14
  36. data/lib/puma/configuration.rb +101 -65
  37. data/lib/puma/const.rb +141 -93
  38. data/lib/puma/control_cli.rb +19 -15
  39. data/lib/puma/detect.rb +7 -4
  40. data/lib/puma/dsl.rb +521 -88
  41. data/lib/puma/error_logger.rb +22 -13
  42. data/lib/puma/events.rb +6 -126
  43. data/lib/puma/io_buffer.rb +39 -4
  44. data/lib/puma/jruby_restart.rb +0 -15
  45. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  46. data/lib/puma/launcher.rb +121 -181
  47. data/lib/puma/log_writer.rb +147 -0
  48. data/lib/puma/minissl/context_builder.rb +27 -12
  49. data/lib/puma/minissl.rb +105 -11
  50. data/lib/puma/null_io.rb +42 -2
  51. data/lib/puma/plugin/systemd.rb +90 -0
  52. data/lib/puma/plugin/tmp_restart.rb +1 -1
  53. data/lib/puma/puma_http11.jar +0 -0
  54. data/lib/puma/rack/builder.rb +6 -6
  55. data/lib/puma/rack/urlmap.rb +1 -1
  56. data/lib/puma/rack_default.rb +19 -4
  57. data/lib/puma/reactor.rb +19 -10
  58. data/lib/puma/request.rb +368 -169
  59. data/lib/puma/runner.rb +65 -22
  60. data/lib/puma/sd_notify.rb +146 -0
  61. data/lib/puma/server.rb +161 -102
  62. data/lib/puma/single.rb +13 -11
  63. data/lib/puma/state_file.rb +3 -6
  64. data/lib/puma/thread_pool.rb +71 -21
  65. data/lib/puma/util.rb +1 -12
  66. data/lib/puma.rb +9 -10
  67. data/lib/rack/handler/puma.rb +116 -86
  68. data/tools/Dockerfile +2 -2
  69. metadata +17 -12
  70. data/lib/puma/queue_close.rb +0 -26
  71. data/lib/puma/systemd.rb +0 -46
  72. data/lib/rack/version_restriction.rb +0 -15
@@ -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()) {
@@ -336,9 +427,7 @@ public class MiniSSL extends RubyObject {
336
427
 
337
428
  return RubyString.newString(getRuntime(), appDataByteList);
338
429
  } catch (SSLException e) {
339
- RaiseException re = getRuntime().newEOFError(e.getMessage());
340
- re.initCause(e);
341
- throw re;
430
+ throw newSSLError(getRuntime(), e);
342
431
  }
343
432
  }
344
433
 
@@ -371,19 +460,19 @@ public class MiniSSL extends RubyObject {
371
460
 
372
461
  return RubyString.newString(context.runtime, dataByteList);
373
462
  } catch (SSLException e) {
374
- RaiseException ex = context.runtime.newRuntimeError(e.toString());
375
- ex.initCause(e);
376
- throw ex;
463
+ throw newSSLError(getRuntime(), e);
377
464
  }
378
465
  }
379
466
 
380
467
  @JRubyMethod
381
- public IRubyObject peercert() throws CertificateEncodingException {
468
+ public IRubyObject peercert(ThreadContext context) throws CertificateEncodingException {
469
+ Certificate peerCert;
382
470
  try {
383
- return JavaEmbedUtils.javaToRuby(getRuntime(), engine.getSession().getPeerCertificates()[0].getEncoded());
471
+ peerCert = engine.getSession().getPeerCertificates()[0];
384
472
  } catch (SSLPeerUnverifiedException e) {
385
- return getRuntime().getNil();
473
+ peerCert = lastCheckedCert0; // null if trust check did not happen
386
474
  }
475
+ return peerCert == null ? context.nil : JavaEmbedUtils.javaToRuby(context.runtime, peerCert.getEncoded());
387
476
  }
388
477
 
389
478
  @JRubyMethod(name = "init?")
@@ -402,4 +491,19 @@ public class MiniSSL extends RubyObject {
402
491
  return getRuntime().getFalse();
403
492
  }
404
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
+
405
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
 
@@ -453,6 +461,9 @@ void Init_mini_ssl(VALUE mod);
453
461
 
454
462
  void Init_puma_http11(void)
455
463
  {
464
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
465
+ rb_ext_ractor_safe(true);
466
+ #endif
456
467
 
457
468
  VALUE mPuma = rb_define_module("Puma");
458
469
  VALUE cHttpParser = rb_define_class_under(mPuma, "HttpParser", rb_cObject);
@@ -461,10 +472,10 @@ void Init_puma_http11(void)
461
472
  DEF_GLOBAL(request_uri, "REQUEST_URI");
462
473
  DEF_GLOBAL(fragment, "FRAGMENT");
463
474
  DEF_GLOBAL(query_string, "QUERY_STRING");
464
- DEF_GLOBAL(http_version, "HTTP_VERSION");
475
+ DEF_GLOBAL(server_protocol, "SERVER_PROTOCOL");
465
476
  DEF_GLOBAL(request_path, "REQUEST_PATH");
466
477
 
467
- eHttpParserError = rb_define_class_under(mPuma, "HttpParserError", rb_eIOError);
478
+ eHttpParserError = rb_define_class_under(mPuma, "HttpParserError", rb_eStandardError);
468
479
  rb_global_variable(&eHttpParserError);
469
480
 
470
481
  rb_define_alloc_func(cHttpParser, HttpParser_alloc);
@@ -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
@@ -80,13 +80,13 @@ module Puma
80
80
 
81
81
  def authenticate(env)
82
82
  return true unless @auth_token
83
- env['QUERY_STRING'].to_s.split(/&;/).include?("token=#{@auth_token}")
83
+ env['QUERY_STRING'].to_s.split(/[&;]/).include? "token=#{@auth_token}"
84
84
  end
85
85
 
86
86
  def rack_response(status, body, content_type='application/json')
87
87
  headers = {
88
- 'Content-Type' => content_type,
89
- 'Content-Length' => body.bytesize.to_s
88
+ 'content-type' => content_type,
89
+ 'content-length' => body.bytesize.to_s
90
90
  }
91
91
 
92
92
  [status, headers, [body]]