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