puma 5.6.7 → 6.4.0
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.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +269 -13
- data/README.md +78 -29
- data/bin/puma-wild +1 -1
- data/docs/compile_options.md +34 -0
- data/docs/fork_worker.md +1 -3
- data/docs/kubernetes.md +12 -0
- data/docs/nginx.md +1 -1
- data/docs/systemd.md +1 -2
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/extconf.rb +11 -8
- data/ext/puma_http11/http11_parser.c +1 -1
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +2 -2
- data/ext/puma_http11/http11_parser.rl +2 -2
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +122 -18
- data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +1 -1
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +156 -53
- data/ext/puma_http11/puma_http11.c +17 -9
- data/lib/puma/app/status.rb +4 -4
- data/lib/puma/binder.rb +50 -53
- data/lib/puma/cli.rb +16 -18
- data/lib/puma/client.rb +59 -19
- data/lib/puma/cluster/worker.rb +18 -11
- data/lib/puma/cluster/worker_handle.rb +4 -1
- data/lib/puma/cluster.rb +33 -30
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +78 -58
- data/lib/puma/const.rb +129 -92
- data/lib/puma/control_cli.rb +15 -11
- data/lib/puma/detect.rb +4 -0
- data/lib/puma/dsl.rb +237 -56
- data/lib/puma/error_logger.rb +18 -9
- data/lib/puma/events.rb +6 -126
- data/lib/puma/io_buffer.rb +39 -4
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +102 -175
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +24 -12
- data/lib/puma/minissl.rb +99 -11
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/rack/builder.rb +6 -6
- data/lib/puma/rack/urlmap.rb +1 -1
- data/lib/puma/rack_default.rb +19 -4
- data/lib/puma/reactor.rb +19 -10
- data/lib/puma/request.rb +365 -170
- data/lib/puma/runner.rb +56 -20
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +116 -89
- data/lib/puma/single.rb +13 -11
- data/lib/puma/state_file.rb +1 -4
- data/lib/puma/thread_pool.rb +57 -19
- data/lib/puma/util.rb +0 -11
- data/lib/puma.rb +9 -10
- data/lib/rack/handler/puma.rb +113 -86
- metadata +9 -5
- data/lib/puma/queue_close.rb +0 -26
- data/lib/puma/systemd.rb +0 -46
- 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,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 | 
            -
                 | 
| 55 | 
            -
             | 
| 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") | 
| 145 | 
            -
                char[]  | 
| 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( | 
| 176 | 
            +
                KeyStore ks = KeyStore.getInstance(keystoreType);
         | 
| 148 177 | 
             
                InputStream is = new FileInputStream(keystoreFile);
         | 
| 149 178 | 
             
                try {
         | 
| 150 | 
            -
                  ks.load(is,  | 
| 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,  | 
| 184 | 
            +
                kmf.init(ks, keystorePass);
         | 
| 156 185 | 
             
                keyManagerFactoryMap.put(keystoreFile, kmf);
         | 
| 157 186 |  | 
| 158 | 
            -
                 | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
                   | 
| 162 | 
            -
             | 
| 163 | 
            -
                   | 
| 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 | 
            -
             | 
| 172 | 
            -
             | 
| 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  | 
| 214 | 
            +
              public IRubyObject initialize(ThreadContext context, IRubyObject miniSSLContext)
         | 
| 177 215 | 
             
                  throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
         | 
| 178 216 |  | 
| 179 | 
            -
                String keystoreFile = miniSSLContext.callMethod( | 
| 217 | 
            +
                String keystoreFile = miniSSLContext.callMethod(context, "keystore").convertToString().asJavaString();
         | 
| 180 218 | 
             
                KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
         | 
| 181 | 
            -
                 | 
| 182 | 
            -
                 | 
| 183 | 
            -
             | 
| 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(),  | 
| 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[]  | 
| 194 | 
            -
                 | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
                     | 
| 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 | 
            -
             | 
| 201 | 
            -
                     | 
| 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( | 
| 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  | 
| 216 | 
            -
                if ( | 
| 217 | 
            -
                  String[]  | 
| 218 | 
            -
             | 
| 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  | 
| 344 | 
            +
                      throw new AssertionError("Unknown SSLOperation: " + sslOp);
         | 
| 255 345 | 
             
                  }
         | 
| 256 346 |  | 
| 257 347 | 
             
                  switch (res.getStatus()) {
         | 
| @@ -336,9 +426,7 @@ public class MiniSSL extends RubyObject { | |
| 336 426 |  | 
| 337 427 | 
             
                  return RubyString.newString(getRuntime(), appDataByteList);
         | 
| 338 428 | 
             
                } catch (SSLException e) {
         | 
| 339 | 
            -
                   | 
| 340 | 
            -
                  re.initCause(e);
         | 
| 341 | 
            -
                  throw re;
         | 
| 429 | 
            +
                  throw newSSLError(getRuntime(), e);
         | 
| 342 430 | 
             
                }
         | 
| 343 431 | 
             
              }
         | 
| 344 432 |  | 
| @@ -371,19 +459,19 @@ public class MiniSSL extends RubyObject { | |
| 371 459 |  | 
| 372 460 | 
             
                  return RubyString.newString(context.runtime, dataByteList);
         | 
| 373 461 | 
             
                } catch (SSLException e) {
         | 
| 374 | 
            -
                   | 
| 375 | 
            -
                  ex.initCause(e);
         | 
| 376 | 
            -
                  throw ex;
         | 
| 462 | 
            +
                  throw newSSLError(getRuntime(), e);
         | 
| 377 463 | 
             
                }
         | 
| 378 464 | 
             
              }
         | 
| 379 465 |  | 
| 380 466 | 
             
              @JRubyMethod
         | 
| 381 | 
            -
              public IRubyObject peercert() throws CertificateEncodingException {
         | 
| 467 | 
            +
              public IRubyObject peercert(ThreadContext context) throws CertificateEncodingException {
         | 
| 468 | 
            +
                Certificate peerCert;
         | 
| 382 469 | 
             
                try {
         | 
| 383 | 
            -
                   | 
| 470 | 
            +
                  peerCert = engine.getSession().getPeerCertificates()[0];
         | 
| 384 471 | 
             
                } catch (SSLPeerUnverifiedException e) {
         | 
| 385 | 
            -
                   | 
| 472 | 
            +
                  peerCert = lastCheckedCert0; // null if trust check did not happen
         | 
| 386 473 | 
             
                }
         | 
| 474 | 
            +
                return peerCert == null ? context.nil : JavaEmbedUtils.javaToRuby(context.runtime, peerCert.getEncoded());
         | 
| 387 475 | 
             
              }
         | 
| 388 476 |  | 
| 389 477 | 
             
              @JRubyMethod(name = "init?")
         | 
| @@ -402,4 +490,19 @@ public class MiniSSL extends RubyObject { | |
| 402 490 | 
             
                  return getRuntime().getFalse();
         | 
| 403 491 | 
             
                }
         | 
| 404 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 | 
            +
             | 
| 405 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  | 
| 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  | 
| 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 "  | 
| 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,  | 
| 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,  | 
| 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  | 
| 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,  | 
| 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-> | 
| 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( | 
| 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);
         | 
    
        data/lib/puma/app/status.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 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( | 
| 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 | 
            -
                      ' | 
| 89 | 
            -
                      ' | 
| 88 | 
            +
                      'content-type' => content_type,
         | 
| 89 | 
            +
                      'content-length' => body.bytesize.to_s
         | 
| 90 90 | 
             
                    }
         | 
| 91 91 |  | 
| 92 92 | 
             
                    [status, headers, [body]]
         |