piesync-puma 3.12.6

Sign up to get free protection for your applications and to get access to all the features.
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,23 @@
1
+ # Standard libraries
2
+ require 'socket'
3
+ require 'tempfile'
4
+ require 'time'
5
+ require 'etc'
6
+ require 'uri'
7
+ require 'stringio'
8
+
9
+ require 'thread'
10
+
11
+ module Puma
12
+ autoload :Const, 'puma/const'
13
+ autoload :Server, 'puma/server'
14
+ autoload :Launcher, 'puma/launcher'
15
+
16
+ def self.stats_object=(val)
17
+ @get_stats = val
18
+ end
19
+
20
+ def self.stats
21
+ @get_stats.stats
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'openssl'
2
+
3
+ module OpenSSL
4
+ module SSL
5
+ class SSLServer
6
+ unless public_method_defined? :accept_nonblock
7
+ def accept_nonblock
8
+ sock = @svr.accept_nonblock
9
+
10
+ begin
11
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
12
+ ssl.sync_close = true
13
+ ssl.accept if @start_immediately
14
+ ssl
15
+ rescue SSLError => ex
16
+ sock.close
17
+ raise ex
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,74 @@
1
+ module Puma
2
+ module App
3
+ class Status
4
+ def initialize(cli)
5
+ @cli = cli
6
+ @auth_token = nil
7
+ end
8
+ OK_STATUS = '{ "status": "ok" }'.freeze
9
+
10
+ attr_accessor :auth_token
11
+
12
+ def authenticate(env)
13
+ return true unless @auth_token
14
+ env['QUERY_STRING'].to_s.split(/&;/).include?("token=#{@auth_token}")
15
+ end
16
+
17
+ def rack_response(status, body, content_type='application/json')
18
+ headers = {
19
+ 'Content-Type' => content_type,
20
+ 'Content-Length' => body.bytesize.to_s
21
+ }
22
+
23
+ [status, headers, [body]]
24
+ end
25
+
26
+ def call(env)
27
+ unless authenticate(env)
28
+ return rack_response(403, 'Invalid auth token', 'text/plain')
29
+ end
30
+
31
+ case env['PATH_INFO']
32
+ when /\/stop$/
33
+ @cli.stop
34
+ return rack_response(200, OK_STATUS)
35
+
36
+ when /\/halt$/
37
+ @cli.halt
38
+ return rack_response(200, OK_STATUS)
39
+
40
+ when /\/restart$/
41
+ @cli.restart
42
+ return rack_response(200, OK_STATUS)
43
+
44
+ when /\/phased-restart$/
45
+ if !@cli.phased_restart
46
+ return rack_response(404, '{ "error": "phased restart not available" }')
47
+ else
48
+ return rack_response(200, OK_STATUS)
49
+ end
50
+
51
+ when /\/reload-worker-directory$/
52
+ if !@cli.send(:reload_worker_directory)
53
+ return rack_response(404, '{ "error": "reload_worker_directory not available" }')
54
+ else
55
+ return rack_response(200, OK_STATUS)
56
+ end
57
+
58
+ when /\/gc$/
59
+ GC.start
60
+ return rack_response(200, OK_STATUS)
61
+
62
+ when /\/gc-stats$/
63
+ json = "{" + GC.stat.map { |k, v| "\"#{k}\": #{v}" }.join(",") + "}"
64
+ return rack_response(200, json)
65
+
66
+ when /\/stats$/
67
+ return rack_response(200, @cli.stats)
68
+ else
69
+ rack_response 404, "Unsupported action", 'text/plain'
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,413 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'socket'
5
+
6
+ require 'puma/const'
7
+ require 'puma/util'
8
+
9
+ module Puma
10
+ class Binder
11
+ include Puma::Const
12
+
13
+ RACK_VERSION = [1,3].freeze
14
+
15
+ def initialize(events)
16
+ @events = events
17
+ @listeners = []
18
+ @inherited_fds = {}
19
+ @activated_sockets = {}
20
+ @unix_paths = []
21
+
22
+ @proto_env = {
23
+ "rack.version".freeze => RACK_VERSION,
24
+ "rack.errors".freeze => events.stderr,
25
+ "rack.multithread".freeze => true,
26
+ "rack.multiprocess".freeze => false,
27
+ "rack.run_once".freeze => false,
28
+ "SCRIPT_NAME".freeze => ENV['SCRIPT_NAME'] || "",
29
+
30
+ # I'd like to set a default CONTENT_TYPE here but some things
31
+ # depend on their not being a default set and inferring
32
+ # it from the content. And so if i set it here, it won't
33
+ # infer properly.
34
+
35
+ "QUERY_STRING".freeze => "",
36
+ SERVER_PROTOCOL => HTTP_11,
37
+ SERVER_SOFTWARE => PUMA_SERVER_STRING,
38
+ GATEWAY_INTERFACE => CGI_VER
39
+ }
40
+
41
+ @envs = {}
42
+ @ios = []
43
+ end
44
+
45
+ attr_reader :listeners, :ios
46
+
47
+ def env(sock)
48
+ @envs.fetch(sock, @proto_env)
49
+ end
50
+
51
+ def close
52
+ @ios.each { |i| i.close }
53
+ @unix_paths.each { |i| File.unlink i }
54
+ end
55
+
56
+ def import_from_env
57
+ remove = []
58
+
59
+ ENV.each do |k,v|
60
+ if k =~ /PUMA_INHERIT_\d+/
61
+ fd, url = v.split(":", 2)
62
+ @inherited_fds[url] = fd.to_i
63
+ remove << k
64
+ elsif k == 'LISTEN_FDS' && ENV['LISTEN_PID'].to_i == $$
65
+ v.to_i.times do |num|
66
+ fd = num + 3
67
+ sock = TCPServer.for_fd(fd)
68
+ begin
69
+ key = [ :unix, Socket.unpack_sockaddr_un(sock.getsockname) ]
70
+ rescue ArgumentError
71
+ port, addr = Socket.unpack_sockaddr_in(sock.getsockname)
72
+ if addr =~ /\:/
73
+ addr = "[#{addr}]"
74
+ end
75
+ key = [ :tcp, addr, port ]
76
+ end
77
+ @activated_sockets[key] = sock
78
+ @events.debug "Registered #{key.join ':'} for activation from LISTEN_FDS"
79
+ end
80
+ remove << k << 'LISTEN_PID'
81
+ end
82
+ end
83
+
84
+ remove.each do |k|
85
+ ENV.delete k
86
+ end
87
+ end
88
+
89
+ def parse(binds, logger)
90
+ binds.each do |str|
91
+ uri = URI.parse str
92
+ case uri.scheme
93
+ when "tcp"
94
+ if fd = @inherited_fds.delete(str)
95
+ io = inherit_tcp_listener uri.host, uri.port, fd
96
+ logger.log "* Inherited #{str}"
97
+ elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
98
+ io = inherit_tcp_listener uri.host, uri.port, sock
99
+ logger.log "* Activated #{str}"
100
+ else
101
+ params = Util.parse_query uri.query
102
+
103
+ opt = params.key?('low_latency')
104
+ bak = params.fetch('backlog', 1024).to_i
105
+
106
+ io = add_tcp_listener uri.host, uri.port, opt, bak
107
+ logger.log "* Listening on #{str}"
108
+ end
109
+
110
+ @listeners << [str, io] if io
111
+ when "unix"
112
+ path = "#{uri.host}#{uri.path}".gsub("%20", " ")
113
+
114
+ if fd = @inherited_fds.delete(str)
115
+ io = inherit_unix_listener path, fd
116
+ logger.log "* Inherited #{str}"
117
+ elsif sock = @activated_sockets.delete([ :unix, path ])
118
+ io = inherit_unix_listener path, sock
119
+ logger.log "* Activated #{str}"
120
+ else
121
+ umask = nil
122
+ mode = nil
123
+ backlog = 1024
124
+
125
+ if uri.query
126
+ params = Util.parse_query uri.query
127
+ if u = params['umask']
128
+ # Use Integer() to respect the 0 prefix as octal
129
+ umask = Integer(u)
130
+ end
131
+
132
+ if u = params['mode']
133
+ mode = Integer('0'+u)
134
+ end
135
+
136
+ if u = params['backlog']
137
+ backlog = Integer(u)
138
+ end
139
+ end
140
+
141
+ io = add_unix_listener path, umask, mode, backlog
142
+ logger.log "* Listening on #{str}"
143
+ end
144
+
145
+ @listeners << [str, io]
146
+ when "ssl"
147
+ params = Util.parse_query uri.query
148
+ require 'puma/minissl'
149
+
150
+ MiniSSL.check
151
+
152
+ ctx = MiniSSL::Context.new
153
+
154
+ if defined?(JRUBY_VERSION)
155
+ unless params['keystore']
156
+ @events.error "Please specify the Java keystore via 'keystore='"
157
+ end
158
+
159
+ ctx.keystore = params['keystore']
160
+
161
+ unless params['keystore-pass']
162
+ @events.error "Please specify the Java keystore password via 'keystore-pass='"
163
+ end
164
+
165
+ ctx.keystore_pass = params['keystore-pass']
166
+ ctx.ssl_cipher_list = params['ssl_cipher_list'] if params['ssl_cipher_list']
167
+ else
168
+ unless params['key']
169
+ @events.error "Please specify the SSL key via 'key='"
170
+ end
171
+
172
+ ctx.key = params['key']
173
+
174
+ unless params['cert']
175
+ @events.error "Please specify the SSL cert via 'cert='"
176
+ end
177
+
178
+ ctx.cert = params['cert']
179
+
180
+ if ['peer', 'force_peer'].include?(params['verify_mode'])
181
+ unless params['ca']
182
+ @events.error "Please specify the SSL ca via 'ca='"
183
+ end
184
+ end
185
+
186
+ ctx.ca = params['ca'] if params['ca']
187
+ ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
188
+ end
189
+
190
+ if params['verify_mode']
191
+ ctx.verify_mode = case params['verify_mode']
192
+ when "peer"
193
+ MiniSSL::VERIFY_PEER
194
+ when "force_peer"
195
+ MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
196
+ when "none"
197
+ MiniSSL::VERIFY_NONE
198
+ else
199
+ @events.error "Please specify a valid verify_mode="
200
+ MiniSSL::VERIFY_NONE
201
+ end
202
+ end
203
+
204
+ if params['verification_flags']
205
+ ctx.verification_flags = Array(params['verification_flags']).
206
+ map { |flag| MiniSSL::VERIFICATION_FLAGS.fetch(flag) }.
207
+ inject { |sum, flag| sum ? sum | flag : flag }
208
+ end
209
+
210
+ if fd = @inherited_fds.delete(str)
211
+ logger.log "* Inherited #{str}"
212
+ io = inherit_ssl_listener fd, ctx
213
+ elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
214
+ io = inherit_ssl_listener sock, ctx
215
+ logger.log "* Activated #{str}"
216
+ else
217
+ io = add_ssl_listener uri.host, uri.port, ctx
218
+ logger.log "* Listening on #{str}"
219
+ end
220
+
221
+ @listeners << [str, io] if io
222
+ else
223
+ logger.error "Invalid URI: #{str}"
224
+ end
225
+ end
226
+
227
+ # If we inherited fds but didn't use them (because of a
228
+ # configuration change), then be sure to close them.
229
+ @inherited_fds.each do |str, fd|
230
+ logger.log "* Closing unused inherited connection: #{str}"
231
+
232
+ begin
233
+ IO.for_fd(fd).close
234
+ rescue SystemCallError
235
+ end
236
+
237
+ # We have to unlink a unix socket path that's not being used
238
+ uri = URI.parse str
239
+ if uri.scheme == "unix"
240
+ path = "#{uri.host}#{uri.path}"
241
+ File.unlink path
242
+ end
243
+ end
244
+
245
+ # Also close any unused activated sockets
246
+ @activated_sockets.each do |key, sock|
247
+ logger.log "* Closing unused activated socket: #{key.join ':'}"
248
+ begin
249
+ sock.close
250
+ rescue SystemCallError
251
+ end
252
+ # We have to unlink a unix socket path that's not being used
253
+ File.unlink key[1] if key[0] == :unix
254
+ end
255
+ end
256
+
257
+ def loopback_addresses
258
+ Socket.ip_address_list.select do |addrinfo|
259
+ addrinfo.ipv6_loopback? || addrinfo.ipv4_loopback?
260
+ end.map { |addrinfo| addrinfo.ip_address }.uniq
261
+ end
262
+
263
+ # Tell the server to listen on host +host+, port +port+.
264
+ # If +optimize_for_latency+ is true (the default) then clients connecting
265
+ # will be optimized for latency over throughput.
266
+ #
267
+ # +backlog+ indicates how many unaccepted connections the kernel should
268
+ # allow to accumulate before returning connection refused.
269
+ #
270
+ def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
271
+ if host == "localhost"
272
+ loopback_addresses.each do |addr|
273
+ add_tcp_listener addr, port, optimize_for_latency, backlog
274
+ end
275
+ return
276
+ end
277
+
278
+ host = host[1..-2] if host and host[0..0] == '['
279
+ s = TCPServer.new(host, port)
280
+ if optimize_for_latency
281
+ s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
282
+ end
283
+ s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
284
+ s.listen backlog
285
+ @connected_port = s.addr[1]
286
+
287
+ @ios << s
288
+ s
289
+ end
290
+
291
+ attr_reader :connected_port
292
+
293
+ def inherit_tcp_listener(host, port, fd)
294
+ if fd.kind_of? TCPServer
295
+ s = fd
296
+ else
297
+ s = TCPServer.for_fd(fd)
298
+ end
299
+
300
+ @ios << s
301
+ s
302
+ end
303
+
304
+ def add_ssl_listener(host, port, ctx,
305
+ optimize_for_latency=true, backlog=1024)
306
+ require 'puma/minissl'
307
+
308
+ MiniSSL.check
309
+
310
+ if host == "localhost"
311
+ loopback_addresses.each do |addr|
312
+ add_ssl_listener addr, port, ctx, optimize_for_latency, backlog
313
+ end
314
+ return
315
+ end
316
+
317
+ host = host[1..-2] if host[0..0] == '['
318
+ s = TCPServer.new(host, port)
319
+ if optimize_for_latency
320
+ s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
321
+ end
322
+ s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
323
+ s.listen backlog
324
+
325
+
326
+ ssl = MiniSSL::Server.new s, ctx
327
+ env = @proto_env.dup
328
+ env[HTTPS_KEY] = HTTPS
329
+ @envs[ssl] = env
330
+
331
+ @ios << ssl
332
+ s
333
+ end
334
+
335
+ def inherit_ssl_listener(fd, ctx)
336
+ require 'puma/minissl'
337
+ MiniSSL.check
338
+
339
+ if fd.kind_of? TCPServer
340
+ s = fd
341
+ else
342
+ s = TCPServer.for_fd(fd)
343
+ end
344
+ ssl = MiniSSL::Server.new(s, ctx)
345
+
346
+ env = @proto_env.dup
347
+ env[HTTPS_KEY] = HTTPS
348
+ @envs[ssl] = env
349
+
350
+ @ios << ssl
351
+
352
+ s
353
+ end
354
+
355
+ # Tell the server to listen on +path+ as a UNIX domain socket.
356
+ #
357
+ def add_unix_listener(path, umask=nil, mode=nil, backlog=1024)
358
+ @unix_paths << path
359
+
360
+ # Let anyone connect by default
361
+ umask ||= 0
362
+
363
+ begin
364
+ old_mask = File.umask(umask)
365
+
366
+ if File.exist? path
367
+ begin
368
+ old = UNIXSocket.new path
369
+ rescue SystemCallError, IOError
370
+ File.unlink path
371
+ else
372
+ old.close
373
+ raise "There is already a server bound to: #{path}"
374
+ end
375
+ end
376
+
377
+ s = UNIXServer.new(path)
378
+ s.listen backlog
379
+ @ios << s
380
+ ensure
381
+ File.umask old_mask
382
+ end
383
+
384
+ if mode
385
+ File.chmod mode, path
386
+ end
387
+
388
+ env = @proto_env.dup
389
+ env[REMOTE_ADDR] = "127.0.0.1"
390
+ @envs[s] = env
391
+
392
+ s
393
+ end
394
+
395
+ def inherit_unix_listener(path, fd)
396
+ @unix_paths << path
397
+
398
+ if fd.kind_of? TCPServer
399
+ s = fd
400
+ else
401
+ s = UNIXServer.for_fd fd
402
+ end
403
+ @ios << s
404
+
405
+ env = @proto_env.dup
406
+ env[REMOTE_ADDR] = "127.0.0.1"
407
+ @envs[s] = env
408
+
409
+ s
410
+ end
411
+
412
+ end
413
+ end