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,36 @@
1
+ require "test_helper"
2
+
3
+ require "puma/events"
4
+
5
+ class TestTCPRack < Minitest::Test
6
+
7
+ def setup
8
+ @port = 3212
9
+ @host = "127.0.0.1"
10
+
11
+ @events = Puma::Events.new STDOUT, STDERR
12
+ @server = Puma::Server.new nil, @events
13
+ end
14
+
15
+ def teardown
16
+ @server.stop(true)
17
+ end
18
+
19
+ def test_passes_the_socket
20
+ @server.tcp_mode!
21
+
22
+ body = "We sell hats for a discount!\n"
23
+
24
+ @server.app = proc do |env, socket|
25
+ socket << body
26
+ socket.close
27
+ end
28
+
29
+ @server.add_tcp_listener @host, @port
30
+ @server.run
31
+
32
+ sock = TCPSocket.new @host, @port
33
+
34
+ assert_equal body, sock.read
35
+ end
36
+ end
@@ -0,0 +1,250 @@
1
+ require "test_helper"
2
+
3
+ require "puma/thread_pool"
4
+
5
+ class TestThreadPool < Minitest::Test
6
+
7
+ def teardown
8
+ @pool.shutdown if @pool
9
+ end
10
+
11
+ def new_pool(min, max, &block)
12
+ block = proc { } unless block
13
+ @pool = Puma::ThreadPool.new(min, max, &block)
14
+ end
15
+
16
+ def pause
17
+ sleep 0.2
18
+ end
19
+
20
+ def test_append_spawns
21
+ saw = []
22
+ thread_name = nil
23
+
24
+ pool = new_pool(0, 1) do |work|
25
+ saw << work
26
+ thread_name = Thread.current.name if Thread.current.respond_to?(:name)
27
+ end
28
+
29
+ pool << 1
30
+
31
+ pause
32
+
33
+ assert_equal [1], saw
34
+ assert_equal 1, pool.spawned
35
+ # Thread name is new in Ruby 2.3
36
+ assert_equal('puma 001', thread_name) if Thread.current.respond_to?(:name)
37
+ end
38
+
39
+ def test_converts_pool_sizes
40
+ pool = new_pool('0', '1')
41
+
42
+ assert_equal 0, pool.spawned
43
+
44
+ pool << 1
45
+
46
+ assert_equal 1, pool.spawned
47
+ end
48
+
49
+ def test_append_queues_on_max
50
+ finish = false
51
+ pool = new_pool(0, 1) { Thread.pass until finish }
52
+
53
+ pool << 1
54
+ pool << 2
55
+ pool << 3
56
+
57
+ pause
58
+
59
+ assert_equal 2, pool.backlog
60
+
61
+ finish = true
62
+ end
63
+
64
+ def test_trim
65
+ pool = new_pool(0, 1)
66
+
67
+ pool << 1
68
+
69
+ pause
70
+
71
+ assert_equal 1, pool.spawned
72
+ pool.trim
73
+
74
+ pause
75
+ assert_equal 0, pool.spawned
76
+ end
77
+
78
+ def test_trim_leaves_min
79
+ finish = false
80
+ pool = new_pool(1, 2) { Thread.pass until finish }
81
+
82
+ pool << 1
83
+ pool << 2
84
+
85
+ finish = true
86
+
87
+ pause
88
+
89
+ assert_equal 2, pool.spawned
90
+ pool.trim
91
+ pause
92
+
93
+ assert_equal 1, pool.spawned
94
+ pool.trim
95
+ pause
96
+
97
+ assert_equal 1, pool.spawned
98
+
99
+ end
100
+
101
+ def test_force_trim_doesnt_overtrim
102
+ finish = false
103
+ pool = new_pool(1, 2) { Thread.pass until finish }
104
+
105
+ pool << 1
106
+ pool << 2
107
+
108
+ assert_equal 2, pool.spawned
109
+ pool.trim true
110
+ pool.trim true
111
+
112
+ finish = true
113
+
114
+ pause
115
+
116
+ assert_equal 1, pool.spawned
117
+ end
118
+
119
+ def test_trim_is_ignored_if_no_waiting_threads
120
+ finish = false
121
+ pool = new_pool(1, 2) { Thread.pass until finish }
122
+
123
+ pool << 1
124
+ pool << 2
125
+
126
+ assert_equal 2, pool.spawned
127
+ pool.trim
128
+ pool.trim
129
+
130
+ assert_equal 0, pool.trim_requested
131
+
132
+ finish = true
133
+
134
+ pause
135
+ end
136
+
137
+ def test_autotrim
138
+ finish = false
139
+ pool = new_pool(1, 2) { Thread.pass until finish }
140
+
141
+ pool << 1
142
+ pool << 2
143
+
144
+ assert_equal 2, pool.spawned
145
+
146
+ finish = true
147
+
148
+ pause
149
+
150
+ assert_equal 2, pool.spawned
151
+
152
+ pool.auto_trim! 1
153
+
154
+ sleep 1
155
+
156
+ pause
157
+
158
+ assert_equal 1, pool.spawned
159
+ end
160
+
161
+ def test_cleanliness
162
+ values = []
163
+ n = 100
164
+ mutex = Mutex.new
165
+
166
+ finished = false
167
+
168
+ pool = new_pool(1,1) {
169
+ mutex.synchronize { values.push Thread.current[:foo] }
170
+ Thread.current[:foo] = :hai
171
+ Thread.pass until finished
172
+ }
173
+
174
+ pool.clean_thread_locals = true
175
+
176
+ n.times { pool << 1 }
177
+
178
+ finished = true
179
+
180
+ pause
181
+
182
+ assert_equal n, values.length
183
+
184
+ assert_equal [], values.compact
185
+ end
186
+
187
+ def test_reap_only_dead_threads
188
+ pool = new_pool(2,2) { Thread.current.kill }
189
+
190
+ assert_equal 2, pool.spawned
191
+
192
+ pool << 1
193
+
194
+ pause
195
+
196
+ assert_equal 2, pool.spawned
197
+
198
+ pool.reap
199
+
200
+ assert_equal 1, pool.spawned
201
+
202
+ pool << 2
203
+
204
+ pause
205
+
206
+ assert_equal 1, pool.spawned
207
+
208
+ pool.reap
209
+
210
+ assert_equal 0, pool.spawned
211
+ end
212
+
213
+ def test_auto_reap_dead_threads
214
+ pool = new_pool(2,2) { Thread.current.kill }
215
+
216
+ assert_equal 2, pool.spawned
217
+
218
+ pool << 1
219
+ pool << 2
220
+
221
+ pause
222
+
223
+ assert_equal 2, pool.spawned
224
+
225
+ pool.auto_reap! 1
226
+
227
+ sleep 1
228
+
229
+ pause
230
+
231
+ assert_equal 0, pool.spawned
232
+ end
233
+
234
+ def test_force_shutdown_immediately
235
+ pool = new_pool(1, 1) {
236
+ begin
237
+ sleep 1
238
+ rescue Puma::ThreadPool::ForceShutdown
239
+ end
240
+ }
241
+
242
+ pool << 1
243
+
244
+ sleep 0.1
245
+
246
+ pool.shutdown(0)
247
+
248
+ assert_equal 0, pool.spawned
249
+ end
250
+ end
@@ -0,0 +1,35 @@
1
+ require "test_helper"
2
+
3
+ # UNIX sockets are not recommended on JRuby
4
+ # (or Windows)
5
+ unless Puma.jruby? || Puma.windows?
6
+ class TestPumaUnixSocket < Minitest::Test
7
+
8
+ App = lambda { |env| [200, {}, ["Works"]] }
9
+
10
+ Path = "test/puma.sock"
11
+
12
+ def setup
13
+ @server = Puma::Server.new App
14
+ @server.add_unix_listener Path
15
+ @server.run
16
+ end
17
+
18
+ def teardown
19
+ @server.stop(true)
20
+ File.unlink Path if File.exist? Path
21
+ end
22
+
23
+ def test_server
24
+ sock = UNIXSocket.new Path
25
+
26
+ sock << "GET / HTTP/1.0\r\nHost: blah.com\r\n\r\n"
27
+
28
+ expected = "HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\nWorks"
29
+
30
+ assert_equal expected, sock.read(expected.size)
31
+
32
+ sock.close
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,88 @@
1
+ # Copyright (c) 2011 Evan Phoenix
2
+ # Copyright (c) 2005 Zed A. Shaw
3
+
4
+ require "test_helper"
5
+
6
+ require "puma/server"
7
+
8
+ class TestHandler
9
+ attr_reader :ran_test
10
+
11
+ def call(env)
12
+ @ran_test = true
13
+
14
+ [200, {"Content-Type" => "text/plain"}, ["hello!"]]
15
+ end
16
+ end
17
+
18
+ class WebServerTest < Minitest::Test
19
+
20
+ def setup
21
+ @valid_request = "GET / HTTP/1.1\r\nHost: www.zedshaw.com\r\nContent-Type: text/plain\r\n\r\n"
22
+
23
+ @tester = TestHandler.new
24
+
25
+ @server = Puma::Server.new @tester, Puma::Events.strings
26
+ @server.add_tcp_listener "127.0.0.1", 0
27
+
28
+ @server.run
29
+ end
30
+
31
+ def teardown
32
+ @server.stop(true)
33
+ end
34
+
35
+ def test_simple_server
36
+ hit(["http://127.0.0.1:#{ @server.connected_port }/test"])
37
+ assert @tester.ran_test, "Handler didn't really run"
38
+ end
39
+
40
+
41
+ def do_test(string, chunk, close_after=nil, shutdown_delay=0)
42
+ # Do not use instance variables here, because it needs to be thread safe
43
+ socket = TCPSocket.new("127.0.0.1", @server.connected_port);
44
+ request = StringIO.new(string)
45
+ chunks_out = 0
46
+
47
+ while data = request.read(chunk)
48
+ chunks_out += socket.write(data)
49
+ socket.flush
50
+ sleep 0.2
51
+ if close_after and chunks_out > close_after
52
+ socket.close
53
+ sleep 1
54
+ end
55
+ end
56
+ sleep(shutdown_delay)
57
+ socket.write(" ") # Some platforms only raise the exception on attempted write
58
+ socket.flush
59
+ end
60
+
61
+ def test_trickle_attack
62
+ do_test(@valid_request, 3)
63
+ end
64
+
65
+ def test_close_client
66
+ assert_raises IOError do
67
+ do_test(@valid_request, 10, 20)
68
+ end
69
+ end
70
+
71
+ def test_bad_client
72
+ do_test("GET /test HTTP/BAD", 3)
73
+ end
74
+
75
+ def test_header_is_too_long
76
+ long = "GET /test HTTP/1.1\r\n" + ("X-Big: stuff\r\n" * 15000) + "\r\n"
77
+ assert_raises Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED, Errno::EINVAL, IOError do
78
+ do_test(long, long.length/2, 10)
79
+ end
80
+ end
81
+
82
+ def test_file_streamed_request
83
+ body = "a" * (Puma::Const::MAX_BODY * 2)
84
+ long = "GET /test HTTP/1.1\r\nContent-length: #{body.length}\r\n\r\n" + body
85
+ do_test(long, (Puma::Const::CHUNK_SIZE * 2) - 400)
86
+ end
87
+
88
+ end
@@ -0,0 +1,9 @@
1
+ # Puma as a service
2
+
3
+ ## Init.d
4
+
5
+ See `/tools/jungle/init.d` for tools to use with init.d and start-stop-daemon.
6
+
7
+ ## Upstart
8
+
9
+ See `/tools/jungle/upstart` for Ubuntu's upstart scripts.
@@ -0,0 +1,59 @@
1
+ # Puma daemon service
2
+
3
+ Init script to manage multiple Puma servers on the same box using start-stop-daemon.
4
+
5
+ ## Installation
6
+
7
+ # Copy the init script to services directory
8
+ sudo cp puma /etc/init.d
9
+ sudo chmod +x /etc/init.d/puma
10
+
11
+ # Make it start at boot time.
12
+ sudo update-rc.d -f puma defaults
13
+
14
+ # Copy the Puma runner to an accessible location
15
+ sudo cp run-puma /usr/local/bin
16
+ sudo chmod +x /usr/local/bin/run-puma
17
+
18
+ # Create an empty configuration file
19
+ sudo touch /etc/puma.conf
20
+
21
+ ## Managing the jungle
22
+
23
+ Puma apps are held in /etc/puma.conf by default. It's mainly a CSV file and every line represents one app. Here's the syntax:
24
+
25
+ app-path,user,config-file-path,log-file-path,environment-variables
26
+
27
+ You can add an instance by editing the file or running the following command:
28
+
29
+ sudo /etc/init.d/puma add /path/to/app user /path/to/app/config/puma.rb /path/to/app/log/puma.log
30
+
31
+ The config and log paths, as well as the environment variables, are optional parameters and default to:
32
+
33
+ * config: /path/to/app/*config/puma.rb*
34
+ * log: /path/to/app/*log/puma.log*
35
+ * environment: (empty)
36
+
37
+ Multiple environment variables need to be separated by a semicolon, e.g.
38
+
39
+ FOO=1;BAR=2
40
+
41
+ To remove an app, simply delete the line from the config file or run:
42
+
43
+ sudo /etc/init.d/puma remove /path/to/app
44
+
45
+ The command will make sure the Puma instance stops before removing it from the jungle.
46
+
47
+ ## Assumptions
48
+
49
+ * The script expects a temporary folder named /path/to/app/*tmp/puma* to exist. Create it if it's not there by default.
50
+ The pid and state files should live there and must be called: *tmp/puma/pid* and *tmp/puma/state*.
51
+ You can change those if you want but you'll have to adapt the script for it to work.
52
+
53
+ * Here's what a minimal app's config file should have:
54
+
55
+ ```
56
+ pidfile "/path/to/app/tmp/puma/pid"
57
+ state_path "/path/to/app/tmp/puma/state"
58
+ activate_control_app
59
+ ```