puma 3.4.0 → 3.12.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 +5 -5
- data/{History.txt → History.md} +356 -74
- data/README.md +143 -227
- data/docs/architecture.md +36 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +1 -1
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/plugins.md +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +124 -22
- data/ext/puma_http11/extconf.rb +2 -0
- data/ext/puma_http11/http11_parser.c +291 -447
- data/ext/puma_http11/http11_parser.h +1 -0
- data/ext/puma_http11/http11_parser.rl +10 -9
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/io_buffer.c +7 -7
- data/ext/puma_http11/mini_ssl.c +67 -6
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +76 -94
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +15 -2
- data/ext/puma_http11/puma_http11.c +1 -0
- data/lib/puma.rb +13 -5
- data/lib/puma/app/status.rb +8 -0
- data/lib/puma/binder.rb +46 -21
- data/lib/puma/cli.rb +49 -33
- data/lib/puma/client.rb +149 -4
- data/lib/puma/cluster.rb +55 -13
- data/lib/puma/commonlogger.rb +19 -20
- data/lib/puma/compat.rb +3 -7
- data/lib/puma/configuration.rb +136 -131
- data/lib/puma/const.rb +19 -37
- data/lib/puma/control_cli.rb +38 -35
- data/lib/puma/convenient.rb +3 -3
- data/lib/puma/detect.rb +3 -1
- data/lib/puma/dsl.rb +86 -57
- data/lib/puma/events.rb +17 -13
- data/lib/puma/io_buffer.rb +1 -1
- data/lib/puma/jruby_restart.rb +0 -1
- data/lib/puma/launcher.rb +61 -30
- data/lib/puma/minissl.rb +85 -4
- data/lib/puma/null_io.rb +6 -13
- data/lib/puma/plugin.rb +12 -1
- data/lib/puma/plugin/tmp_restart.rb +1 -2
- data/lib/puma/rack/builder.rb +3 -0
- data/lib/puma/rack/urlmap.rb +9 -8
- data/lib/puma/reactor.rb +144 -0
- data/lib/puma/runner.rb +27 -1
- data/lib/puma/server.rb +135 -33
- data/lib/puma/single.rb +17 -3
- data/lib/puma/tcp_logger.rb +8 -1
- data/lib/puma/thread_pool.rb +70 -20
- data/lib/puma/util.rb +1 -5
- data/lib/rack/handler/puma.rb +58 -17
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +9 -2
- data/tools/jungle/init.d/puma +85 -58
- data/tools/jungle/init.d/run-puma +16 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/jungle/upstart/puma.conf +1 -1
- data/tools/trickletest.rb +1 -1
- metadata +22 -94
- data/Gemfile +0 -13
- data/Manifest.txt +0 -78
- data/Rakefile +0 -158
- data/docs/config.md +0 -0
- data/lib/puma/rack/backports/uri/common_18.rb +0 -59
- data/lib/puma/rack/backports/uri/common_192.rb +0 -55
- data/puma.gemspec +0 -52
    
        data/lib/puma/const.rb
    CHANGED
    
    | @@ -53,6 +53,8 @@ module Puma | |
| 53 53 | 
             
                415 => 'Unsupported Media Type',
         | 
| 54 54 | 
             
                416 => 'Range Not Satisfiable',
         | 
| 55 55 | 
             
                417 => 'Expectation Failed',
         | 
| 56 | 
            +
                418 => 'I\'m A Teapot',
         | 
| 57 | 
            +
                421 => 'Misdirected Request',
         | 
| 56 58 | 
             
                422 => 'Unprocessable Entity',
         | 
| 57 59 | 
             
                423 => 'Locked',
         | 
| 58 60 | 
             
                424 => 'Failed Dependency',
         | 
| @@ -60,6 +62,7 @@ module Puma | |
| 60 62 | 
             
                428 => 'Precondition Required',
         | 
| 61 63 | 
             
                429 => 'Too Many Requests',
         | 
| 62 64 | 
             
                431 => 'Request Header Fields Too Large',
         | 
| 65 | 
            +
                451 => 'Unavailable For Legal Reasons',
         | 
| 63 66 | 
             
                500 => 'Internal Server Error',
         | 
| 64 67 | 
             
                501 => 'Not Implemented',
         | 
| 65 68 | 
             
                502 => 'Bad Gateway',
         | 
| @@ -73,19 +76,14 @@ module Puma | |
| 73 76 | 
             
                511 => 'Network Authentication Required'
         | 
| 74 77 | 
             
              }
         | 
| 75 78 |  | 
| 76 | 
            -
              SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message|
         | 
| 77 | 
            -
                [message.downcase.gsub(/\s|-|'/, '_').to_sym, code]
         | 
| 78 | 
            -
              }.flatten]
         | 
| 79 | 
            -
             | 
| 80 79 | 
             
              # For some HTTP status codes the client only expects headers.
         | 
| 81 80 | 
             
              #
         | 
| 82 81 |  | 
| 83 | 
            -
               | 
| 84 | 
            -
             | 
| 85 | 
            -
                 | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
              STATUS_WITH_NO_ENTITY_BODY = no_body
         | 
| 82 | 
            +
              STATUS_WITH_NO_ENTITY_BODY = {
         | 
| 83 | 
            +
                204 => true,
         | 
| 84 | 
            +
                205 => true,
         | 
| 85 | 
            +
                304 => true
         | 
| 86 | 
            +
              }
         | 
| 89 87 |  | 
| 90 88 | 
             
              # Frequently used constants when constructing requests or responses.  Many times
         | 
| 91 89 | 
             
              # the constant just refers to a string with the same contents.  Using these constants
         | 
| @@ -100,10 +98,10 @@ module Puma | |
| 100 98 | 
             
              # too taxing on performance.
         | 
| 101 99 | 
             
              module Const
         | 
| 102 100 |  | 
| 103 | 
            -
                PUMA_VERSION = VERSION = "3. | 
| 104 | 
            -
                CODE_NAME = " | 
| 101 | 
            +
                PUMA_VERSION = VERSION = "3.12.0".freeze
         | 
| 102 | 
            +
                CODE_NAME = "Llamas in Pajamas".freeze
         | 
| 105 103 | 
             
                PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
         | 
| 106 | 
            -
             | 
| 104 | 
            +
             | 
| 107 105 | 
             
                FAST_TRACK_KA_TIMEOUT = 0.2
         | 
| 108 106 |  | 
| 109 107 | 
             
                # The default number of seconds for another request within a persistent
         | 
| @@ -118,15 +116,6 @@ module Puma | |
| 118 116 | 
             
                # sending data back
         | 
| 119 117 | 
             
                WRITE_TIMEOUT = 10
         | 
| 120 118 |  | 
| 121 | 
            -
                # How long, after raising the ForceShutdown of a thread during
         | 
| 122 | 
            -
                # forced shutdown mode, to wait for the thread to try and finish
         | 
| 123 | 
            -
                # up it's work before leaving the thread to die on the vine.
         | 
| 124 | 
            -
                SHUTDOWN_GRACE_TIME = 5 # seconds
         | 
| 125 | 
            -
             | 
| 126 | 
            -
                DATE = "Date".freeze
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                SCRIPT_NAME = "SCRIPT_NAME".freeze
         | 
| 129 | 
            -
             | 
| 130 119 | 
             
                # The original URI requested by the client.
         | 
| 131 120 | 
             
                REQUEST_URI= 'REQUEST_URI'.freeze
         | 
| 132 121 | 
             
                REQUEST_PATH = 'REQUEST_PATH'.freeze
         | 
| @@ -163,26 +152,12 @@ module Puma | |
| 163 152 | 
             
                # Maximum request body size before it is moved out of memory and into a tempfile for reading.
         | 
| 164 153 | 
             
                MAX_BODY = MAX_HEADER
         | 
| 165 154 |  | 
| 166 | 
            -
                # A frozen format for this is about 15% faster
         | 
| 167 | 
            -
                STATUS_FORMAT = "HTTP/1.1 %d %s\r\nConnection: close\r\n".freeze
         | 
| 168 | 
            -
             | 
| 169 | 
            -
                CONTENT_TYPE = "Content-Type".freeze
         | 
| 170 | 
            -
             | 
| 171 | 
            -
                LAST_MODIFIED = "Last-Modified".freeze
         | 
| 172 | 
            -
                ETAG = "ETag".freeze
         | 
| 173 | 
            -
                SLASH = "/".freeze
         | 
| 174 155 | 
             
                REQUEST_METHOD = "REQUEST_METHOD".freeze
         | 
| 175 | 
            -
                GET = "GET".freeze
         | 
| 176 156 | 
             
                HEAD = "HEAD".freeze
         | 
| 177 157 | 
             
                # ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
         | 
| 178 | 
            -
                ETAG_FORMAT = "\"%x-%x-%x\"".freeze
         | 
| 179 158 | 
             
                LINE_END = "\r\n".freeze
         | 
| 180 159 | 
             
                REMOTE_ADDR = "REMOTE_ADDR".freeze
         | 
| 181 160 | 
             
                HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
         | 
| 182 | 
            -
                HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
         | 
| 183 | 
            -
                HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
         | 
| 184 | 
            -
                REDIRECT = "HTTP/1.1 302 Found\r\nLocation: %s\r\nConnection: close\r\n\r\n".freeze
         | 
| 185 | 
            -
                HOST = "HOST".freeze
         | 
| 186 161 |  | 
| 187 162 | 
             
                SERVER_NAME = "SERVER_NAME".freeze
         | 
| 188 163 | 
             
                SERVER_PORT = "SERVER_PORT".freeze
         | 
| @@ -195,7 +170,6 @@ module Puma | |
| 195 170 |  | 
| 196 171 | 
             
                SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
         | 
| 197 172 | 
             
                HTTP_11 = "HTTP/1.1".freeze
         | 
| 198 | 
            -
                HTTP_10 = "HTTP/1.0".freeze
         | 
| 199 173 |  | 
| 200 174 | 
             
                SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
         | 
| 201 175 | 
             
                GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
         | 
| @@ -219,7 +193,10 @@ module Puma | |
| 219 193 |  | 
| 220 194 | 
             
                HTTP_VERSION = "HTTP_VERSION".freeze
         | 
| 221 195 | 
             
                HTTP_CONNECTION = "HTTP_CONNECTION".freeze
         | 
| 196 | 
            +
                HTTP_EXPECT = "HTTP_EXPECT".freeze
         | 
| 197 | 
            +
                CONTINUE = "100-continue".freeze
         | 
| 222 198 |  | 
| 199 | 
            +
                HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n".freeze
         | 
| 223 200 | 
             
                HTTP_11_200 = "HTTP/1.1 200 OK\r\n".freeze
         | 
| 224 201 | 
             
                HTTP_10_200 = "HTTP/1.0 200 OK\r\n".freeze
         | 
| 225 202 |  | 
| @@ -229,6 +206,7 @@ module Puma | |
| 229 206 | 
             
                CONTENT_LENGTH2 = "content-length".freeze
         | 
| 230 207 | 
             
                CONTENT_LENGTH_S = "Content-Length: ".freeze
         | 
| 231 208 | 
             
                TRANSFER_ENCODING = "transfer-encoding".freeze
         | 
| 209 | 
            +
                TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING".freeze
         | 
| 232 210 |  | 
| 233 211 | 
             
                CONNECTION_CLOSE = "Connection: close\r\n".freeze
         | 
| 234 212 | 
             
                CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n".freeze
         | 
| @@ -236,6 +214,8 @@ module Puma | |
| 236 214 | 
             
                TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n".freeze
         | 
| 237 215 | 
             
                CLOSE_CHUNKED = "0\r\n\r\n".freeze
         | 
| 238 216 |  | 
| 217 | 
            +
                CHUNKED = "chunked".freeze
         | 
| 218 | 
            +
             | 
| 239 219 | 
             
                COLON = ": ".freeze
         | 
| 240 220 |  | 
| 241 221 | 
             
                NEWLINE = "\n".freeze
         | 
| @@ -243,5 +223,7 @@ module Puma | |
| 243 223 | 
             
                HIJACK_P = "rack.hijack?".freeze
         | 
| 244 224 | 
             
                HIJACK = "rack.hijack".freeze
         | 
| 245 225 | 
             
                HIJACK_IO = "rack.hijack_io".freeze
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                EARLY_HINTS = "rack.early_hints".freeze
         | 
| 246 228 | 
             
              end
         | 
| 247 229 | 
             
            end
         | 
    
        data/lib/puma/control_cli.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            require 'optparse'
         | 
| 2 | 
            -
            require 'puma'
         | 
| 2 | 
            +
            require 'puma/state_file'
         | 
| 3 3 | 
             
            require 'puma/const'
         | 
| 4 4 | 
             
            require 'puma/detect'
         | 
| 5 5 | 
             
            require 'puma/configuration'
         | 
| @@ -9,7 +9,7 @@ require 'socket' | |
| 9 9 | 
             
            module Puma
         | 
| 10 10 | 
             
              class ControlCLI
         | 
| 11 11 |  | 
| 12 | 
            -
                COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory}
         | 
| 12 | 
            +
                COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats}
         | 
| 13 13 |  | 
| 14 14 | 
             
                def initialize(argv, stdout=STDOUT, stderr=STDERR)
         | 
| 15 15 | 
             
                  @state = nil
         | 
| @@ -69,6 +69,7 @@ module Puma | |
| 69 69 | 
             
                  end
         | 
| 70 70 |  | 
| 71 71 | 
             
                  opts.order!(argv) { |a| opts.terminate a }
         | 
| 72 | 
            +
                  opts.parse!
         | 
| 72 73 |  | 
| 73 74 | 
             
                  @command = argv.shift
         | 
| 74 75 |  | 
| @@ -78,11 +79,12 @@ module Puma | |
| 78 79 | 
             
                    end
         | 
| 79 80 |  | 
| 80 81 | 
             
                    if @config_file
         | 
| 81 | 
            -
                      config = Puma::Configuration. | 
| 82 | 
            -
                       | 
| 83 | 
            -
                      @ | 
| 82 | 
            +
                      config = Puma::Configuration.new({ config_files: [@config_file] }, {})
         | 
| 83 | 
            +
                      config.load
         | 
| 84 | 
            +
                      @state              ||= config.options[:state]
         | 
| 85 | 
            +
                      @control_url        ||= config.options[:control_url]
         | 
| 84 86 | 
             
                      @control_auth_token ||= config.options[:control_auth_token]
         | 
| 85 | 
            -
                      @pidfile | 
| 87 | 
            +
                      @pidfile            ||= config.options[:pidfile]
         | 
| 86 88 | 
             
                    end
         | 
| 87 89 | 
             
                  end
         | 
| 88 90 |  | 
| @@ -97,6 +99,7 @@ module Puma | |
| 97 99 |  | 
| 98 100 | 
             
                rescue => e
         | 
| 99 101 | 
             
                  @stdout.puts e.message
         | 
| 102 | 
            +
                  @stdout.puts e.backtrace
         | 
| 100 103 | 
             
                  exit 1
         | 
| 101 104 | 
             
                end
         | 
| 102 105 |  | 
| @@ -167,7 +170,7 @@ module Puma | |
| 167 170 | 
             
                    end
         | 
| 168 171 |  | 
| 169 172 | 
             
                    message "Command #{@command} sent success"
         | 
| 170 | 
            -
                    message response.last if @command == "stats"
         | 
| 173 | 
            +
                    message response.last if @command == "stats" || @command == "gc-stats"
         | 
| 171 174 | 
             
                  end
         | 
| 172 175 |  | 
| 173 176 | 
             
                  @server.close
         | 
| @@ -179,46 +182,45 @@ module Puma | |
| 179 182 | 
             
                  end
         | 
| 180 183 |  | 
| 181 184 | 
             
                  begin
         | 
| 182 | 
            -
                    Process.getpgid @pid
         | 
| 183 | 
            -
                  rescue SystemCallError
         | 
| 184 | 
            -
                    if @command == "restart"
         | 
| 185 | 
            -
                      start
         | 
| 186 | 
            -
                    else
         | 
| 187 | 
            -
                      raise "No pid '#{@pid}' found"
         | 
| 188 | 
            -
                    end
         | 
| 189 | 
            -
                  end
         | 
| 190 185 |  | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 186 | 
            +
                    case @command
         | 
| 187 | 
            +
                    when "restart"
         | 
| 188 | 
            +
                      Process.kill "SIGUSR2", @pid
         | 
| 194 189 |  | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 190 | 
            +
                    when "halt"
         | 
| 191 | 
            +
                      Process.kill "QUIT", @pid
         | 
| 197 192 |  | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 193 | 
            +
                    when "stop"
         | 
| 194 | 
            +
                      Process.kill "SIGTERM", @pid
         | 
| 200 195 |  | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 196 | 
            +
                    when "stats"
         | 
| 197 | 
            +
                      puts "Stats not available via pid only"
         | 
| 198 | 
            +
                      return
         | 
| 204 199 |  | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 200 | 
            +
                    when "reload-worker-directory"
         | 
| 201 | 
            +
                      puts "reload-worker-directory not available via pid only"
         | 
| 202 | 
            +
                      return
         | 
| 208 203 |  | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 204 | 
            +
                    when "phased-restart"
         | 
| 205 | 
            +
                      Process.kill "SIGUSR1", @pid
         | 
| 211 206 |  | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 214 | 
            -
                     | 
| 207 | 
            +
                    else
         | 
| 208 | 
            +
                      return
         | 
| 209 | 
            +
                    end
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                  rescue SystemCallError
         | 
| 212 | 
            +
                    if @command == "restart"
         | 
| 213 | 
            +
                      start
         | 
| 214 | 
            +
                    else
         | 
| 215 | 
            +
                      raise "No pid '#{@pid}' found"
         | 
| 216 | 
            +
                    end
         | 
| 215 217 | 
             
                  end
         | 
| 216 218 |  | 
| 217 219 | 
             
                  message "Command #{@command} sent success"
         | 
| 218 220 | 
             
                end
         | 
| 219 221 |  | 
| 220 222 | 
             
                def run
         | 
| 221 | 
            -
                  start if @command == "start"
         | 
| 223 | 
            +
                  return start if @command == "start"
         | 
| 222 224 |  | 
| 223 225 | 
             
                  prepare_configuration
         | 
| 224 226 |  | 
| @@ -230,6 +232,7 @@ module Puma | |
| 230 232 |  | 
| 231 233 | 
             
                rescue => e
         | 
| 232 234 | 
             
                  message e.message
         | 
| 235 | 
            +
                  message e.backtrace
         | 
| 233 236 | 
             
                  exit 1
         | 
| 234 237 | 
             
                end
         | 
| 235 238 |  | 
| @@ -242,7 +245,7 @@ module Puma | |
| 242 245 | 
             
                  run_args += ["-S", @state]  if @state
         | 
| 243 246 | 
             
                  run_args += ["-q"] if @quiet
         | 
| 244 247 | 
             
                  run_args += ["--pidfile", @pidfile] if @pidfile
         | 
| 245 | 
            -
                  run_args += ["--control", @control_url] if @control_url
         | 
| 248 | 
            +
                  run_args += ["--control-url", @control_url] if @control_url
         | 
| 246 249 | 
             
                  run_args += ["--control-token", @control_auth_token] if @control_auth_token
         | 
| 247 250 | 
             
                  run_args += ["-C", @config_file] if @config_file
         | 
| 248 251 |  | 
    
        data/lib/puma/convenient.rb
    CHANGED
    
    | @@ -3,12 +3,12 @@ require 'puma/configuration' | |
| 3 3 |  | 
| 4 4 | 
             
            module Puma
         | 
| 5 5 | 
             
              def self.run(opts={})
         | 
| 6 | 
            -
                cfg = Puma::Configuration.new do | | 
| 6 | 
            +
                cfg = Puma::Configuration.new do |user_config|
         | 
| 7 7 | 
             
                  if port = opts[:port]
         | 
| 8 | 
            -
                     | 
| 8 | 
            +
                    user_config.port port
         | 
| 9 9 | 
             
                  end
         | 
| 10 10 |  | 
| 11 | 
            -
                   | 
| 11 | 
            +
                  user_config.quiet
         | 
| 12 12 |  | 
| 13 13 | 
             
                  yield c
         | 
| 14 14 | 
             
                end
         | 
    
        data/lib/puma/detect.rb
    CHANGED
    
    
    
        data/lib/puma/dsl.rb
    CHANGED
    
    | @@ -1,20 +1,35 @@ | |
| 1 1 | 
             
            module Puma
         | 
| 2 2 | 
             
              # The methods that are available for use inside the config file.
         | 
| 3 | 
            +
              # These same methods are used in Puma cli and the rack handler
         | 
| 4 | 
            +
              # internally.
         | 
| 3 5 | 
             
              #
         | 
| 6 | 
            +
              # Used manually (via CLI class):
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              #   config = Configuration.new({}) do |user_config|
         | 
| 9 | 
            +
              #     user_config.port 3001
         | 
| 10 | 
            +
              #   end
         | 
| 11 | 
            +
              #   config.load
         | 
| 12 | 
            +
              #
         | 
| 13 | 
            +
              #   puts config.options[:binds]
         | 
| 14 | 
            +
              #   "tcp://127.0.0.1:3001"
         | 
| 15 | 
            +
              #
         | 
| 16 | 
            +
              # Used to load file:
         | 
| 17 | 
            +
              #
         | 
| 18 | 
            +
              #   $ cat puma_config.rb
         | 
| 19 | 
            +
              #     port 3002
         | 
| 20 | 
            +
              #
         | 
| 21 | 
            +
              #   config = Configuration.new(config_file: "puma_config.rb")
         | 
| 22 | 
            +
              #   config.load
         | 
| 23 | 
            +
              #
         | 
| 24 | 
            +
              #   puts config.options[:binds]
         | 
| 25 | 
            +
              #   # => "tcp://127.0.0.1:3002"
         | 
| 26 | 
            +
              #
         | 
| 27 | 
            +
              # Detailed docs can be found in `examples/config.rb`
         | 
| 4 28 | 
             
              class DSL
         | 
| 5 29 | 
             
                include ConfigDefault
         | 
| 6 30 |  | 
| 7 | 
            -
                def self.load(options, cfg, path)
         | 
| 8 | 
            -
                  d = new(options, cfg)
         | 
| 9 | 
            -
                  d._load_from(path)
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                  options
         | 
| 12 | 
            -
                ensure
         | 
| 13 | 
            -
                  d._offer_plugins
         | 
| 14 | 
            -
                end
         | 
| 15 | 
            -
             | 
| 16 31 | 
             
                def initialize(options, config)
         | 
| 17 | 
            -
                  @config | 
| 32 | 
            +
                  @config  = config
         | 
| 18 33 | 
             
                  @options = options
         | 
| 19 34 |  | 
| 20 35 | 
             
                  @plugins = []
         | 
| @@ -40,36 +55,10 @@ module Puma | |
| 40 55 | 
             
                  @plugins.clear
         | 
| 41 56 | 
             
                end
         | 
| 42 57 |  | 
| 43 | 
            -
                def _run(&blk)
         | 
| 44 | 
            -
                  blk.call self
         | 
| 45 | 
            -
                ensure
         | 
| 46 | 
            -
                  _offer_plugins
         | 
| 47 | 
            -
                end
         | 
| 48 | 
            -
             | 
| 49 58 | 
             
                def inject(&blk)
         | 
| 50 59 | 
             
                  instance_eval(&blk)
         | 
| 51 60 | 
             
                end
         | 
| 52 61 |  | 
| 53 | 
            -
                # Load configuration from another named file. If the file name is absolute,
         | 
| 54 | 
            -
                # load the file as an absolute path. Otherwise load it relative to the
         | 
| 55 | 
            -
                # current config file.
         | 
| 56 | 
            -
                #
         | 
| 57 | 
            -
                def import(file)
         | 
| 58 | 
            -
                  if File.extname(file) == ""
         | 
| 59 | 
            -
                    file += ".rb"
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  if file[0,1] == "/"
         | 
| 63 | 
            -
                    path = file
         | 
| 64 | 
            -
                  elsif @path
         | 
| 65 | 
            -
                    path = File.join File.dirname(@path), file
         | 
| 66 | 
            -
                  else
         | 
| 67 | 
            -
                    raise "No original configuration path to import relative to"
         | 
| 68 | 
            -
                  end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                  DSL.new(@options, @config)._load_from(path)
         | 
| 71 | 
            -
                end
         | 
| 72 | 
            -
             | 
| 73 62 | 
             
                def get(key,default=nil)
         | 
| 74 63 | 
             
                  @options[key.to_sym] || default
         | 
| 75 64 | 
             
                end
         | 
| @@ -115,15 +104,35 @@ module Puma | |
| 115 104 | 
             
                end
         | 
| 116 105 |  | 
| 117 106 | 
             
                # Load additional configuration from a file
         | 
| 107 | 
            +
                # Files get loaded later via Configuration#load
         | 
| 118 108 | 
             
                def load(file)
         | 
| 119 | 
            -
                   | 
| 109 | 
            +
                  @options[:config_files] ||= []
         | 
| 110 | 
            +
                  @options[:config_files] << file
         | 
| 120 111 | 
             
                end
         | 
| 121 112 |  | 
| 122 | 
            -
                #  | 
| 123 | 
            -
                # protocols.
         | 
| 113 | 
            +
                # Adds a binding for the server to +url+. tcp://, unix://, and ssl:// are the only accepted
         | 
| 114 | 
            +
                # protocols. Use query parameters within the url to specify options.
         | 
| 115 | 
            +
                #
         | 
| 116 | 
            +
                # @note multiple urls can be bound to, calling `bind` does not overwrite previous bindings.
         | 
| 117 | 
            +
                #
         | 
| 118 | 
            +
                # @example Explicitly the socket backlog depth (default is 1024)
         | 
| 119 | 
            +
                #   bind('unix:///var/run/puma.sock?backlog=2048')
         | 
| 124 120 | 
             
                #
         | 
| 121 | 
            +
                # @example Set up ssl cert
         | 
| 122 | 
            +
                #   bind('ssl://127.0.0.1:9292?key=key.key&cert=cert.pem')
         | 
| 123 | 
            +
                #
         | 
| 124 | 
            +
                # @example Prefer low-latency over higher throughput (via `Socket::TCP_NODELAY`)
         | 
| 125 | 
            +
                #   bind('tcp://0.0.0.0:9292?low_latency=true')
         | 
| 126 | 
            +
                #
         | 
| 127 | 
            +
                # @example Set socket permissions
         | 
| 128 | 
            +
                #   bind('unix:///var/run/puma.sock?umask=0111')
         | 
| 125 129 | 
             
                def bind(url)
         | 
| 126 | 
            -
                   | 
| 130 | 
            +
                  @options[:binds] ||= []
         | 
| 131 | 
            +
                  @options[:binds] << url
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                def clear_binds!
         | 
| 135 | 
            +
                  @options[:binds] = []
         | 
| 127 136 | 
             
                end
         | 
| 128 137 |  | 
| 129 138 | 
             
                # Define the TCP port to bind to. Use +bind+ for more advanced options.
         | 
| @@ -133,6 +142,19 @@ module Puma | |
| 133 142 | 
             
                  bind "tcp://#{host}:#{port}"
         | 
| 134 143 | 
             
                end
         | 
| 135 144 |  | 
| 145 | 
            +
                # Define how long persistent connections can be idle before puma closes
         | 
| 146 | 
            +
                # them
         | 
| 147 | 
            +
                #
         | 
| 148 | 
            +
                def persistent_timeout(seconds)
         | 
| 149 | 
            +
                  @options[:persistent_timeout] = Integer(seconds)
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                # Define how long the tcp socket stays open, if no data has been received
         | 
| 153 | 
            +
                #
         | 
| 154 | 
            +
                def first_data_timeout(seconds)
         | 
| 155 | 
            +
                  @options[:first_data_timeout] = Integer(seconds)
         | 
| 156 | 
            +
                end
         | 
| 157 | 
            +
             | 
| 136 158 | 
             
                # Work around leaky apps that leave garbage in Thread locals
         | 
| 137 159 | 
             
                # across requests
         | 
| 138 160 | 
             
                #
         | 
| @@ -147,7 +169,7 @@ module Puma | |
| 147 169 | 
             
                end
         | 
| 148 170 |  | 
| 149 171 | 
             
                # When shutting down, drain the accept socket of pending
         | 
| 150 | 
            -
                # connections and  | 
| 172 | 
            +
                # connections and process them. This loops over the accept
         | 
| 151 173 | 
             
                # socket until there are no more read events and then stops
         | 
| 152 174 | 
             
                # looking and waits for the requests to finish.
         | 
| 153 175 | 
             
                def drain_on_shutdown(which=true)
         | 
| @@ -185,7 +207,8 @@ module Puma | |
| 185 207 | 
             
                # This can be called multiple times to add code each time.
         | 
| 186 208 | 
             
                #
         | 
| 187 209 | 
             
                def on_restart(&block)
         | 
| 188 | 
            -
                   | 
| 210 | 
            +
                  @options[:on_restart] ||= []
         | 
| 211 | 
            +
                  @options[:on_restart] << block
         | 
| 189 212 | 
             
                end
         | 
| 190 213 |  | 
| 191 214 | 
             
                # Command to use to restart puma. This should be just how to
         | 
| @@ -231,6 +254,10 @@ module Puma | |
| 231 254 | 
             
                  @options[:mode] = :tcp
         | 
| 232 255 | 
             
                end
         | 
| 233 256 |  | 
| 257 | 
            +
                def early_hints(answer=true)
         | 
| 258 | 
            +
                  @options[:early_hints] = answer
         | 
| 259 | 
            +
                end
         | 
| 260 | 
            +
             | 
| 234 261 | 
             
                # Redirect STDOUT and STDERR to files specified.
         | 
| 235 262 | 
             
                def stdout_redirect(stdout=nil, stderr=nil, append=false)
         | 
| 236 263 | 
             
                  @options[:redirect_stdout] = stdout
         | 
| @@ -257,11 +284,13 @@ module Puma | |
| 257 284 | 
             
                end
         | 
| 258 285 |  | 
| 259 286 | 
             
                def ssl_bind(host, port, opts)
         | 
| 287 | 
            +
                  verify = opts.fetch(:verify_mode, 'none')
         | 
| 288 | 
            +
             | 
| 260 289 | 
             
                  if defined?(JRUBY_VERSION)
         | 
| 261 290 | 
             
                    keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
         | 
| 262 | 
            -
                    bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}"
         | 
| 291 | 
            +
                    bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}"
         | 
| 263 292 | 
             
                  else
         | 
| 264 | 
            -
                    bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}"
         | 
| 293 | 
            +
                    bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&verify_mode=#{verify}"
         | 
| 265 294 | 
             
                  end
         | 
| 266 295 | 
             
                end
         | 
| 267 296 |  | 
| @@ -288,7 +317,8 @@ module Puma | |
| 288 317 | 
             
                # This can be called multiple times to add hooks.
         | 
| 289 318 | 
             
                #
         | 
| 290 319 | 
             
                def before_fork(&block)
         | 
| 291 | 
            -
                   | 
| 320 | 
            +
                  @options[:before_fork] ||= []
         | 
| 321 | 
            +
                  @options[:before_fork] << block
         | 
| 292 322 | 
             
                end
         | 
| 293 323 |  | 
| 294 324 | 
             
                # *Cluster mode only* Code to run in a worker when it boots to setup
         | 
| @@ -297,7 +327,8 @@ module Puma | |
| 297 327 | 
             
                # This can be called multiple times to add hooks.
         | 
| 298 328 | 
             
                #
         | 
| 299 329 | 
             
                def on_worker_boot(&block)
         | 
| 300 | 
            -
                   | 
| 330 | 
            +
                  @options[:before_worker_boot] ||= []
         | 
| 331 | 
            +
                  @options[:before_worker_boot] << block
         | 
| 301 332 | 
             
                end
         | 
| 302 333 |  | 
| 303 334 | 
             
                # *Cluster mode only* Code to run immediately before a worker shuts
         | 
| @@ -308,7 +339,8 @@ module Puma | |
| 308 339 | 
             
                # This can be called multiple times to add hooks.
         | 
| 309 340 | 
             
                #
         | 
| 310 341 | 
             
                def on_worker_shutdown(&block)
         | 
| 311 | 
            -
                   | 
| 342 | 
            +
                  @options[:before_worker_shutdown] ||= []
         | 
| 343 | 
            +
                  @options[:before_worker_shutdown] << block
         | 
| 312 344 | 
             
                end
         | 
| 313 345 |  | 
| 314 346 | 
             
                # *Cluster mode only* Code to run in the master when it is
         | 
| @@ -317,7 +349,8 @@ module Puma | |
| 317 349 | 
             
                # This can be called multiple times to add hooks.
         | 
| 318 350 | 
             
                #
         | 
| 319 351 | 
             
                def on_worker_fork(&block)
         | 
| 320 | 
            -
                   | 
| 352 | 
            +
                  @options[:before_worker_fork] ||= []
         | 
| 353 | 
            +
                  @options[:before_worker_fork] << block
         | 
| 321 354 | 
             
                end
         | 
| 322 355 |  | 
| 323 356 | 
             
                # *Cluster mode only* Code to run in the master after it starts
         | 
| @@ -326,7 +359,8 @@ module Puma | |
| 326 359 | 
             
                # This can be called multiple times to add hooks.
         | 
| 327 360 | 
             
                #
         | 
| 328 361 | 
             
                def after_worker_fork(&block)
         | 
| 329 | 
            -
                   | 
| 362 | 
            +
                  @options[:after_worker_fork] ||= []
         | 
| 363 | 
            +
                  @options[:after_worker_fork] = block
         | 
| 330 364 | 
             
                end
         | 
| 331 365 |  | 
| 332 366 | 
             
                alias_method :after_worker_boot, :after_worker_fork
         | 
| @@ -390,17 +424,17 @@ module Puma | |
| 390 424 | 
             
                # that have not checked in within the given +timeout+.
         | 
| 391 425 | 
             
                # This mitigates hung processes. Default value is 60 seconds.
         | 
| 392 426 | 
             
                def worker_timeout(timeout)
         | 
| 393 | 
            -
                  @options[:worker_timeout] = timeout
         | 
| 427 | 
            +
                  @options[:worker_timeout] = Integer(timeout)
         | 
| 394 428 | 
             
                end
         | 
| 395 429 |  | 
| 396 430 | 
             
                # *Cluster mode only* Set the timeout for workers to boot
         | 
| 397 431 | 
             
                def worker_boot_timeout(timeout)
         | 
| 398 | 
            -
                  @options[:worker_boot_timeout] = timeout
         | 
| 432 | 
            +
                  @options[:worker_boot_timeout] = Integer(timeout)
         | 
| 399 433 | 
             
                end
         | 
| 400 434 |  | 
| 401 435 | 
             
                # *Cluster mode only* Set the timeout for worker shutdown
         | 
| 402 436 | 
             
                def worker_shutdown_timeout(timeout)
         | 
| 403 | 
            -
                  @options[:worker_shutdown_timeout] = timeout
         | 
| 437 | 
            +
                  @options[:worker_shutdown_timeout] = Integer(timeout)
         | 
| 404 438 | 
             
                end
         | 
| 405 439 |  | 
| 406 440 | 
             
                # When set to true (the default), workers accept all requests
         | 
| @@ -468,10 +502,5 @@ module Puma | |
| 468 502 | 
             
                  end
         | 
| 469 503 | 
             
                end
         | 
| 470 504 |  | 
| 471 | 
            -
                private
         | 
| 472 | 
            -
             | 
| 473 | 
            -
                def _ary(key)
         | 
| 474 | 
            -
                  (@options.cur[key] ||= [])
         | 
| 475 | 
            -
                end
         | 
| 476 505 | 
             
              end
         | 
| 477 506 | 
             
            end
         |