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,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