piesync-puma 3.12.6

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 (82) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +1429 -0
  3. data/LICENSE +26 -0
  4. data/README.md +280 -0
  5. data/bin/puma +10 -0
  6. data/bin/puma-wild +31 -0
  7. data/bin/pumactl +12 -0
  8. data/docs/architecture.md +36 -0
  9. data/docs/deployment.md +91 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/nginx.md +80 -0
  14. data/docs/plugins.md +28 -0
  15. data/docs/restart.md +39 -0
  16. data/docs/signals.md +96 -0
  17. data/docs/systemd.md +272 -0
  18. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  19. data/ext/puma_http11/ext_help.h +15 -0
  20. data/ext/puma_http11/extconf.rb +15 -0
  21. data/ext/puma_http11/http11_parser.c +1071 -0
  22. data/ext/puma_http11/http11_parser.h +65 -0
  23. data/ext/puma_http11/http11_parser.java.rl +161 -0
  24. data/ext/puma_http11/http11_parser.rl +149 -0
  25. data/ext/puma_http11/http11_parser_common.rl +54 -0
  26. data/ext/puma_http11/io_buffer.c +155 -0
  27. data/ext/puma_http11/mini_ssl.c +494 -0
  28. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  29. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +470 -0
  30. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +352 -0
  31. data/ext/puma_http11/puma_http11.c +500 -0
  32. data/lib/puma.rb +23 -0
  33. data/lib/puma/accept_nonblock.rb +23 -0
  34. data/lib/puma/app/status.rb +74 -0
  35. data/lib/puma/binder.rb +413 -0
  36. data/lib/puma/cli.rb +235 -0
  37. data/lib/puma/client.rb +480 -0
  38. data/lib/puma/cluster.rb +531 -0
  39. data/lib/puma/commonlogger.rb +108 -0
  40. data/lib/puma/compat.rb +14 -0
  41. data/lib/puma/configuration.rb +361 -0
  42. data/lib/puma/const.rb +239 -0
  43. data/lib/puma/control_cli.rb +264 -0
  44. data/lib/puma/convenient.rb +25 -0
  45. data/lib/puma/daemon_ext.rb +33 -0
  46. data/lib/puma/delegation.rb +13 -0
  47. data/lib/puma/detect.rb +15 -0
  48. data/lib/puma/dsl.rb +518 -0
  49. data/lib/puma/events.rb +153 -0
  50. data/lib/puma/io_buffer.rb +9 -0
  51. data/lib/puma/java_io_buffer.rb +47 -0
  52. data/lib/puma/jruby_restart.rb +84 -0
  53. data/lib/puma/launcher.rb +433 -0
  54. data/lib/puma/minissl.rb +285 -0
  55. data/lib/puma/null_io.rb +44 -0
  56. data/lib/puma/plugin.rb +117 -0
  57. data/lib/puma/plugin/tmp_restart.rb +34 -0
  58. data/lib/puma/rack/backports/uri/common_193.rb +33 -0
  59. data/lib/puma/rack/builder.rb +299 -0
  60. data/lib/puma/rack/urlmap.rb +91 -0
  61. data/lib/puma/rack_default.rb +7 -0
  62. data/lib/puma/reactor.rb +347 -0
  63. data/lib/puma/runner.rb +184 -0
  64. data/lib/puma/server.rb +1072 -0
  65. data/lib/puma/single.rb +123 -0
  66. data/lib/puma/state_file.rb +31 -0
  67. data/lib/puma/tcp_logger.rb +41 -0
  68. data/lib/puma/thread_pool.rb +346 -0
  69. data/lib/puma/util.rb +129 -0
  70. data/lib/rack/handler/puma.rb +115 -0
  71. data/tools/jungle/README.md +19 -0
  72. data/tools/jungle/init.d/README.md +61 -0
  73. data/tools/jungle/init.d/puma +421 -0
  74. data/tools/jungle/init.d/run-puma +18 -0
  75. data/tools/jungle/rc.d/README.md +74 -0
  76. data/tools/jungle/rc.d/puma +61 -0
  77. data/tools/jungle/rc.d/puma.conf +10 -0
  78. data/tools/jungle/upstart/README.md +61 -0
  79. data/tools/jungle/upstart/puma-manager.conf +31 -0
  80. data/tools/jungle/upstart/puma.conf +69 -0
  81. data/tools/trickletest.rb +45 -0
  82. metadata +131 -0
@@ -0,0 +1,239 @@
1
+ #encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Puma
5
+ class UnsupportedOption < RuntimeError
6
+ end
7
+
8
+
9
+ # Every standard HTTP code mapped to the appropriate message. These are
10
+ # used so frequently that they are placed directly in Puma for easy
11
+ # access rather than Puma::Const itself.
12
+
13
+ # Every standard HTTP code mapped to the appropriate message.
14
+ # Generated with:
15
+ # curl -s https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv | \
16
+ # ruby -ne 'm = /^(\d{3}),(?!Unassigned|\(Unused\))([^,]+)/.match($_) and \
17
+ # puts "#{m[1]} => \x27#{m[2].strip}\x27,"'
18
+ HTTP_STATUS_CODES = {
19
+ 100 => 'Continue',
20
+ 101 => 'Switching Protocols',
21
+ 102 => 'Processing',
22
+ 200 => 'OK',
23
+ 201 => 'Created',
24
+ 202 => 'Accepted',
25
+ 203 => 'Non-Authoritative Information',
26
+ 204 => 'No Content',
27
+ 205 => 'Reset Content',
28
+ 206 => 'Partial Content',
29
+ 207 => 'Multi-Status',
30
+ 208 => 'Already Reported',
31
+ 226 => 'IM Used',
32
+ 300 => 'Multiple Choices',
33
+ 301 => 'Moved Permanently',
34
+ 302 => 'Found',
35
+ 303 => 'See Other',
36
+ 304 => 'Not Modified',
37
+ 305 => 'Use Proxy',
38
+ 307 => 'Temporary Redirect',
39
+ 308 => 'Permanent Redirect',
40
+ 400 => 'Bad Request',
41
+ 401 => 'Unauthorized',
42
+ 402 => 'Payment Required',
43
+ 403 => 'Forbidden',
44
+ 404 => 'Not Found',
45
+ 405 => 'Method Not Allowed',
46
+ 406 => 'Not Acceptable',
47
+ 407 => 'Proxy Authentication Required',
48
+ 408 => 'Request Timeout',
49
+ 409 => 'Conflict',
50
+ 410 => 'Gone',
51
+ 411 => 'Length Required',
52
+ 412 => 'Precondition Failed',
53
+ 413 => 'Payload Too Large',
54
+ 414 => 'URI Too Long',
55
+ 415 => 'Unsupported Media Type',
56
+ 416 => 'Range Not Satisfiable',
57
+ 417 => 'Expectation Failed',
58
+ 418 => 'I\'m A Teapot',
59
+ 421 => 'Misdirected Request',
60
+ 422 => 'Unprocessable Entity',
61
+ 423 => 'Locked',
62
+ 424 => 'Failed Dependency',
63
+ 426 => 'Upgrade Required',
64
+ 428 => 'Precondition Required',
65
+ 429 => 'Too Many Requests',
66
+ 431 => 'Request Header Fields Too Large',
67
+ 451 => 'Unavailable For Legal Reasons',
68
+ 500 => 'Internal Server Error',
69
+ 501 => 'Not Implemented',
70
+ 502 => 'Bad Gateway',
71
+ 503 => 'Service Unavailable',
72
+ 504 => 'Gateway Timeout',
73
+ 505 => 'HTTP Version Not Supported',
74
+ 506 => 'Variant Also Negotiates',
75
+ 507 => 'Insufficient Storage',
76
+ 508 => 'Loop Detected',
77
+ 510 => 'Not Extended',
78
+ 511 => 'Network Authentication Required'
79
+ }
80
+
81
+ # For some HTTP status codes the client only expects headers.
82
+ #
83
+
84
+ STATUS_WITH_NO_ENTITY_BODY = {
85
+ 204 => true,
86
+ 205 => true,
87
+ 304 => true
88
+ }
89
+
90
+ # Frequently used constants when constructing requests or responses. Many times
91
+ # the constant just refers to a string with the same contents. Using these constants
92
+ # gave about a 3% to 10% performance improvement over using the strings directly.
93
+ #
94
+ # The constants are frozen because Hash#[]= when called with a String key dups
95
+ # the String UNLESS the String is frozen. This saves us therefore 2 object
96
+ # allocations when creating the env hash later.
97
+ #
98
+ # While Puma does try to emulate the CGI/1.2 protocol, it does not use the REMOTE_IDENT,
99
+ # REMOTE_USER, or REMOTE_HOST parameters since those are either a security problem or
100
+ # too taxing on performance.
101
+ module Const
102
+
103
+ PUMA_VERSION = VERSION = "3.12.6".freeze
104
+ CODE_NAME = "Llamas in Pajamas".freeze
105
+ PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
106
+
107
+ FAST_TRACK_KA_TIMEOUT = 0.2
108
+
109
+ # The default number of seconds for another request within a persistent
110
+ # session.
111
+ PERSISTENT_TIMEOUT = 20
112
+
113
+ # The default number of seconds to wait until we get the first data
114
+ # for the request
115
+ FIRST_DATA_TIMEOUT = 30
116
+
117
+ # How long to wait when getting some write blocking on the socket when
118
+ # sending data back
119
+ WRITE_TIMEOUT = 10
120
+
121
+ # How many requests to attempt inline before sending a client back to
122
+ # the reactor to be subject to normal ordering. The idea here is that
123
+ # we amortize the cost of going back to the reactor for a well behaved
124
+ # but very "greedy" client across 10 requests. This prevents a not
125
+ # well behaved client from monopolizing the thread forever.
126
+ MAX_FAST_INLINE = 10
127
+
128
+ # The original URI requested by the client.
129
+ REQUEST_URI= 'REQUEST_URI'.freeze
130
+ REQUEST_PATH = 'REQUEST_PATH'.freeze
131
+ QUERY_STRING = 'QUERY_STRING'.freeze
132
+
133
+ PATH_INFO = 'PATH_INFO'.freeze
134
+
135
+ PUMA_TMP_BASE = "puma".freeze
136
+
137
+ # Indicate that we couldn't parse the request
138
+ ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n".freeze
139
+
140
+ # The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
141
+ ERROR_404_RESPONSE = "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND".freeze
142
+
143
+ # The standard empty 408 response for requests that timed out.
144
+ ERROR_408_RESPONSE = "HTTP/1.1 408 Request Timeout\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\n".freeze
145
+
146
+ CONTENT_LENGTH = "CONTENT_LENGTH".freeze
147
+
148
+ # Indicate that there was an internal error, obviously.
149
+ ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n".freeze
150
+
151
+ # A common header for indicating the server is too busy. Not used yet.
152
+ ERROR_503_RESPONSE = "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
153
+
154
+ # The basic max request size we'll try to read.
155
+ CHUNK_SIZE = 16 * 1024
156
+
157
+ # This is the maximum header that is allowed before a client is booted. The parser detects
158
+ # this, but we'd also like to do this as well.
159
+ MAX_HEADER = 1024 * (80 + 32)
160
+
161
+ # Maximum request body size before it is moved out of memory and into a tempfile for reading.
162
+ MAX_BODY = MAX_HEADER
163
+
164
+ REQUEST_METHOD = "REQUEST_METHOD".freeze
165
+ HEAD = "HEAD".freeze
166
+ # ETag is based on the apache standard of hex mtime-size-inode (inode is 0 on win32)
167
+ LINE_END = "\r\n".freeze
168
+ REMOTE_ADDR = "REMOTE_ADDR".freeze
169
+ HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
170
+
171
+ SERVER_NAME = "SERVER_NAME".freeze
172
+ SERVER_PORT = "SERVER_PORT".freeze
173
+ HTTP_HOST = "HTTP_HOST".freeze
174
+ PORT_80 = "80".freeze
175
+ PORT_443 = "443".freeze
176
+ LOCALHOST = "localhost".freeze
177
+ LOCALHOST_IP = "127.0.0.1".freeze
178
+ LOCALHOST_ADDR = "127.0.0.1:0".freeze
179
+
180
+ SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
181
+ HTTP_11 = "HTTP/1.1".freeze
182
+
183
+ SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
184
+ GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
185
+ CGI_VER = "CGI/1.2".freeze
186
+
187
+ STOP_COMMAND = "?".freeze
188
+ HALT_COMMAND = "!".freeze
189
+ RESTART_COMMAND = "R".freeze
190
+
191
+ RACK_INPUT = "rack.input".freeze
192
+ RACK_URL_SCHEME = "rack.url_scheme".freeze
193
+ RACK_AFTER_REPLY = "rack.after_reply".freeze
194
+ PUMA_SOCKET = "puma.socket".freeze
195
+ PUMA_CONFIG = "puma.config".freeze
196
+ PUMA_PEERCERT = "puma.peercert".freeze
197
+
198
+ HTTP = "http".freeze
199
+ HTTPS = "https".freeze
200
+
201
+ HTTPS_KEY = "HTTPS".freeze
202
+
203
+ HTTP_VERSION = "HTTP_VERSION".freeze
204
+ HTTP_CONNECTION = "HTTP_CONNECTION".freeze
205
+ HTTP_EXPECT = "HTTP_EXPECT".freeze
206
+ CONTINUE = "100-continue".freeze
207
+
208
+ HTTP_11_100 = "HTTP/1.1 100 Continue\r\n\r\n".freeze
209
+ HTTP_11_200 = "HTTP/1.1 200 OK\r\n".freeze
210
+ HTTP_10_200 = "HTTP/1.0 200 OK\r\n".freeze
211
+
212
+ CLOSE = "close".freeze
213
+ KEEP_ALIVE = "keep-alive".freeze
214
+
215
+ CONTENT_LENGTH2 = "content-length".freeze
216
+ CONTENT_LENGTH_S = "Content-Length: ".freeze
217
+ TRANSFER_ENCODING = "transfer-encoding".freeze
218
+ TRANSFER_ENCODING2 = "HTTP_TRANSFER_ENCODING".freeze
219
+
220
+ CONNECTION_CLOSE = "Connection: close\r\n".freeze
221
+ CONNECTION_KEEP_ALIVE = "Connection: Keep-Alive\r\n".freeze
222
+
223
+ TRANSFER_ENCODING_CHUNKED = "Transfer-Encoding: chunked\r\n".freeze
224
+ CLOSE_CHUNKED = "0\r\n\r\n".freeze
225
+
226
+ CHUNKED = "chunked".freeze
227
+
228
+ COLON = ": ".freeze
229
+
230
+ NEWLINE = "\n".freeze
231
+ HTTP_INJECTION_REGEX = /[\r\n]/.freeze
232
+
233
+ HIJACK_P = "rack.hijack?".freeze
234
+ HIJACK = "rack.hijack".freeze
235
+ HIJACK_IO = "rack.hijack_io".freeze
236
+
237
+ EARLY_HINTS = "rack.early_hints".freeze
238
+ end
239
+ end
@@ -0,0 +1,264 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+ require_relative 'state_file'
5
+ require_relative 'const'
6
+ require_relative 'detect'
7
+ require_relative 'configuration'
8
+ require 'uri'
9
+ require 'socket'
10
+
11
+ module Puma
12
+ class ControlCLI
13
+
14
+ COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats}
15
+
16
+ def initialize(argv, stdout=STDOUT, stderr=STDERR)
17
+ @state = nil
18
+ @quiet = false
19
+ @pidfile = nil
20
+ @pid = nil
21
+ @control_url = nil
22
+ @control_auth_token = nil
23
+ @config_file = nil
24
+ @command = nil
25
+
26
+ @argv = argv.dup
27
+ @stdout = stdout
28
+ @stderr = stderr
29
+ @cli_options = {}
30
+
31
+ opts = OptionParser.new do |o|
32
+ o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token | -F config.rb) (#{COMMANDS.join("|")})"
33
+
34
+ o.on "-S", "--state PATH", "Where the state file to use is" do |arg|
35
+ @state = arg
36
+ end
37
+
38
+ o.on "-Q", "--quiet", "Not display messages" do |arg|
39
+ @quiet = true
40
+ end
41
+
42
+ o.on "-P", "--pidfile PATH", "Pid file" do |arg|
43
+ @pidfile = arg
44
+ end
45
+
46
+ o.on "-p", "--pid PID", "Pid" do |arg|
47
+ @pid = arg.to_i
48
+ end
49
+
50
+ o.on "-C", "--control-url URL", "The bind url to use for the control server" do |arg|
51
+ @control_url = arg
52
+ end
53
+
54
+ o.on "-T", "--control-token TOKEN", "The token to use as authentication for the control server" do |arg|
55
+ @control_auth_token = arg
56
+ end
57
+
58
+ o.on "-F", "--config-file PATH", "Puma config script" do |arg|
59
+ @config_file = arg
60
+ end
61
+
62
+ o.on_tail("-H", "--help", "Show this message") do
63
+ @stdout.puts o
64
+ exit
65
+ end
66
+
67
+ o.on_tail("-V", "--version", "Show version") do
68
+ puts Const::PUMA_VERSION
69
+ exit
70
+ end
71
+ end
72
+
73
+ opts.order!(argv) { |a| opts.terminate a }
74
+ opts.parse!
75
+
76
+ @command = argv.shift
77
+
78
+ unless @config_file == '-'
79
+ if @config_file.nil? and File.exist?('config/puma.rb')
80
+ @config_file = 'config/puma.rb'
81
+ end
82
+
83
+ if @config_file
84
+ config = Puma::Configuration.new({ config_files: [@config_file] }, {})
85
+ config.load
86
+ @state ||= config.options[:state]
87
+ @control_url ||= config.options[:control_url]
88
+ @control_auth_token ||= config.options[:control_auth_token]
89
+ @pidfile ||= config.options[:pidfile]
90
+ end
91
+ end
92
+
93
+ # check present of command
94
+ unless @command
95
+ raise "Available commands: #{COMMANDS.join(", ")}"
96
+ end
97
+
98
+ unless COMMANDS.include? @command
99
+ raise "Invalid command: #{@command}"
100
+ end
101
+
102
+ rescue => e
103
+ @stdout.puts e.message
104
+ @stdout.puts e.backtrace
105
+ exit 1
106
+ end
107
+
108
+ def message(msg)
109
+ @stdout.puts msg unless @quiet
110
+ end
111
+
112
+ def prepare_configuration
113
+ if @state
114
+ unless File.exist? @state
115
+ raise "State file not found: #{@state}"
116
+ end
117
+
118
+ sf = Puma::StateFile.new
119
+ sf.load @state
120
+
121
+ @control_url = sf.control_url
122
+ @control_auth_token = sf.control_auth_token
123
+ @pid = sf.pid
124
+ elsif @pidfile
125
+ # get pid from pid_file
126
+ @pid = File.open(@pidfile).gets.to_i
127
+ end
128
+ end
129
+
130
+ def send_request
131
+ uri = URI.parse @control_url
132
+
133
+ # create server object by scheme
134
+ server = case uri.scheme
135
+ when "tcp"
136
+ TCPSocket.new uri.host, uri.port
137
+ when "unix"
138
+ UNIXSocket.new "#{uri.host}#{uri.path}"
139
+ else
140
+ raise "Invalid scheme: #{uri.scheme}"
141
+ end
142
+
143
+ if @command == "status"
144
+ message "Puma is started"
145
+ else
146
+ url = "/#{@command}"
147
+
148
+ if @control_auth_token
149
+ url = url + "?token=#{@control_auth_token}"
150
+ end
151
+
152
+ server << "GET #{url} HTTP/1.0\r\n\r\n"
153
+
154
+ unless data = server.read
155
+ raise "Server closed connection before responding"
156
+ end
157
+
158
+ response = data.split("\r\n")
159
+
160
+ if response.empty?
161
+ raise "Server sent empty response"
162
+ end
163
+
164
+ (@http,@code,@message) = response.first.split(" ",3)
165
+
166
+ if @code == "403"
167
+ raise "Unauthorized access to server (wrong auth token)"
168
+ elsif @code == "404"
169
+ raise "Command error: #{response.last}"
170
+ elsif @code != "200"
171
+ raise "Bad response from server: #{@code}"
172
+ end
173
+
174
+ message "Command #{@command} sent success"
175
+ message response.last if @command == "stats" || @command == "gc-stats"
176
+ end
177
+ ensure
178
+ server.close if server && !server.closed?
179
+ end
180
+
181
+ def send_signal
182
+ unless @pid
183
+ raise "Neither pid nor control url available"
184
+ end
185
+
186
+ begin
187
+
188
+ case @command
189
+ when "restart"
190
+ Process.kill "SIGUSR2", @pid
191
+
192
+ when "halt"
193
+ Process.kill "QUIT", @pid
194
+
195
+ when "stop"
196
+ Process.kill "SIGTERM", @pid
197
+
198
+ when "stats"
199
+ puts "Stats not available via pid only"
200
+ return
201
+
202
+ when "reload-worker-directory"
203
+ puts "reload-worker-directory not available via pid only"
204
+ return
205
+
206
+ when "phased-restart"
207
+ Process.kill "SIGUSR1", @pid
208
+
209
+ else
210
+ return
211
+ end
212
+
213
+ rescue SystemCallError
214
+ if @command == "restart"
215
+ start
216
+ else
217
+ raise "No pid '#{@pid}' found"
218
+ end
219
+ end
220
+
221
+ message "Command #{@command} sent success"
222
+ end
223
+
224
+ def run
225
+ return start if @command == "start"
226
+
227
+ prepare_configuration
228
+
229
+ if Puma.windows?
230
+ send_request
231
+ else
232
+ @control_url ? send_request : send_signal
233
+ end
234
+
235
+ rescue => e
236
+ message e.message
237
+ message e.backtrace
238
+ exit 1
239
+ end
240
+
241
+ private
242
+ def start
243
+ require 'puma/cli'
244
+
245
+ run_args = []
246
+
247
+ run_args += ["-S", @state] if @state
248
+ run_args += ["-q"] if @quiet
249
+ run_args += ["--pidfile", @pidfile] if @pidfile
250
+ run_args += ["--control-url", @control_url] if @control_url
251
+ run_args += ["--control-token", @control_auth_token] if @control_auth_token
252
+ run_args += ["-C", @config_file] if @config_file
253
+
254
+ events = Puma::Events.new @stdout, @stderr
255
+
256
+ # replace $0 because puma use it to generate restart command
257
+ puma_cmd = $0.gsub(/pumactl$/, 'puma')
258
+ $0 = puma_cmd if File.exist?(puma_cmd)
259
+
260
+ cli = Puma::CLI.new run_args, events
261
+ cli.run
262
+ end
263
+ end
264
+ end