puma-simon 3.7.1

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 (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,222 @@
1
+ require "test_helper"
2
+
3
+ require "puma/events"
4
+
5
+ class SSLEventsHelper < ::Puma::Events
6
+ attr_accessor :addr, :cert, :error
7
+
8
+ def ssl_error(server, peeraddr, peercert, error)
9
+ self.addr = peeraddr
10
+ self.cert = peercert
11
+ self.error = error
12
+ end
13
+ end
14
+
15
+ DISABLE_SSL = begin
16
+ Puma::MiniSSL.check
17
+ rescue
18
+ true
19
+ else
20
+ false
21
+ end
22
+
23
+ class TestPumaServerSSL < Minitest::Test
24
+
25
+ def setup
26
+ return if DISABLE_SSL
27
+ @port = 3212
28
+ @host = "127.0.0.1"
29
+
30
+ @app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
31
+
32
+ @ctx = Puma::MiniSSL::Context.new
33
+
34
+ if Puma.jruby?
35
+ @ctx.keystore = File.expand_path "../../examples/puma/keystore.jks", __FILE__
36
+ @ctx.keystore_pass = 'blahblah'
37
+ else
38
+ @ctx.key = File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__
39
+ @ctx.cert = File.expand_path "../../examples/puma/cert_puma.pem", __FILE__
40
+ end
41
+
42
+ @ctx.verify_mode = Puma::MiniSSL::VERIFY_NONE
43
+
44
+ @events = SSLEventsHelper.new STDOUT, STDERR
45
+ @server = Puma::Server.new @app, @events
46
+ @server.add_ssl_listener @host, @port, @ctx
47
+ @server.run
48
+
49
+ @http = Net::HTTP.new @host, @port
50
+ @http.use_ssl = true
51
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
52
+ end
53
+
54
+ def teardown
55
+ return if DISABLE_SSL
56
+ @server.stop(true)
57
+ end
58
+
59
+ def test_url_scheme_for_https
60
+ return if DISABLE_SSL
61
+
62
+ body = nil
63
+ @http.start do
64
+ req = Net::HTTP::Get.new "/", {}
65
+
66
+ @http.request(req) do |rep|
67
+ body = rep.body
68
+ end
69
+ end
70
+
71
+ assert_equal "https", body
72
+ end
73
+
74
+ def test_very_large_return
75
+ return if DISABLE_SSL
76
+
77
+ giant = "x" * 2056610
78
+
79
+ @server.app = proc do
80
+ [200, {}, [giant]]
81
+ end
82
+
83
+ body = nil
84
+ @http.start do
85
+ req = Net::HTTP::Get.new "/"
86
+ @http.request(req) do |rep|
87
+ body = rep.body
88
+ end
89
+ end
90
+
91
+ assert_equal giant.bytesize, body.bytesize
92
+ end
93
+
94
+ def test_form_submit
95
+ return if DISABLE_SSL
96
+
97
+ body = nil
98
+ @http.start do
99
+ req = Net::HTTP::Post.new '/'
100
+ req.set_form_data('a' => '1', 'b' => '2')
101
+
102
+ @http.request(req) do |rep|
103
+ body = rep.body
104
+ end
105
+
106
+ end
107
+
108
+ assert_equal "https", body
109
+ end
110
+
111
+ def test_ssl_v3_rejection
112
+ return if DISABLE_SSL
113
+ @http.ssl_version='SSLv3'
114
+ assert_raises(OpenSSL::SSL::SSLError) do
115
+ @http.start do
116
+ Net::HTTP::Get.new '/'
117
+ end
118
+ end
119
+ unless Puma.jruby?
120
+ assert_match("wrong version number", @events.error.message) if @events.error
121
+ end
122
+ end
123
+
124
+ end
125
+
126
+ # client-side TLS authentication tests
127
+ class TestPumaServerSSLClient < Minitest::Test
128
+
129
+ def assert_ssl_client_error_match(error, subject=nil, &blk)
130
+ @port = 3212
131
+ @host = "127.0.0.1"
132
+
133
+ @app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
134
+
135
+ @ctx = Puma::MiniSSL::Context.new
136
+ if Puma.jruby?
137
+ @ctx.keystore = File.expand_path "../../examples/puma/client-certs/keystore.jks", __FILE__
138
+ @ctx.keystore_pass = 'blahblah'
139
+ else
140
+ @ctx.key = File.expand_path "../../examples/puma/client-certs/server.key", __FILE__
141
+ @ctx.cert = File.expand_path "../../examples/puma/client-certs/server.crt", __FILE__
142
+ @ctx.ca = File.expand_path "../../examples/puma/client-certs/ca.crt", __FILE__
143
+ end
144
+ @ctx.verify_mode = Puma::MiniSSL::VERIFY_PEER | Puma::MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
145
+
146
+ events = SSLEventsHelper.new STDOUT, STDERR
147
+ @server = Puma::Server.new @app, events
148
+ @server.add_ssl_listener @host, @port, @ctx
149
+ @server.run
150
+
151
+ @http = Net::HTTP.new @host, @port
152
+ @http.use_ssl = true
153
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
154
+
155
+ blk.call(@http)
156
+
157
+ client_error = false
158
+ begin
159
+ @http.start do
160
+ req = Net::HTTP::Get.new "/", {}
161
+ @http.request(req)
162
+ end
163
+ rescue OpenSSL::SSL::SSLError
164
+ client_error = true
165
+ end
166
+
167
+ sleep 0.1
168
+ assert_equal !!error, client_error
169
+ # The JRuby MiniSSL implementation lacks error capturing currently, so we can't inspect the
170
+ # messages here
171
+ unless Puma.jruby?
172
+ assert_match error, events.error.message if error
173
+ assert_equal @host, events.addr if error
174
+ assert_equal subject, events.cert.subject.to_s if subject
175
+ end
176
+ ensure
177
+ @server.stop(true)
178
+ end
179
+
180
+ def test_verify_fail_if_no_client_cert
181
+ return if DISABLE_SSL
182
+
183
+ assert_ssl_client_error_match 'peer did not return a certificate' do |http|
184
+ # nothing
185
+ end
186
+ end
187
+
188
+ def test_verify_fail_if_client_unknown_ca
189
+ return if DISABLE_SSL
190
+
191
+ assert_ssl_client_error_match('self signed certificate in certificate chain', '/DC=net/DC=puma/CN=ca-unknown') do |http|
192
+ key = File.expand_path "../../examples/puma/client-certs/client_unknown.key", __FILE__
193
+ crt = File.expand_path "../../examples/puma/client-certs/client_unknown.crt", __FILE__
194
+ http.key = OpenSSL::PKey::RSA.new File.read(key)
195
+ http.cert = OpenSSL::X509::Certificate.new File.read(crt)
196
+ http.ca_file = File.expand_path "../../examples/puma/client-certs/unknown_ca.crt", __FILE__
197
+ end
198
+ end
199
+
200
+ def test_verify_fail_if_client_expired_cert
201
+ return if DISABLE_SSL
202
+ assert_ssl_client_error_match('certificate has expired', '/DC=net/DC=puma/CN=client-expired') do |http|
203
+ key = File.expand_path "../../examples/puma/client-certs/client_expired.key", __FILE__
204
+ crt = File.expand_path "../../examples/puma/client-certs/client_expired.crt", __FILE__
205
+ http.key = OpenSSL::PKey::RSA.new File.read(key)
206
+ http.cert = OpenSSL::X509::Certificate.new File.read(crt)
207
+ http.ca_file = File.expand_path "../../examples/puma/client-certs/ca.crt", __FILE__
208
+ end
209
+ end
210
+
211
+ def test_verify_client_cert
212
+ return if DISABLE_SSL
213
+ assert_ssl_client_error_match(nil) do |http|
214
+ key = File.expand_path "../../examples/puma/client-certs/client.key", __FILE__
215
+ crt = File.expand_path "../../examples/puma/client-certs/client.crt", __FILE__
216
+ http.key = OpenSSL::PKey::RSA.new File.read(key)
217
+ http.cert = OpenSSL::X509::Certificate.new File.read(crt)
218
+ http.ca_file = File.expand_path "../../examples/puma/client-certs/ca.crt", __FILE__
219
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,57 @@
1
+ require "test_helper"
2
+
3
+ require "rack/handler/puma"
4
+
5
+ class TestPumaUnixSocket < Minitest::Test
6
+ def test_handler
7
+ handler = Rack::Handler.get(:puma)
8
+ assert_equal Rack::Handler::Puma, handler
9
+ handler = Rack::Handler.get('Puma')
10
+ assert_equal Rack::Handler::Puma, handler
11
+ end
12
+ end
13
+
14
+ class TestPathHandler < Minitest::Test
15
+ def app
16
+ Proc.new {|env| @input = env; [200, {}, ["hello world"]]}
17
+ end
18
+
19
+ def setup
20
+ @input = nil
21
+ end
22
+
23
+ def in_handler(app, options = {})
24
+ options[:Port] ||= 0
25
+ options[:Silent] = true
26
+
27
+ @launcher = nil
28
+ thread = Thread.new do
29
+ Rack::Handler::Puma.run(app, options) do |s, p|
30
+ @launcher = s
31
+ end
32
+ end
33
+ thread.abort_on_exception = true
34
+
35
+ # Wait for launcher to boot
36
+ Timeout.timeout(10) do
37
+ until @launcher
38
+ sleep 1
39
+ end
40
+ end
41
+ sleep 1
42
+
43
+ yield @launcher
44
+ ensure
45
+ @launcher.stop if @launcher
46
+ thread.join if thread
47
+ end
48
+
49
+
50
+ def test_handler_boots
51
+ in_handler(app) do |launcher|
52
+ hit(["http://0.0.0.0:#{ launcher.connected_port }/test"])
53
+ assert_equal("/test", @input["PATH_INFO"])
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,138 @@
1
+ require "test_helper"
2
+
3
+ require "rack"
4
+
5
+ class TestRackServer < Minitest::Test
6
+
7
+ class ErrorChecker
8
+ def initialize(app)
9
+ @app = app
10
+ @exception = nil
11
+ @env = nil
12
+ end
13
+
14
+ attr_reader :exception, :env
15
+
16
+ def call(env)
17
+ begin
18
+ @env = env
19
+ return @app.call(env)
20
+ rescue Exception => e
21
+ @exception = e
22
+
23
+ [
24
+ 500,
25
+ { "X-Exception" => e.message, "X-Exception-Class" => e.class.to_s },
26
+ ["Error detected"]
27
+ ]
28
+ end
29
+ end
30
+ end
31
+
32
+ class ServerLint < Rack::Lint
33
+ def call(env)
34
+ assert("No env given") { env }
35
+ check_env env
36
+
37
+ @app.call(env)
38
+ end
39
+ end
40
+
41
+ def setup
42
+ @valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
43
+
44
+ @simple = lambda { |env| [200, { "X-Header" => "Works" }, ["Hello"]] }
45
+ @server = Puma::Server.new @simple
46
+ @server.add_tcp_listener "127.0.0.1", 0
47
+
48
+ @stopped = false
49
+ end
50
+
51
+ def stop
52
+ @server.stop(true)
53
+ @stopped = true
54
+ end
55
+
56
+ def teardown
57
+ @server.stop(true) unless @stopped
58
+ end
59
+
60
+ def test_lint
61
+ @checker = ErrorChecker.new ServerLint.new(@simple)
62
+ @server.app = @checker
63
+
64
+ @server.run
65
+
66
+ hit(["http://127.0.0.1:#{ @server.connected_port }/test"])
67
+
68
+ stop
69
+
70
+ if exc = @checker.exception
71
+ raise exc
72
+ end
73
+ end
74
+
75
+ def test_large_post_body
76
+ @checker = ErrorChecker.new ServerLint.new(@simple)
77
+ @server.app = @checker
78
+
79
+ @server.run
80
+
81
+ big = "x" * (1024 * 16)
82
+
83
+ Net::HTTP.post_form URI.parse("http://127.0.0.1:#{ @server.connected_port }/test"),
84
+ { "big" => big }
85
+
86
+ stop
87
+
88
+ if exc = @checker.exception
89
+ raise exc
90
+ end
91
+ end
92
+
93
+ def test_path_info
94
+ input = nil
95
+ @server.app = lambda { |env| input = env; @simple.call(env) }
96
+ @server.run
97
+
98
+ hit(["http://127.0.0.1:#{ @server.connected_port }/test/a/b/c"])
99
+
100
+ stop
101
+
102
+ assert_equal "/test/a/b/c", input['PATH_INFO']
103
+ end
104
+
105
+ def test_after_reply
106
+ closed = false
107
+
108
+ @server.app = lambda do |env|
109
+ env['rack.after_reply'] << lambda { closed = true }
110
+ @simple.call(env)
111
+ end
112
+
113
+ @server.run
114
+
115
+ hit(["http://127.0.0.1:#{ @server.connected_port }/test"])
116
+
117
+ stop
118
+
119
+ assert_equal true, closed
120
+ end
121
+
122
+ def test_common_logger
123
+ log = StringIO.new
124
+
125
+ logger = Rack::CommonLogger.new(@simple, log)
126
+
127
+ @server.app = logger
128
+
129
+ @server.run
130
+
131
+ hit(["http://127.0.0.1:#{ @server.connected_port }/test"])
132
+
133
+ stop
134
+
135
+ assert_match %r!GET /test HTTP/1\.1!, log.string
136
+ end
137
+
138
+ end
@@ -0,0 +1,39 @@
1
+ require "test_helper"
2
+
3
+ require "puma/events"
4
+ require "puma/tcp_logger"
5
+
6
+ class TestTCPLogger < Minitest::Test
7
+
8
+ def setup
9
+ @events = Puma::Events.new STDOUT, STDERR
10
+ @server = Puma::Server.new nil, @events
11
+
12
+ @server.app = proc { |env, socket|}
13
+ @server.tcp_mode!
14
+
15
+ @socket = nil
16
+ end
17
+
18
+ def test_events
19
+ # in lib/puma/launcher.rb:85
20
+ # Puma::Events is default tcp_logger for cluster mode
21
+ logger = Puma::Events.new(STDOUT, STDERR)
22
+ out, err = capture_subprocess_io do
23
+ Puma::TCPLogger.new(logger, @server.app).call({}, @socket)
24
+ end
25
+ assert_match(/connected/, out)
26
+ assert_equal('', err)
27
+ end
28
+
29
+ def test_io
30
+ # in lib/puma/configuration.rb:184
31
+ # STDOUT is default tcp_logger for single mode
32
+ logger = STDOUT
33
+ out, err = capture_subprocess_io do
34
+ Puma::TCPLogger.new(logger, @server.app).call({}, @socket)
35
+ end
36
+ assert_match(/connected/, out)
37
+ assert_equal('', err)
38
+ end
39
+ end