puma-simon 3.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/.github/issue_template.md +20 -0
  3. data/.gitignore +18 -0
  4. data/.hoeignore +12 -0
  5. data/.travis.yml +29 -0
  6. data/DEPLOYMENT.md +91 -0
  7. data/Gemfile +12 -0
  8. data/History.md +1254 -0
  9. data/LICENSE +26 -0
  10. data/Manifest.txt +78 -0
  11. data/README.md +353 -0
  12. data/Rakefile +158 -0
  13. data/Release.md +9 -0
  14. data/bin/puma +10 -0
  15. data/bin/puma-wild +31 -0
  16. data/bin/pumactl +12 -0
  17. data/docs/nginx.md +80 -0
  18. data/docs/signals.md +43 -0
  19. data/docs/systemd.md +197 -0
  20. data/examples/CA/cacert.pem +23 -0
  21. data/examples/CA/newcerts/cert_1.pem +19 -0
  22. data/examples/CA/newcerts/cert_2.pem +19 -0
  23. data/examples/CA/private/cakeypair.pem +30 -0
  24. data/examples/CA/serial +1 -0
  25. data/examples/config.rb +200 -0
  26. data/examples/plugins/redis_stop_puma.rb +46 -0
  27. data/examples/puma/cert_puma.pem +19 -0
  28. data/examples/puma/client-certs/ca.crt +19 -0
  29. data/examples/puma/client-certs/ca.key +27 -0
  30. data/examples/puma/client-certs/client.crt +19 -0
  31. data/examples/puma/client-certs/client.key +27 -0
  32. data/examples/puma/client-certs/client_expired.crt +19 -0
  33. data/examples/puma/client-certs/client_expired.key +27 -0
  34. data/examples/puma/client-certs/client_unknown.crt +19 -0
  35. data/examples/puma/client-certs/client_unknown.key +27 -0
  36. data/examples/puma/client-certs/generate.rb +78 -0
  37. data/examples/puma/client-certs/keystore.jks +0 -0
  38. data/examples/puma/client-certs/server.crt +19 -0
  39. data/examples/puma/client-certs/server.key +27 -0
  40. data/examples/puma/client-certs/server.p12 +0 -0
  41. data/examples/puma/client-certs/unknown_ca.crt +19 -0
  42. data/examples/puma/client-certs/unknown_ca.key +27 -0
  43. data/examples/puma/csr_puma.pem +11 -0
  44. data/examples/puma/keystore.jks +0 -0
  45. data/examples/puma/puma_keypair.pem +15 -0
  46. data/examples/qc_config.rb +13 -0
  47. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  48. data/ext/puma_http11/ext_help.h +15 -0
  49. data/ext/puma_http11/extconf.rb +15 -0
  50. data/ext/puma_http11/http11_parser.c +1069 -0
  51. data/ext/puma_http11/http11_parser.h +65 -0
  52. data/ext/puma_http11/http11_parser.java.rl +161 -0
  53. data/ext/puma_http11/http11_parser.rl +147 -0
  54. data/ext/puma_http11/http11_parser_common.rl +54 -0
  55. data/ext/puma_http11/io_buffer.c +155 -0
  56. data/ext/puma_http11/mini_ssl.c +457 -0
  57. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  58. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +473 -0
  59. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +339 -0
  60. data/ext/puma_http11/puma_http11.c +500 -0
  61. data/gemfiles/2.1-Gemfile +12 -0
  62. data/lib/puma.rb +15 -0
  63. data/lib/puma/accept_nonblock.rb +23 -0
  64. data/lib/puma/app/status.rb +66 -0
  65. data/lib/puma/binder.rb +402 -0
  66. data/lib/puma/cli.rb +220 -0
  67. data/lib/puma/client.rb +434 -0
  68. data/lib/puma/cluster.rb +510 -0
  69. data/lib/puma/commonlogger.rb +106 -0
  70. data/lib/puma/compat.rb +14 -0
  71. data/lib/puma/configuration.rb +364 -0
  72. data/lib/puma/const.rb +224 -0
  73. data/lib/puma/control_cli.rb +259 -0
  74. data/lib/puma/convenient.rb +23 -0
  75. data/lib/puma/daemon_ext.rb +31 -0
  76. data/lib/puma/delegation.rb +11 -0
  77. data/lib/puma/detect.rb +13 -0
  78. data/lib/puma/dsl.rb +486 -0
  79. data/lib/puma/events.rb +152 -0
  80. data/lib/puma/io_buffer.rb +7 -0
  81. data/lib/puma/java_io_buffer.rb +45 -0
  82. data/lib/puma/jruby_restart.rb +83 -0
  83. data/lib/puma/launcher.rb +410 -0
  84. data/lib/puma/minissl.rb +221 -0
  85. data/lib/puma/null_io.rb +42 -0
  86. data/lib/puma/plugin.rb +115 -0
  87. data/lib/puma/plugin/tmp_restart.rb +35 -0
  88. data/lib/puma/rack/backports/uri/common_193.rb +33 -0
  89. data/lib/puma/rack/builder.rb +298 -0
  90. data/lib/puma/rack/urlmap.rb +91 -0
  91. data/lib/puma/rack_default.rb +7 -0
  92. data/lib/puma/reactor.rb +210 -0
  93. data/lib/puma/runner.rb +171 -0
  94. data/lib/puma/server.rb +949 -0
  95. data/lib/puma/single.rb +112 -0
  96. data/lib/puma/state_file.rb +29 -0
  97. data/lib/puma/tcp_logger.rb +39 -0
  98. data/lib/puma/thread_pool.rb +297 -0
  99. data/lib/puma/util.rb +128 -0
  100. data/lib/rack/handler/puma.rb +78 -0
  101. data/puma.gemspec +52 -0
  102. data/test/ab_rs.rb +22 -0
  103. data/test/config.rb +2 -0
  104. data/test/config/app.rb +9 -0
  105. data/test/config/plugin.rb +1 -0
  106. data/test/config/settings.rb +2 -0
  107. data/test/config/state_file_testing_config.rb +14 -0
  108. data/test/hello-bind.ru +2 -0
  109. data/test/hello-delay.ru +3 -0
  110. data/test/hello-map.ru +3 -0
  111. data/test/hello-post.ru +4 -0
  112. data/test/hello-stuck.ru +1 -0
  113. data/test/hello-tcp.ru +5 -0
  114. data/test/hello.ru +1 -0
  115. data/test/hijack.ru +6 -0
  116. data/test/hijack2.ru +5 -0
  117. data/test/lobster.ru +4 -0
  118. data/test/shell/run.sh +24 -0
  119. data/test/shell/t1.rb +19 -0
  120. data/test/shell/t1_conf.rb +3 -0
  121. data/test/shell/t2.rb +17 -0
  122. data/test/shell/t2_conf.rb +6 -0
  123. data/test/shell/t3.rb +25 -0
  124. data/test/shell/t3_conf.rb +5 -0
  125. data/test/slow.ru +4 -0
  126. data/test/ssl_config.rb +4 -0
  127. data/test/test_app_status.rb +93 -0
  128. data/test/test_binder.rb +31 -0
  129. data/test/test_cli.rb +209 -0
  130. data/test/test_config.rb +95 -0
  131. data/test/test_events.rb +161 -0
  132. data/test/test_helper.rb +50 -0
  133. data/test/test_http10.rb +27 -0
  134. data/test/test_http11.rb +186 -0
  135. data/test/test_integration.rb +247 -0
  136. data/test/test_iobuffer.rb +39 -0
  137. data/test/test_minissl.rb +29 -0
  138. data/test/test_null_io.rb +49 -0
  139. data/test/test_persistent.rb +245 -0
  140. data/test/test_puma_server.rb +626 -0
  141. data/test/test_puma_server_ssl.rb +222 -0
  142. data/test/test_rack_handler.rb +57 -0
  143. data/test/test_rack_server.rb +138 -0
  144. data/test/test_tcp_logger.rb +39 -0
  145. data/test/test_tcp_rack.rb +36 -0
  146. data/test/test_thread_pool.rb +250 -0
  147. data/test/test_unix_socket.rb +35 -0
  148. data/test/test_web_server.rb +88 -0
  149. data/tools/jungle/README.md +9 -0
  150. data/tools/jungle/init.d/README.md +59 -0
  151. data/tools/jungle/init.d/puma +421 -0
  152. data/tools/jungle/init.d/run-puma +18 -0
  153. data/tools/jungle/upstart/README.md +61 -0
  154. data/tools/jungle/upstart/puma-manager.conf +31 -0
  155. data/tools/jungle/upstart/puma.conf +69 -0
  156. data/tools/trickletest.rb +45 -0
  157. metadata +297 -0
@@ -0,0 +1,128 @@
1
+ major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i }
2
+
3
+ if major == 1 && minor == 9 && patch == 3 && RUBY_PATCHLEVEL < 125
4
+ require 'puma/rack/backports/uri/common_193'
5
+ else
6
+ require 'uri/common'
7
+ end
8
+
9
+ module Puma
10
+ module Util
11
+ module_function
12
+
13
+ def pipe
14
+ IO.pipe
15
+ end
16
+
17
+ # Unescapes a URI escaped string with +encoding+. +encoding+ will be the
18
+ # target encoding of the string returned, and it defaults to UTF-8
19
+ if defined?(::Encoding)
20
+ def unescape(s, encoding = Encoding::UTF_8)
21
+ URI.decode_www_form_component(s, encoding)
22
+ end
23
+ else
24
+ def unescape(s, encoding = nil)
25
+ URI.decode_www_form_component(s, encoding)
26
+ end
27
+ end
28
+ module_function :unescape
29
+
30
+ DEFAULT_SEP = /[&;] */n
31
+
32
+ # Stolen from Mongrel, with some small modifications:
33
+ # Parses a query string by breaking it up at the '&'
34
+ # and ';' characters. You can also use this to parse
35
+ # cookies by changing the characters used in the second
36
+ # parameter (which defaults to '&;').
37
+ def parse_query(qs, d = nil, &unescaper)
38
+ unescaper ||= method(:unescape)
39
+
40
+ params = {}
41
+
42
+ (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
43
+ next if p.empty?
44
+ k, v = p.split('=', 2).map(&unescaper)
45
+
46
+ if cur = params[k]
47
+ if cur.class == Array
48
+ params[k] << v
49
+ else
50
+ params[k] = [cur, v]
51
+ end
52
+ else
53
+ params[k] = v
54
+ end
55
+ end
56
+
57
+ return params
58
+ end
59
+
60
+ # A case-insensitive Hash that preserves the original case of a
61
+ # header when set.
62
+ class HeaderHash < Hash
63
+ def self.new(hash={})
64
+ HeaderHash === hash ? hash : super(hash)
65
+ end
66
+
67
+ def initialize(hash={})
68
+ super()
69
+ @names = {}
70
+ hash.each { |k, v| self[k] = v }
71
+ end
72
+
73
+ def each
74
+ super do |k, v|
75
+ yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)
76
+ end
77
+ end
78
+
79
+ def to_hash
80
+ hash = {}
81
+ each { |k,v| hash[k] = v }
82
+ hash
83
+ end
84
+
85
+ def [](k)
86
+ super(k) || super(@names[k.downcase])
87
+ end
88
+
89
+ def []=(k, v)
90
+ canonical = k.downcase
91
+ delete k if @names[canonical] && @names[canonical] != k # .delete is expensive, don't invoke it unless necessary
92
+ @names[k] = @names[canonical] = k
93
+ super k, v
94
+ end
95
+
96
+ def delete(k)
97
+ canonical = k.downcase
98
+ result = super @names.delete(canonical)
99
+ @names.delete_if { |name,| name.downcase == canonical }
100
+ result
101
+ end
102
+
103
+ def include?(k)
104
+ @names.include?(k) || @names.include?(k.downcase)
105
+ end
106
+
107
+ alias_method :has_key?, :include?
108
+ alias_method :member?, :include?
109
+ alias_method :key?, :include?
110
+
111
+ def merge!(other)
112
+ other.each { |k, v| self[k] = v }
113
+ self
114
+ end
115
+
116
+ def merge(other)
117
+ hash = dup
118
+ hash.merge! other
119
+ end
120
+
121
+ def replace(other)
122
+ clear
123
+ other.each { |k, v| self[k] = v }
124
+ self
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,78 @@
1
+ require 'rack/handler'
2
+
3
+ module Rack
4
+ module Handler
5
+ module Puma
6
+ DEFAULT_OPTIONS = {
7
+ :Verbose => false,
8
+ :Silent => false
9
+ }
10
+
11
+ def self.run(app, options = {})
12
+ require 'puma/configuration'
13
+ require 'puma/events'
14
+ require 'puma/launcher'
15
+
16
+ options = DEFAULT_OPTIONS.merge(options)
17
+
18
+ conf = ::Puma::Configuration.new(options) do |c|
19
+ c.quiet
20
+
21
+ if options.delete(:Verbose)
22
+ app = Rack::CommonLogger.new(app, STDOUT)
23
+ end
24
+
25
+ if options[:environment]
26
+ c.environment options[:environment]
27
+ end
28
+
29
+ if options[:Threads]
30
+ min, max = options.delete(:Threads).split(':', 2)
31
+ c.threads min, max
32
+ end
33
+
34
+ host = options[:Host]
35
+
36
+ if host && (host[0,1] == '.' || host[0,1] == '/')
37
+ c.bind "unix://#{host}"
38
+ elsif host && host =~ /^ssl:\/\//
39
+ uri = URI.parse(host)
40
+ uri.port ||= options[:Port] || ::Puma::Configuration::DefaultTCPPort
41
+ c.bind uri.to_s
42
+ else
43
+ host ||= ::Puma::Configuration::DefaultTCPHost
44
+ port = options[:Port] || ::Puma::Configuration::DefaultTCPPort
45
+
46
+ c.port port, host
47
+ end
48
+
49
+ c.app app
50
+ end
51
+
52
+ events = options.delete(:Silent) ? ::Puma::Events.strings : ::Puma::Events.stdio
53
+
54
+ launcher = ::Puma::Launcher.new(conf, :events => events)
55
+
56
+ yield launcher if block_given?
57
+ begin
58
+ launcher.run
59
+ rescue Interrupt
60
+ puts "* Gracefully stopping, waiting for requests to finish"
61
+ launcher.stop
62
+ puts "* Goodbye!"
63
+ end
64
+ end
65
+
66
+ def self.valid_options
67
+ {
68
+ "Host=HOST" => "Hostname to listen on (default: localhost)",
69
+ "Port=PORT" => "Port to listen on (default: 8080)",
70
+ "Threads=MIN:MAX" => "min:max threads to use (default 0:16)",
71
+ "Verbose" => "Don't report each request (default: false)"
72
+ }
73
+ end
74
+ end
75
+
76
+ register :puma, Puma
77
+ end
78
+ end
@@ -0,0 +1,52 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # This is only used when puma is a git dep from Bundler, so it's a little
4
+ # weird.
5
+
6
+ d = File.read(File.expand_path("../lib/puma/const.rb", __FILE__))
7
+ if d =~ /VERSION = "(\d+\.\d+\.\d+)"/
8
+ version = $1
9
+ else
10
+ version = "0.0.1"
11
+ end
12
+
13
+ Gem::Specification.new do |s|
14
+ s.name = "puma-simon"
15
+ s.version = version
16
+
17
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
18
+ s.authors = ["Evan Phoenix"]
19
+ s.date = `git log --pretty="%ai" -n 1`.split(" ").first
20
+ s.description = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications. Puma is intended for use in both development and production environments. It's great for highly concurrent Ruby implementations such as Rubinius and JRuby as well as as providing process worker support to support CRuby well."
21
+ s.email = ["evan@phx.io"]
22
+ s.executables = ["puma", "pumactl"]
23
+ s.extensions = ["ext/puma_http11/extconf.rb"]
24
+ s.files = `git ls-files`.split($/)
25
+ s.homepage = "http://puma.io"
26
+ s.license = "BSD-3-Clause"
27
+ s.rdoc_options = ["--main", "README.md"]
28
+ s.require_paths = ["lib"]
29
+ s.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
30
+ s.rubyforge_project = "puma"
31
+ s.rubygems_version = "1.8.25"
32
+ s.summary = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications"
33
+ s.test_files = s.files.grep(/^test/)
34
+
35
+ if s.respond_to? :specification_version then
36
+ s.specification_version = 3
37
+
38
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
39
+ s.add_development_dependency(%q<rdoc>, ["~> 4.0"])
40
+ s.add_development_dependency(%q<rake-compiler>, ["~> 0.8.0"])
41
+ s.add_development_dependency(%q<hoe>, ["~> 3.6"])
42
+ else
43
+ s.add_dependency(%q<rdoc>, ["~> 4.0"])
44
+ s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
45
+ s.add_dependency(%q<hoe>, ["~> 3.6"])
46
+ end
47
+ else
48
+ s.add_dependency(%q<rdoc>, ["~> 4.0"])
49
+ s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
50
+ s.add_dependency(%q<hoe>, ["~> 3.6"])
51
+ end
52
+ end
@@ -0,0 +1,22 @@
1
+ url = ARGV.shift
2
+ count = (ARGV.shift || 1000).to_i
3
+
4
+ STDOUT.sync = true
5
+
6
+ 1.upto(5) do |i|
7
+ print "#{i}: "
8
+ str = `ab -n #{count} -c #{i} #{url} 2>/dev/null`
9
+
10
+ rs = /Requests per second:\s+([\d.]+)\s/.match(str)
11
+ puts rs[1]
12
+ end
13
+
14
+ puts "Keep Alive:"
15
+
16
+ 1.upto(5) do |i|
17
+ print "#{i}: "
18
+ str = `ab -n #{count} -k -c #{i} #{url} 2>/dev/null`
19
+
20
+ rs = /Requests per second:\s+([\d.]+)\s/.match(str)
21
+ puts rs[1]
22
+ end
@@ -0,0 +1,2 @@
1
+ pidfile "/tmp/jruby.pid"
2
+ switch_user "daemon", "daemon"
@@ -0,0 +1,9 @@
1
+ port ENV['PORT'] if ENV['PORT']
2
+
3
+ app do |env|
4
+ [200, {}, ["embedded app"]]
5
+ end
6
+
7
+ lowlevel_error_handler do |err|
8
+ [200, {}, ["error page"]]
9
+ end
@@ -0,0 +1 @@
1
+ plugin :tmp_restart
@@ -0,0 +1,2 @@
1
+ port 3000
2
+ threads 3, 5
@@ -0,0 +1,14 @@
1
+ pidfile "t3-pid"
2
+ workers 3
3
+ on_worker_boot do |index|
4
+ File.open("t3-worker-#{index}-pid", "w") { |f| f.puts Process.pid }
5
+ end
6
+
7
+ before_fork { 1 }
8
+ on_worker_shutdown { 1 }
9
+ on_worker_boot { 1 }
10
+ on_worker_fork { 1 }
11
+ on_restart { 1 }
12
+ after_worker_boot { 1 }
13
+ lowlevel_error_handler { 1 }
14
+
@@ -0,0 +1,2 @@
1
+ #\ -O bind=tcp://127.0.0.1:9292
2
+ run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello World"]] }
@@ -0,0 +1,3 @@
1
+ sleep 10
2
+
3
+ run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello World"]] }
@@ -0,0 +1,3 @@
1
+ map "/foo" do
2
+ run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello World"]] }
3
+ end
@@ -0,0 +1,4 @@
1
+ run lambda { |env|
2
+ p :body => env['rack.input'].read
3
+ [200, {"Content-Type" => "text/plain"}, ["Hello World"]]
4
+ }
@@ -0,0 +1 @@
1
+ run lambda { |env| sleep 60; [200, {"Content-Type" => "text/plain"}, ["Hello World"]] }
@@ -0,0 +1,5 @@
1
+ run lambda { |env, socket|
2
+ p :here
3
+ socket.puts "Sockets for the low, low price of free!"
4
+ socket.close
5
+ }
@@ -0,0 +1 @@
1
+ run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello World"]] }
@@ -0,0 +1,6 @@
1
+
2
+ run lambda { |env|
3
+ io = env['rack.hijack'].call
4
+ io.puts "HTTP/1.1 200\r\n\r\nBLAH"
5
+ [-1, {}, []]
6
+ }
@@ -0,0 +1,5 @@
1
+ run lambda { |env|
2
+ body = lambda { |io| io.puts "BLAH\n"; io.close }
3
+
4
+ [200, { 'rack.hijack' => body }, []]
5
+ }
@@ -0,0 +1,4 @@
1
+ require 'rack/lobster'
2
+
3
+ use Rack::ShowExceptions
4
+ run Rack::Lobster.new
@@ -0,0 +1,24 @@
1
+ ERROR=0
2
+
3
+ if ruby -rubygems t1.rb > /dev/null 2>&1; then
4
+ echo "t1 OK"
5
+ else
6
+ echo "t1 FAIL"
7
+ ERROR=1
8
+ fi
9
+
10
+ if ruby -rubygems t2.rb > /dev/null 2>&1; then
11
+ echo "t2 OK"
12
+ else
13
+ echo "t2 FAIL"
14
+ ERROR=2
15
+ fi
16
+
17
+ if ruby -rubygems t3.rb > /dev/null 2>&1; then
18
+ echo "t3 OK"
19
+ else
20
+ echo "t3 FAIL"
21
+ ERROR=3
22
+ fi
23
+
24
+ exit $ERROR
@@ -0,0 +1,19 @@
1
+ system "ruby -rubygems -I../../lib ../../bin/puma -p 10102 -C t1_conf.rb ../hello.ru &"
2
+ sleep 5
3
+ system "curl http://localhost:10102/"
4
+
5
+ system "kill `cat t1-pid`"
6
+
7
+ sleep 1
8
+
9
+ log = File.read("t1-stdout")
10
+
11
+ File.unlink "t1-stdout" if File.file? "t1-stdout"
12
+ File.unlink "t1-pid" if File.file? "t1-pid"
13
+
14
+ if log =~ %r!GET / HTTP/1\.1!
15
+ exit 0
16
+ else
17
+ exit 1
18
+ end
19
+
@@ -0,0 +1,3 @@
1
+ log_requests
2
+ stdout_redirect "t1-stdout"
3
+ pidfile "t1-pid"
@@ -0,0 +1,17 @@
1
+ system "ruby -rubygems -I../../lib ../../bin/pumactl -F t2_conf.rb start"
2
+ sleep 5
3
+ system "curl http://localhost:10103/"
4
+
5
+ system "ruby -rubygems -I../../lib ../../bin/pumactl -F t2_conf.rb stop"
6
+
7
+ sleep 1
8
+
9
+ log = File.read("t2-stdout")
10
+
11
+ File.unlink "t2-stdout" if File.file? "t2-stdout"
12
+
13
+ if log =~ %r(GET / HTTP/1\.1) && !File.file?("t2-pid")
14
+ exit 0
15
+ else
16
+ exit 1
17
+ end
@@ -0,0 +1,6 @@
1
+ log_requests
2
+ stdout_redirect "t2-stdout"
3
+ pidfile "t2-pid"
4
+ bind "tcp://0.0.0.0:10103"
5
+ rackup File.expand_path('../hello.ru', File.dirname(__FILE__))
6
+ daemonize