puma 3.11.1 → 6.6.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.
Files changed (98) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +2092 -422
  3. data/LICENSE +23 -20
  4. data/README.md +301 -69
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +59 -21
  7. data/docs/compile_options.md +55 -0
  8. data/docs/deployment.md +69 -58
  9. data/docs/fork_worker.md +41 -0
  10. data/docs/java_options.md +54 -0
  11. data/docs/jungle/README.md +9 -0
  12. data/docs/jungle/rc.d/README.md +74 -0
  13. data/docs/jungle/rc.d/puma +61 -0
  14. data/docs/jungle/rc.d/puma.conf +10 -0
  15. data/docs/kubernetes.md +78 -0
  16. data/docs/nginx.md +2 -2
  17. data/docs/plugins.md +26 -12
  18. data/docs/rails_dev_mode.md +28 -0
  19. data/docs/restart.md +48 -22
  20. data/docs/signals.md +13 -11
  21. data/docs/stats.md +147 -0
  22. data/docs/systemd.md +108 -117
  23. data/docs/testing_benchmarks_local_files.md +150 -0
  24. data/docs/testing_test_rackup_ci_files.md +36 -0
  25. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  26. data/ext/puma_http11/ext_help.h +1 -1
  27. data/ext/puma_http11/extconf.rb +68 -3
  28. data/ext/puma_http11/http11_parser.c +106 -118
  29. data/ext/puma_http11/http11_parser.h +2 -2
  30. data/ext/puma_http11/http11_parser.java.rl +22 -38
  31. data/ext/puma_http11/http11_parser.rl +6 -4
  32. data/ext/puma_http11/http11_parser_common.rl +6 -6
  33. data/ext/puma_http11/mini_ssl.c +474 -94
  34. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  35. data/ext/puma_http11/org/jruby/puma/Http11.java +136 -121
  36. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
  37. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +251 -88
  38. data/ext/puma_http11/puma_http11.c +53 -58
  39. data/lib/puma/app/status.rb +71 -49
  40. data/lib/puma/binder.rb +257 -151
  41. data/lib/puma/cli.rb +61 -38
  42. data/lib/puma/client.rb +464 -224
  43. data/lib/puma/cluster/worker.rb +183 -0
  44. data/lib/puma/cluster/worker_handle.rb +96 -0
  45. data/lib/puma/cluster.rb +343 -239
  46. data/lib/puma/commonlogger.rb +23 -14
  47. data/lib/puma/configuration.rb +144 -96
  48. data/lib/puma/const.rb +194 -115
  49. data/lib/puma/control_cli.rb +135 -81
  50. data/lib/puma/detect.rb +34 -2
  51. data/lib/puma/dsl.rb +1092 -153
  52. data/lib/puma/error_logger.rb +113 -0
  53. data/lib/puma/events.rb +17 -111
  54. data/lib/puma/io_buffer.rb +44 -5
  55. data/lib/puma/jruby_restart.rb +2 -73
  56. data/lib/puma/json_serialization.rb +96 -0
  57. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  58. data/lib/puma/launcher.rb +205 -138
  59. data/lib/puma/log_writer.rb +147 -0
  60. data/lib/puma/minissl/context_builder.rb +96 -0
  61. data/lib/puma/minissl.rb +279 -70
  62. data/lib/puma/null_io.rb +61 -2
  63. data/lib/puma/plugin/systemd.rb +90 -0
  64. data/lib/puma/plugin/tmp_restart.rb +3 -1
  65. data/lib/puma/plugin.rb +9 -13
  66. data/lib/puma/rack/builder.rb +10 -11
  67. data/lib/puma/rack/urlmap.rb +3 -1
  68. data/lib/puma/rack_default.rb +21 -4
  69. data/lib/puma/reactor.rb +97 -185
  70. data/lib/puma/request.rb +688 -0
  71. data/lib/puma/runner.rb +114 -69
  72. data/lib/puma/sd_notify.rb +146 -0
  73. data/lib/puma/server.rb +409 -704
  74. data/lib/puma/single.rb +29 -72
  75. data/lib/puma/state_file.rb +48 -9
  76. data/lib/puma/thread_pool.rb +234 -93
  77. data/lib/puma/util.rb +23 -10
  78. data/lib/puma.rb +68 -5
  79. data/lib/rack/handler/puma.rb +119 -86
  80. data/tools/Dockerfile +16 -0
  81. data/tools/trickletest.rb +0 -1
  82. metadata +55 -33
  83. data/ext/puma_http11/io_buffer.c +0 -155
  84. data/lib/puma/accept_nonblock.rb +0 -23
  85. data/lib/puma/compat.rb +0 -14
  86. data/lib/puma/convenient.rb +0 -23
  87. data/lib/puma/daemon_ext.rb +0 -31
  88. data/lib/puma/delegation.rb +0 -11
  89. data/lib/puma/java_io_buffer.rb +0 -45
  90. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
  91. data/lib/puma/tcp_logger.rb +0 -39
  92. data/tools/jungle/README.md +0 -13
  93. data/tools/jungle/init.d/README.md +0 -59
  94. data/tools/jungle/init.d/puma +0 -421
  95. data/tools/jungle/init.d/run-puma +0 -18
  96. data/tools/jungle/upstart/README.md +0 -61
  97. data/tools/jungle/upstart/puma-manager.conf +0 -31
  98. data/tools/jungle/upstart/puma.conf +0 -69
data/lib/puma/const.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  #encoding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  module Puma
3
5
  class UnsupportedOption < RuntimeError
4
6
  end
5
7
 
6
-
7
8
  # Every standard HTTP code mapped to the appropriate message. These are
8
9
  # used so frequently that they are placed directly in Puma for easy
9
10
  # access rather than Puma::Const itself.
@@ -17,6 +18,7 @@ module Puma
17
18
  100 => 'Continue',
18
19
  101 => 'Switching Protocols',
19
20
  102 => 'Processing',
21
+ 103 => 'Early Hints',
20
22
  200 => 'OK',
21
23
  201 => 'Created',
22
24
  202 => 'Accepted',
@@ -48,16 +50,16 @@ module Puma
48
50
  410 => 'Gone',
49
51
  411 => 'Length Required',
50
52
  412 => 'Precondition Failed',
51
- 413 => 'Payload Too Large',
53
+ 413 => 'Content Too Large',
52
54
  414 => 'URI Too Long',
53
55
  415 => 'Unsupported Media Type',
54
56
  416 => 'Range Not Satisfiable',
55
57
  417 => 'Expectation Failed',
56
- 418 => 'I\'m A Teapot',
57
58
  421 => 'Misdirected Request',
58
- 422 => 'Unprocessable Entity',
59
+ 422 => 'Unprocessable Content',
59
60
  423 => 'Locked',
60
61
  424 => 'Failed Dependency',
62
+ 425 => 'Too Early',
61
63
  426 => 'Upgrade Required',
62
64
  428 => 'Precondition Required',
63
65
  429 => 'Too Many Requests',
@@ -72,9 +74,9 @@ module Puma
72
74
  506 => 'Variant Also Negotiates',
73
75
  507 => 'Insufficient Storage',
74
76
  508 => 'Loop Detected',
75
- 510 => 'Not Extended',
77
+ 510 => 'Not Extended (OBSOLETED)',
76
78
  511 => 'Network Authentication Required'
77
- }
79
+ }.freeze
78
80
 
79
81
  # For some HTTP status codes the client only expects headers.
80
82
  #
@@ -83,7 +85,7 @@ module Puma
83
85
  204 => true,
84
86
  205 => true,
85
87
  304 => true
86
- }
88
+ }.freeze
87
89
 
88
90
  # Frequently used constants when constructing requests or responses. Many times
89
91
  # the constant just refers to a string with the same contents. Using these constants
@@ -98,52 +100,44 @@ module Puma
98
100
  # too taxing on performance.
99
101
  module Const
100
102
 
101
- PUMA_VERSION = VERSION = "3.11.1".freeze
102
- CODE_NAME = "Love Song".freeze
103
- PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
104
-
105
- FAST_TRACK_KA_TIMEOUT = 0.2
103
+ PUMA_VERSION = VERSION = "6.6.0"
104
+ CODE_NAME = "Return to Forever"
106
105
 
107
- # The default number of seconds for another request within a persistent
108
- # session.
109
- PERSISTENT_TIMEOUT = 20
106
+ PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
110
107
 
111
- # The default number of seconds to wait until we get the first data
112
- # for the request
113
- FIRST_DATA_TIMEOUT = 30
108
+ FAST_TRACK_KA_TIMEOUT = 0.2
114
109
 
115
110
  # How long to wait when getting some write blocking on the socket when
116
111
  # sending data back
117
112
  WRITE_TIMEOUT = 10
118
113
 
119
114
  # The original URI requested by the client.
120
- REQUEST_URI= 'REQUEST_URI'.freeze
121
- REQUEST_PATH = 'REQUEST_PATH'.freeze
122
- QUERY_STRING = 'QUERY_STRING'.freeze
123
-
124
- PATH_INFO = 'PATH_INFO'.freeze
125
-
126
- PUMA_TMP_BASE = "puma".freeze
127
-
128
- # Indicate that we couldn't parse the request
129
- ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n".freeze
130
-
131
- # The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
132
- ERROR_404_RESPONSE = "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND".freeze
133
-
134
- # The standard empty 408 response for requests that timed out.
135
- ERROR_408_RESPONSE = "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n".freeze
136
-
137
- CONTENT_LENGTH = "CONTENT_LENGTH".freeze
138
-
139
- # Indicate that there was an internal error, obviously.
140
- ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n".freeze
141
-
142
- # A common header for indicating the server is too busy. Not used yet.
143
- ERROR_503_RESPONSE = "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
115
+ REQUEST_URI= "REQUEST_URI"
116
+ REQUEST_PATH = "REQUEST_PATH"
117
+ QUERY_STRING = "QUERY_STRING"
118
+ CONTENT_LENGTH = "CONTENT_LENGTH"
119
+
120
+ PATH_INFO = "PATH_INFO"
121
+
122
+ PUMA_TMP_BASE = "puma"
123
+
124
+ ERROR_RESPONSE = {
125
+ # Indicate that we couldn't parse the request
126
+ 400 => "HTTP/1.1 400 Bad Request\r\n\r\n",
127
+ # The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
128
+ 404 => "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n",
129
+ # The standard empty 408 response for requests that timed out.
130
+ 408 => "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n\r\n",
131
+ # Indicate that there was an internal error, obviously.
132
+ 500 => "HTTP/1.1 500 Internal Server Error\r\n\r\n",
133
+ # Incorrect or invalid header value
134
+ 501 => "HTTP/1.1 501 Not Implemented\r\n\r\n",
135
+ # A common header for indicating the server is too busy. Not used yet.
136
+ 503 => "HTTP/1.1 503 Service Unavailable\r\n\r\n"
137
+ }.freeze
144
138
 
145
139
  # The basic max request size we'll try to read.
146
- CHUNK_SIZE = 16 * 1024
140
+ CHUNK_SIZE = 64 * 1024
147
141
 
148
142
  # This is the maximum header that is allowed before a client is booted. The parser detects
149
143
  # this, but we'd also like to do this as well.
@@ -152,78 +146,163 @@ module Puma
152
146
  # Maximum request body size before it is moved out of memory and into a tempfile for reading.
153
147
  MAX_BODY = MAX_HEADER
154
148
 
155
- REQUEST_METHOD = "REQUEST_METHOD".freeze
156
- HEAD = "HEAD".freeze
157
- # ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
158
- LINE_END = "\r\n".freeze
159
- REMOTE_ADDR = "REMOTE_ADDR".freeze
160
- HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
161
-
162
- SERVER_NAME = "SERVER_NAME".freeze
163
- SERVER_PORT = "SERVER_PORT".freeze
164
- HTTP_HOST = "HTTP_HOST".freeze
165
- PORT_80 = "80".freeze
166
- PORT_443 = "443".freeze
167
- LOCALHOST = "localhost".freeze
168
- LOCALHOST_IP = "127.0.0.1".freeze
169
- LOCALHOST_ADDR = "127.0.0.1:0".freeze
170
-
171
- SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
172
- HTTP_11 = "HTTP/1.1".freeze
149
+ REQUEST_METHOD = "REQUEST_METHOD"
150
+ HEAD = "HEAD"
151
+
152
+ # based on https://www.rfc-editor.org/rfc/rfc9110.html#name-overview,
153
+ # with CONNECT removed, and PATCH added
154
+ SUPPORTED_HTTP_METHODS = %w[HEAD GET POST PUT DELETE OPTIONS TRACE PATCH].freeze
155
+
156
+ # list from https://www.iana.org/assignments/http-methods/http-methods.xhtml
157
+ # as of 04-May-23
158
+ IANA_HTTP_METHODS = %w[
159
+ ACL
160
+ BASELINE-CONTROL
161
+ BIND
162
+ CHECKIN
163
+ CHECKOUT
164
+ CONNECT
165
+ COPY
166
+ DELETE
167
+ GET
168
+ HEAD
169
+ LABEL
170
+ LINK
171
+ LOCK
172
+ MERGE
173
+ MKACTIVITY
174
+ MKCALENDAR
175
+ MKCOL
176
+ MKREDIRECTREF
177
+ MKWORKSPACE
178
+ MOVE
179
+ OPTIONS
180
+ ORDERPATCH
181
+ PATCH
182
+ POST
183
+ PRI
184
+ PROPFIND
185
+ PROPPATCH
186
+ PUT
187
+ REBIND
188
+ REPORT
189
+ SEARCH
190
+ TRACE
191
+ UNBIND
192
+ UNCHECKOUT
193
+ UNLINK
194
+ UNLOCK
195
+ UPDATE
196
+ UPDATEREDIRECTREF
197
+ VERSION-CONTROL
198
+ ].freeze
173
199
 
174
- SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
175
- GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
176
- CGI_VER = "CGI/1.2".freeze
177
-
178
- STOP_COMMAND = "?".freeze
179
- HALT_COMMAND = "!".freeze
180
- RESTART_COMMAND = "R".freeze
181
-
182
- RACK_INPUT = "rack.input".freeze
183
- RACK_URL_SCHEME = "rack.url_scheme".freeze
184
- RACK_AFTER_REPLY = "rack.after_reply".freeze
185
- PUMA_SOCKET = "puma.socket".freeze
186
- PUMA_CONFIG = "puma.config".freeze
187
- PUMA_PEERCERT = "puma.peercert".freeze
188
-
189
- HTTP = "http".freeze
190
- HTTPS = "https".freeze
191
-
192
- HTTPS_KEY = "HTTPS".freeze
193
-
194
- HTTP_VERSION = "HTTP_VERSION".freeze
195
- HTTP_CONNECTION = "HTTP_CONNECTION".freeze
196
- HTTP_EXPECT = "HTTP_EXPECT".freeze
197
- CONTINUE = "100-continue".freeze
198
-
199
- HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n".freeze
200
- HTTP_11_200 = "HTTP/1.1 200 OK\r\n".freeze
201
- HTTP_10_200 = "HTTP/1.0 200 OK\r\n".freeze
202
-
203
- CLOSE = "close".freeze
204
- KEEP_ALIVE = "keep-alive".freeze
205
-
206
- CONTENT_LENGTH2 = "content-length".freeze
207
- CONTENT_LENGTH_S = "Content-Length: ".freeze
208
- TRANSFER_ENCODING = "transfer-encoding".freeze
209
- TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING".freeze
210
-
211
- CONNECTION_CLOSE = "Connection: close\r\n".freeze
212
- CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n".freeze
213
-
214
- TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n".freeze
215
- CLOSE_CHUNKED = "0\r\n\r\n".freeze
216
-
217
- CHUNKED = "chunked".freeze
218
-
219
- COLON = ": ".freeze
220
-
221
- NEWLINE = "\n".freeze
222
-
223
- HIJACK_P = "rack.hijack?".freeze
224
- HIJACK = "rack.hijack".freeze
225
- HIJACK_IO = "rack.hijack_io".freeze
226
-
227
- EARLY_HINTS = "rack.early_hints".freeze
200
+ # ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
201
+ LINE_END = "\r\n"
202
+ REMOTE_ADDR = "REMOTE_ADDR"
203
+ HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
204
+ HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL"
205
+ HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME"
206
+ HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO"
207
+
208
+ SERVER_NAME = "SERVER_NAME"
209
+ SERVER_PORT = "SERVER_PORT"
210
+ HTTP_HOST = "HTTP_HOST"
211
+ PORT_80 = "80"
212
+ PORT_443 = "443"
213
+ LOCALHOST = "localhost"
214
+ LOCALHOST_IPV4 = "127.0.0.1"
215
+ LOCALHOST_IPV6 = "::1"
216
+ UNSPECIFIED_IPV4 = "0.0.0.0"
217
+ UNSPECIFIED_IPV6 = "::"
218
+
219
+ SERVER_PROTOCOL = "SERVER_PROTOCOL"
220
+ HTTP_11 = "HTTP/1.1"
221
+
222
+ SERVER_SOFTWARE = "SERVER_SOFTWARE"
223
+ GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
224
+ CGI_VER = "CGI/1.2"
225
+
226
+ STOP_COMMAND = "?"
227
+ HALT_COMMAND = "!"
228
+ RESTART_COMMAND = "R"
229
+
230
+ RACK_INPUT = "rack.input"
231
+ RACK_URL_SCHEME = "rack.url_scheme"
232
+ RACK_AFTER_REPLY = "rack.after_reply"
233
+ PUMA_SOCKET = "puma.socket"
234
+ PUMA_CONFIG = "puma.config"
235
+ PUMA_PEERCERT = "puma.peercert"
236
+
237
+ HTTP = "http"
238
+ HTTPS = "https"
239
+
240
+ HTTPS_KEY = "HTTPS"
241
+
242
+ HTTP_VERSION = "HTTP_VERSION"
243
+ HTTP_CONNECTION = "HTTP_CONNECTION"
244
+ HTTP_EXPECT = "HTTP_EXPECT"
245
+ CONTINUE = "100-continue"
246
+
247
+ HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n"
248
+ HTTP_11_200 = "HTTP/1.1 200 OK\r\n"
249
+ HTTP_10_200 = "HTTP/1.0 200 OK\r\n"
250
+
251
+ CLOSE = "close"
252
+ KEEP_ALIVE = "keep-alive"
253
+
254
+ CONTENT_LENGTH2 = "content-length"
255
+ CONTENT_LENGTH_S = "Content-Length: "
256
+ TRANSFER_ENCODING = "transfer-encoding"
257
+ TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING"
258
+
259
+ CONNECTION_CLOSE = "Connection: close\r\n"
260
+ CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n"
261
+
262
+ TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n"
263
+ CLOSE_CHUNKED = "0\r\n\r\n"
264
+
265
+ CHUNKED = "chunked"
266
+
267
+ COLON = ": "
268
+
269
+ NEWLINE = "\n"
270
+
271
+ HIJACK_P = "rack.hijack?"
272
+ HIJACK = "rack.hijack"
273
+ HIJACK_IO = "rack.hijack_io"
274
+
275
+ EARLY_HINTS = "rack.early_hints"
276
+
277
+ # Illegal character in the key or value of response header
278
+ DQUOTE = "\""
279
+ HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
280
+ ILLEGAL_HEADER_KEY_REGEX = /[\x00-\x20#{DQUOTE}#{HTTP_HEADER_DELIMITER}]/.freeze
281
+ # header values can contain HTAB?
282
+ ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
283
+
284
+ # The keys of headers that should not be convert to underscore
285
+ # normalized versions. These headers are ignored at the request reading layer,
286
+ # but if we normalize them after reading, it's just confusing for the application.
287
+ UNMASKABLE_HEADERS = {
288
+ "HTTP_TRANSFER,ENCODING" => true,
289
+ "HTTP_CONTENT,LENGTH" => true,
290
+ }
291
+
292
+ # Banned keys of response header
293
+ BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
294
+
295
+ PROXY_PROTOCOL_V1_REGEX = /^PROXY (?:TCP4|TCP6|UNKNOWN) ([^\r]+)\r\n/.freeze
296
+
297
+ # All constants are prefixed with `PIPE_` to avoid name collisions.
298
+ module PipeRequest
299
+ PIPE_WAKEUP = "!"
300
+ PIPE_BOOT = "b"
301
+ PIPE_FORK = "f"
302
+ PIPE_EXTERNAL_TERM = "e"
303
+ PIPE_TERM = "t"
304
+ PIPE_PING = "p"
305
+ PIPE_IDLE = "i"
306
+ end
228
307
  end
229
308
  end