puma 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- data/Gemfile +2 -0
- data/History.txt +29 -0
- data/README.md +30 -1
- data/lib/puma/binder.rb +29 -2
- data/lib/puma/capistrano.rb +2 -1
- data/lib/puma/cli.rb +33 -11
- data/lib/puma/client.rb +7 -0
- data/lib/puma/configuration.rb +13 -5
- data/lib/puma/const.rb +1 -1
- data/lib/puma/control_cli.rb +10 -1
- data/lib/puma/minissl.rb +5 -4
- data/lib/puma/server.rb +26 -9
- data/puma.gemspec +4 -4
- data/test/test_app_status.rb +1 -1
- data/test/test_puma_server.rb +42 -0
- data/tools/jungle/upstart/puma-manager.conf +5 -5
- data/tools/jungle/upstart/puma.conf +2 -2
- metadata +203 -186
data/Gemfile
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
=== 2.1.0 / 2013-06-18
|
2
|
+
|
3
|
+
* 3 minor features:
|
4
|
+
* Allow listening socket to be configured via Capistrano variable
|
5
|
+
* Output results from 'stat's command when using pumactl
|
6
|
+
* Support systemd socket activation
|
7
|
+
|
8
|
+
* 15 bug fixes:
|
9
|
+
* Deal with pipes closing while stopping. Fixes #270
|
10
|
+
* Error out early if there is no app configured
|
11
|
+
* Handle ConnectionError rather than the lowlevel exceptions
|
12
|
+
* tune with `-C` config file and `on_worker_boot`
|
13
|
+
* use `-w`
|
14
|
+
* Fixed some typos in upstart scripts
|
15
|
+
* Make sure to use bytesize instead of size (MiniSSL write)
|
16
|
+
* Fix an error in puma-manager.conf
|
17
|
+
* fix: stop leaking sockets on restart (affects ruby 1.9.3 or before)
|
18
|
+
* Ignore errors on the cross-thread pipe. Fixes #246
|
19
|
+
* Ignore errors while uncorking the socket (it might already be closed)
|
20
|
+
* Ignore the body on a HEAD request. Fixes #278
|
21
|
+
* Handle all engine data when possible. Fixes #251.
|
22
|
+
* Handle all read exceptions properly. Fixes #252
|
23
|
+
* Handle errors from the server better
|
24
|
+
|
25
|
+
* 3 doc changes:
|
26
|
+
* Add note about on_worker_boot hook
|
27
|
+
* Add some documentation for Clustered mode
|
28
|
+
* Added quotes to /etc/puma.conf
|
29
|
+
|
1
30
|
=== 2.0.1 / 2013-04-30
|
2
31
|
|
3
32
|
* 1 bug fix:
|
data/README.md
CHANGED
@@ -4,6 +4,10 @@
|
|
4
4
|
|
5
5
|
## Description
|
6
6
|
|
7
|
+
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. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like Rubinius or JRuby.
|
8
|
+
|
9
|
+
## Built For Speed & Concurrency
|
10
|
+
|
7
11
|
Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web applications. It can be used with any application that supports Rack, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for [Rubinius](http://rubini.us), but also works well with JRuby and MRI. Puma is intended for use in both development and production environments.
|
8
12
|
|
9
13
|
Under the hood, Puma processes requests using a C-optimized Ragel extension (inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable way. Puma then serves the request in a thread from an internal thread pool (which you can control). This allows Puma to provide real concurrency for your web application!
|
@@ -69,6 +73,31 @@ Puma utilizes a dynamic thread pool which you can modify. You can set the minimu
|
|
69
73
|
|
70
74
|
Puma will automatically scale the number of threads based on how much traffic is present. The current default is `0:16`. Feel free to experiment, but be careful not to set the number of maximum threads to a very large number, as you may exhaust resources on the system (or hit resource limits).
|
71
75
|
|
76
|
+
### Clustered mode
|
77
|
+
|
78
|
+
Puma 2 offers clustered mode, allowing you to use forked processes to handle multiple incoming requests concurrently, in addition to threads already provided. You can tune the number of workers with the `-w` (or `--workers`) flag:
|
79
|
+
|
80
|
+
$ puma -t 8:32 -w 3
|
81
|
+
|
82
|
+
On a ruby implementation that offers native threads, you should tune this number to match the number of cores available.
|
83
|
+
Note that threads are still used in clustered mode, and the `-t` thread flag setting is per worker, so `-w 2 -t 16:16` will be 32 threads.
|
84
|
+
|
85
|
+
Additionally, you can specify a block in your configuration that will be run on boot of each worker:
|
86
|
+
|
87
|
+
# config/puma.rb
|
88
|
+
on_worker_boot do
|
89
|
+
# configuration here
|
90
|
+
end
|
91
|
+
|
92
|
+
This code can be used to setup the process before booting the application, allowing
|
93
|
+
you to do some puma-specific things that you don't want to embed in your application.
|
94
|
+
For instance, you could fire a log notification that a worker booted or send something to statsd.
|
95
|
+
This can be called multiple times to add hooks.
|
96
|
+
|
97
|
+
Be sure to specify the location of your configuration file:
|
98
|
+
|
99
|
+
$ puma -t 8:32 -w 3 -C config/puma.rb
|
100
|
+
|
72
101
|
### Binding TCP / Sockets
|
73
102
|
|
74
103
|
In contrast to many other server configs which require multiple flags, Puma simply uses one URI parameter with the `-b` (or `--bind`) flag:
|
@@ -165,4 +194,4 @@ $ bundle exec cap puma:stop
|
|
165
194
|
|
166
195
|
## License
|
167
196
|
|
168
|
-
Puma is copyright
|
197
|
+
Puma is copyright 2013 Evan Phoenix and contributors. It is licensed under the BSD license. See the include LICENSE file for details.
|
data/lib/puma/binder.rb
CHANGED
@@ -53,6 +53,24 @@ module Puma
|
|
53
53
|
@inherited_fds[url] = fd.to_i
|
54
54
|
remove << k
|
55
55
|
end
|
56
|
+
if k =~ /LISTEN_FDS/ && ENV['LISTEN_PID'].to_i == $$
|
57
|
+
v.to_i.times do |num|
|
58
|
+
fd = num + 3
|
59
|
+
sock = TCPServer.for_fd(fd)
|
60
|
+
begin
|
61
|
+
url = "unix://" + Socket.unpack_sockaddr_un(sock.getsockname)
|
62
|
+
rescue ArgumentError
|
63
|
+
port, addr = Socket.unpack_sockaddr_in(sock.getsockname)
|
64
|
+
if addr =~ /\:/
|
65
|
+
addr = "[#{addr}]"
|
66
|
+
end
|
67
|
+
url = "tcp://#{addr}:#{port}"
|
68
|
+
end
|
69
|
+
@inherited_fds[url] = sock
|
70
|
+
end
|
71
|
+
ENV.delete k
|
72
|
+
ENV.delete 'LISTEN_PID'
|
73
|
+
end
|
56
74
|
end
|
57
75
|
|
58
76
|
remove.each do |k|
|
@@ -141,7 +159,12 @@ module Puma
|
|
141
159
|
logger.log "* Closing unused inherited connection: #{str}"
|
142
160
|
|
143
161
|
begin
|
144
|
-
|
162
|
+
if fd.kind_of? TCPServer
|
163
|
+
fd.close
|
164
|
+
else
|
165
|
+
IO.for_fd(fd).close
|
166
|
+
end
|
167
|
+
|
145
168
|
rescue SystemCallError
|
146
169
|
end
|
147
170
|
|
@@ -244,7 +267,11 @@ module Puma
|
|
244
267
|
def inherit_unix_listener(path, fd)
|
245
268
|
@unix_paths << path
|
246
269
|
|
247
|
-
|
270
|
+
if fd.kind_of? TCPServer
|
271
|
+
s = fd
|
272
|
+
else
|
273
|
+
s = UNIXServer.for_fd fd
|
274
|
+
end
|
248
275
|
@ios << s
|
249
276
|
|
250
277
|
s
|
data/lib/puma/capistrano.rb
CHANGED
@@ -11,13 +11,14 @@ Capistrano::Configuration.instance.load do
|
|
11
11
|
_cset(:puma_cmd) { "#{fetch(:bundle_cmd, 'bundle')} exec puma" }
|
12
12
|
_cset(:pumactl_cmd) { "#{fetch(:bundle_cmd, 'bundle')} exec pumactl" }
|
13
13
|
_cset(:puma_state) { "#{shared_path}/sockets/puma.state" }
|
14
|
+
_cset(:puma_socket) { "unix://#{shared_path}/sockets/puma.sock" }
|
14
15
|
_cset(:puma_role) { :app }
|
15
16
|
|
16
17
|
namespace :puma do
|
17
18
|
desc 'Start puma'
|
18
19
|
task :start, :roles => lambda { fetch(:puma_role) }, :on_no_matching_servers => :continue do
|
19
20
|
puma_env = fetch(:rack_env, fetch(:rails_env, 'production'))
|
20
|
-
run "cd #{current_path} && #{fetch(:puma_cmd)} -q -d -e #{puma_env} -b '
|
21
|
+
run "cd #{current_path} && #{fetch(:puma_cmd)} -q -d -e #{puma_env} -b '#{fetch(:puma_socket)}' -S #{fetch(:puma_state)} --control 'unix://#{shared_path}/sockets/pumactl.sock'", :pty => false
|
21
22
|
end
|
22
23
|
|
23
24
|
desc 'Stop puma'
|
data/lib/puma/cli.rb
CHANGED
@@ -117,7 +117,7 @@ module Puma
|
|
117
117
|
require 'puma/jruby_restart'
|
118
118
|
JRubyRestart.chdir_exec(@restart_dir, @restart_argv)
|
119
119
|
else
|
120
|
-
redirects = {}
|
120
|
+
redirects = {:close_others => true}
|
121
121
|
@binder.listeners.each_with_index do |(l,io),i|
|
122
122
|
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
123
123
|
redirects[io.to_i] = io.to_i
|
@@ -419,6 +419,11 @@ module Puma
|
|
419
419
|
|
420
420
|
@binder.parse @options[:binds], self
|
421
421
|
|
422
|
+
unless @config.app_configured?
|
423
|
+
error "No application configured, nothing to run"
|
424
|
+
exit 1
|
425
|
+
end
|
426
|
+
|
422
427
|
if @options[:daemon]
|
423
428
|
Process.daemon(true, @io_redirected)
|
424
429
|
end
|
@@ -547,7 +552,12 @@ module Puma
|
|
547
552
|
server.stop
|
548
553
|
end
|
549
554
|
|
550
|
-
|
555
|
+
begin
|
556
|
+
@worker_write << "b#{Process.pid}\n"
|
557
|
+
rescue SystemCallError, IOError
|
558
|
+
STDERR.puts "Master seems to have exitted, exitting."
|
559
|
+
return
|
560
|
+
end
|
551
561
|
|
552
562
|
server.run.join
|
553
563
|
|
@@ -643,6 +653,13 @@ module Puma
|
|
643
653
|
end
|
644
654
|
end
|
645
655
|
|
656
|
+
def wakeup!
|
657
|
+
begin
|
658
|
+
@wakeup.write "!" unless @wakeup.closed?
|
659
|
+
rescue SystemCallError, IOError
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
646
663
|
def run_cluster
|
647
664
|
log "Puma #{Puma::Const::PUMA_VERSION} starting in cluster mode..."
|
648
665
|
log "* Process workers: #{@options[:workers]}"
|
@@ -651,10 +668,15 @@ module Puma
|
|
651
668
|
|
652
669
|
@binder.parse @options[:binds], self
|
653
670
|
|
654
|
-
|
671
|
+
unless @config.app_configured?
|
672
|
+
error "No application configured, nothing to run"
|
673
|
+
exit 1
|
674
|
+
end
|
675
|
+
|
676
|
+
read, @wakeup = Puma::Util.pipe
|
655
677
|
|
656
678
|
Signal.trap "SIGCHLD" do
|
657
|
-
|
679
|
+
wakeup!
|
658
680
|
end
|
659
681
|
|
660
682
|
stop = false
|
@@ -663,7 +685,7 @@ module Puma
|
|
663
685
|
Signal.trap "SIGUSR2" do
|
664
686
|
@restart = true
|
665
687
|
stop = true
|
666
|
-
|
688
|
+
wakeup!
|
667
689
|
end
|
668
690
|
rescue Exception
|
669
691
|
end
|
@@ -672,7 +694,7 @@ module Puma
|
|
672
694
|
|
673
695
|
begin
|
674
696
|
Signal.trap "SIGTERM" do
|
675
|
-
# The worker installs
|
697
|
+
# The worker installs their own SIGTERM when booted.
|
676
698
|
# Until then, this is run by the worker and the worker
|
677
699
|
# should just exit if they get it.
|
678
700
|
if Process.pid != master_pid
|
@@ -680,7 +702,7 @@ module Puma
|
|
680
702
|
exit! 0
|
681
703
|
else
|
682
704
|
stop = true
|
683
|
-
|
705
|
+
wakeup!
|
684
706
|
end
|
685
707
|
end
|
686
708
|
rescue Exception
|
@@ -691,7 +713,7 @@ module Puma
|
|
691
713
|
begin
|
692
714
|
Signal.trap "SIGUSR1" do
|
693
715
|
phased_restart = true
|
694
|
-
|
716
|
+
wakeup!
|
695
717
|
end
|
696
718
|
rescue Exception
|
697
719
|
end
|
@@ -715,12 +737,12 @@ module Puma
|
|
715
737
|
|
716
738
|
write_state
|
717
739
|
|
718
|
-
@master_read, @worker_write = read,
|
740
|
+
@master_read, @worker_write = read, @wakeup
|
719
741
|
spawn_workers
|
720
742
|
|
721
743
|
Signal.trap "SIGINT" do
|
722
744
|
stop = true
|
723
|
-
|
745
|
+
wakeup!
|
724
746
|
end
|
725
747
|
|
726
748
|
begin
|
@@ -761,7 +783,7 @@ module Puma
|
|
761
783
|
@check_pipe.close
|
762
784
|
@suicide_pipe.close
|
763
785
|
read.close
|
764
|
-
|
786
|
+
@wakeup.close
|
765
787
|
end
|
766
788
|
|
767
789
|
if @restart
|
data/lib/puma/client.rb
CHANGED
@@ -16,6 +16,9 @@ if Puma::IS_JRUBY
|
|
16
16
|
end
|
17
17
|
|
18
18
|
module Puma
|
19
|
+
|
20
|
+
class ConnectionError < RuntimeError; end
|
21
|
+
|
19
22
|
class Client
|
20
23
|
include Puma::Const
|
21
24
|
|
@@ -139,6 +142,8 @@ module Puma
|
|
139
142
|
data = @io.read_nonblock(CHUNK_SIZE)
|
140
143
|
rescue Errno::EAGAIN
|
141
144
|
return false
|
145
|
+
rescue SystemCallError, IOError
|
146
|
+
raise ConnectionError, "Connection error detected during read"
|
142
147
|
end
|
143
148
|
|
144
149
|
if @buffer
|
@@ -223,6 +228,8 @@ module Puma
|
|
223
228
|
chunk = @io.read_nonblock(want)
|
224
229
|
rescue Errno::EAGAIN
|
225
230
|
return false
|
231
|
+
rescue SystemCallError, IOError
|
232
|
+
raise ConnectionError, "Connection error detected during read"
|
226
233
|
end
|
227
234
|
|
228
235
|
# No chunk means a closed socket
|
data/lib/puma/configuration.rb
CHANGED
@@ -67,6 +67,16 @@ module Puma
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
# Indicate if there is a properly configured app
|
71
|
+
#
|
72
|
+
def app_configured?
|
73
|
+
@options[:app] || File.exists?(rackup)
|
74
|
+
end
|
75
|
+
|
76
|
+
def rackup
|
77
|
+
@options[:rackup] || DefaultRackup
|
78
|
+
end
|
79
|
+
|
70
80
|
# Load the specified rackup file, pull an options from
|
71
81
|
# the rackup file, and set @app.
|
72
82
|
#
|
@@ -74,13 +84,11 @@ module Puma
|
|
74
84
|
app = @options[:app]
|
75
85
|
|
76
86
|
unless app
|
77
|
-
|
78
|
-
|
79
|
-
unless File.exists?(path)
|
80
|
-
raise "Missing rackup file '#{path}'"
|
87
|
+
unless File.exists?(rackup)
|
88
|
+
raise "Missing rackup file '#{rackup}'"
|
81
89
|
end
|
82
90
|
|
83
|
-
app, options = Rack::Builder.parse_file
|
91
|
+
app, options = Rack::Builder.parse_file rackup
|
84
92
|
@options.merge! options
|
85
93
|
|
86
94
|
options.each do |key,val|
|
data/lib/puma/const.rb
CHANGED
data/lib/puma/control_cli.rb
CHANGED
@@ -138,7 +138,15 @@ module Puma
|
|
138
138
|
|
139
139
|
@server << "GET #{url} HTTP/1.0\r\n\r\n"
|
140
140
|
|
141
|
-
|
141
|
+
unless data = @server.read
|
142
|
+
raise "Server closed connection before responding"
|
143
|
+
end
|
144
|
+
|
145
|
+
response = data.split("\r\n")
|
146
|
+
|
147
|
+
if response.empty?
|
148
|
+
raise "Server sent empty response"
|
149
|
+
end
|
142
150
|
|
143
151
|
(@http,@code,@message) = response.first.split(" ")
|
144
152
|
|
@@ -149,6 +157,7 @@ module Puma
|
|
149
157
|
end
|
150
158
|
|
151
159
|
message "Command #{@options[:command]} sent success"
|
160
|
+
message response.last if @options[:command] == "stats"
|
152
161
|
end
|
153
162
|
|
154
163
|
@server.close
|
data/lib/puma/minissl.rb
CHANGED
@@ -46,19 +46,20 @@ module Puma
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def write(data)
|
49
|
-
need = data.
|
49
|
+
need = data.bytesize
|
50
50
|
|
51
51
|
while true
|
52
52
|
wrote = @engine.write data
|
53
53
|
enc = @engine.extract
|
54
54
|
|
55
|
-
|
56
|
-
@socket.
|
55
|
+
while enc
|
56
|
+
@socket.write enc
|
57
|
+
enc = @engine.extract
|
57
58
|
end
|
58
59
|
|
59
60
|
need -= wrote
|
60
61
|
|
61
|
-
return data.
|
62
|
+
return data.bytesize if need == 0
|
62
63
|
|
63
64
|
data = data[need..-1]
|
64
65
|
end
|
data/lib/puma/server.rb
CHANGED
@@ -94,7 +94,10 @@ module Puma
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def uncork_socket(socket)
|
97
|
-
|
97
|
+
begin
|
98
|
+
socket.setsockopt(6, 3, 0) if socket.kind_of? TCPSocket
|
99
|
+
rescue IOError
|
100
|
+
end
|
98
101
|
end
|
99
102
|
else
|
100
103
|
def cork_socket(socket)
|
@@ -135,7 +138,7 @@ module Puma
|
|
135
138
|
client.close
|
136
139
|
|
137
140
|
@events.parse_error self, client.env, e
|
138
|
-
rescue
|
141
|
+
rescue ConnectionError
|
139
142
|
client.close
|
140
143
|
else
|
141
144
|
if process_now
|
@@ -259,7 +262,7 @@ module Puma
|
|
259
262
|
end
|
260
263
|
|
261
264
|
# The client disconnected while we were reading data
|
262
|
-
rescue
|
265
|
+
rescue ConnectionError
|
263
266
|
# Swallow them. The ensure tries to close +client+ down
|
264
267
|
|
265
268
|
# The client doesn't know HTTP well
|
@@ -351,6 +354,8 @@ module Puma
|
|
351
354
|
|
352
355
|
body = req.body
|
353
356
|
|
357
|
+
head = env[REQUEST_METHOD] == HEAD
|
358
|
+
|
354
359
|
env[RACK_INPUT] = body
|
355
360
|
env[RACK_URL_SCHEME] = env[HTTPS_KEY] ? HTTPS : HTTP
|
356
361
|
|
@@ -381,7 +386,7 @@ module Puma
|
|
381
386
|
end
|
382
387
|
|
383
388
|
content_length = nil
|
384
|
-
no_body =
|
389
|
+
no_body = head
|
385
390
|
|
386
391
|
if res_body.kind_of? Array and res_body.size == 1
|
387
392
|
content_length = res_body[0].bytesize
|
@@ -407,7 +412,7 @@ module Puma
|
|
407
412
|
lines.append "HTTP/1.1 ", status.to_s, " ",
|
408
413
|
HTTP_STATUS_CODES[status], line_ending
|
409
414
|
|
410
|
-
no_body
|
415
|
+
no_body ||= status < 200 || STATUS_WITH_NO_ENTITY_BODY[status]
|
411
416
|
end
|
412
417
|
else
|
413
418
|
allow_chunked = false
|
@@ -422,7 +427,7 @@ module Puma
|
|
422
427
|
lines.append "HTTP/1.0 ", status.to_s, " ",
|
423
428
|
HTTP_STATUS_CODES[status], line_ending
|
424
429
|
|
425
|
-
no_body
|
430
|
+
no_body ||= status < 200 || STATUS_WITH_NO_ENTITY_BODY[status]
|
426
431
|
end
|
427
432
|
end
|
428
433
|
|
@@ -579,19 +584,31 @@ module Puma
|
|
579
584
|
# off the request queue before finally exiting.
|
580
585
|
#
|
581
586
|
def stop(sync=false)
|
582
|
-
|
587
|
+
begin
|
588
|
+
@notify << STOP_COMMAND
|
589
|
+
rescue IOError
|
590
|
+
# The server, in another thread, is shutting down
|
591
|
+
end
|
583
592
|
|
584
593
|
@thread.join if @thread && sync
|
585
594
|
end
|
586
595
|
|
587
596
|
def halt(sync=false)
|
588
|
-
|
597
|
+
begin
|
598
|
+
@notify << HALT_COMMAND
|
599
|
+
rescue IOError
|
600
|
+
# The server, in another thread, is shutting down
|
601
|
+
end
|
589
602
|
|
590
603
|
@thread.join if @thread && sync
|
591
604
|
end
|
592
605
|
|
593
606
|
def begin_restart
|
594
|
-
|
607
|
+
begin
|
608
|
+
@notify << RESTART_COMMAND
|
609
|
+
rescue IOError
|
610
|
+
# The server, in another thread, is shutting down
|
611
|
+
end
|
595
612
|
end
|
596
613
|
|
597
614
|
def fast_write(io, str)
|
data/puma.gemspec
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "puma"
|
5
|
-
s.version = "2.0
|
5
|
+
s.version = "2.1.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Evan Phoenix"]
|
9
|
-
s.date = "2013-
|
10
|
-
s.description = "Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby
|
9
|
+
s.date = "2013-06-18"
|
10
|
+
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. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like Rubinius or JRuby."
|
11
11
|
s.email = ["evan@phx.io"]
|
12
12
|
s.executables = ["puma", "pumactl"]
|
13
13
|
s.extensions = ["ext/puma_http11/extconf.rb"]
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
20
20
|
s.rubyforge_project = "puma"
|
21
21
|
s.rubygems_version = "1.8.25"
|
22
|
-
s.summary = "Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby
|
22
|
+
s.summary = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications"
|
23
23
|
s.test_files = ["test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_iobuffer.rb", "test/test_minissl.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
|
24
24
|
|
25
25
|
if s.respond_to? :specification_version then
|
data/test/test_app_status.rb
CHANGED
data/test/test_puma_server.rb
CHANGED
@@ -162,4 +162,46 @@ class TestPumaServer < Test::Unit::TestCase
|
|
162
162
|
|
163
163
|
assert_equal "80", res.body
|
164
164
|
end
|
165
|
+
|
166
|
+
def test_HEAD_has_no_body
|
167
|
+
@server.app = proc { |env| [200, {"Foo" => "Bar"}, ["hello"]] }
|
168
|
+
|
169
|
+
@server.add_tcp_listener @host, @port
|
170
|
+
@server.run
|
171
|
+
|
172
|
+
sock = TCPSocket.new @host, @port
|
173
|
+
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
174
|
+
|
175
|
+
data = sock.read
|
176
|
+
|
177
|
+
assert_equal "HTTP/1.0 200 OK\r\nFoo: Bar\r\n\r\n", data
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_GET_with_empty_body_has_sane_chunking
|
181
|
+
@server.app = proc { |env| [200, {}, [""]] }
|
182
|
+
|
183
|
+
@server.add_tcp_listener @host, @port
|
184
|
+
@server.run
|
185
|
+
|
186
|
+
sock = TCPSocket.new @host, @port
|
187
|
+
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
188
|
+
|
189
|
+
data = sock.read
|
190
|
+
|
191
|
+
assert_equal "HTTP/1.0 200 OK\r\n\r\n", data
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_GET_with_no_body_has_sane_chunking
|
195
|
+
@server.app = proc { |env| [200, {}, [""]] }
|
196
|
+
|
197
|
+
@server.add_tcp_listener @host, @port
|
198
|
+
@server.run
|
199
|
+
|
200
|
+
sock = TCPSocket.new @host, @port
|
201
|
+
sock << "HEAD / HTTP/1.0\r\n\r\n"
|
202
|
+
|
203
|
+
data = sock.read
|
204
|
+
|
205
|
+
assert_equal "HTTP/1.0 200 OK\r\n\r\n", data
|
206
|
+
end
|
165
207
|
end
|
@@ -6,9 +6,9 @@
|
|
6
6
|
#
|
7
7
|
# See puma.conf for how to manage a single Puma instance.
|
8
8
|
#
|
9
|
-
# Use "stop
|
10
|
-
# Use "start
|
11
|
-
# Use "restart
|
9
|
+
# Use "stop puma-manager" to stop all Puma instances.
|
10
|
+
# Use "start puma-manager" to start all instances.
|
11
|
+
# Use "restart puma-manager" to restart all instances.
|
12
12
|
# Crazy, right?
|
13
13
|
#
|
14
14
|
|
@@ -20,12 +20,12 @@ stop on runlevel [06]
|
|
20
20
|
|
21
21
|
# Set this to the number of Puma processes you want
|
22
22
|
# to run on this machine
|
23
|
-
env PUMA_CONF
|
23
|
+
env PUMA_CONF="/etc/puma.conf"
|
24
24
|
|
25
25
|
pre-start script
|
26
26
|
for i in `cat $PUMA_CONF`; do
|
27
27
|
app=`echo $i | cut -d , -f 1`
|
28
|
-
logger -t "puma-manager" "Starting $app"
|
28
|
+
logger -t "puma-manager" "Starting $app"
|
29
29
|
start puma app=$app
|
30
30
|
done
|
31
31
|
end script
|
@@ -6,7 +6,7 @@
|
|
6
6
|
#
|
7
7
|
# See workers.conf for how to manage all Puma instances at once.
|
8
8
|
#
|
9
|
-
# Save this config as /etc/init/puma.conf then
|
9
|
+
# Save this config as /etc/init/puma.conf then manage puma with:
|
10
10
|
# sudo start puma index=0
|
11
11
|
# sudo stop puma index=0
|
12
12
|
# sudo status puma index=0
|
@@ -34,7 +34,7 @@ script
|
|
34
34
|
# respawn as bash so we can source in rbenv/rvm
|
35
35
|
exec /bin/bash <<EOT
|
36
36
|
export HOME=/home/apps
|
37
|
-
|
37
|
+
|
38
38
|
# Pick your poison :) Or none if you're using a system wide installed Ruby.
|
39
39
|
# rbenv
|
40
40
|
# source /home/apps/.bash_profile
|
metadata
CHANGED
@@ -1,201 +1,218 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.1.0
|
4
5
|
prerelease:
|
5
|
-
version: 2.0.1
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
|
7
|
+
authors:
|
8
|
+
- Evan Phoenix
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
12
|
+
date: 2013-06-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rack
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.1'
|
22
|
+
- - <
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '2.0'
|
25
|
+
type: :runtime
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.1'
|
33
|
+
- - <
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '2.0'
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rdoc
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '3.10'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ~>
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '3.10'
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: rake-compiler
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 0.8.0
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ~>
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.8.0
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: hoe
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.5'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ~>
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '3.5'
|
84
|
+
description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server
|
85
|
+
for Ruby/Rack applications. Puma is intended for use in both development and production
|
86
|
+
environments. In order to get the best throughput, it is highly recommended that
|
87
|
+
you use a Ruby implementation with real threads like Rubinius or JRuby.
|
88
|
+
email:
|
89
|
+
- evan@phx.io
|
90
|
+
executables:
|
91
|
+
- puma
|
92
|
+
- pumactl
|
93
|
+
extensions:
|
94
|
+
- ext/puma_http11/extconf.rb
|
95
|
+
extra_rdoc_files:
|
96
|
+
- History.txt
|
97
|
+
- Manifest.txt
|
98
|
+
files:
|
99
|
+
- COPYING
|
100
|
+
- Gemfile
|
101
|
+
- History.txt
|
102
|
+
- LICENSE
|
103
|
+
- Manifest.txt
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- TODO
|
107
|
+
- bin/puma
|
108
|
+
- bin/pumactl
|
109
|
+
- docs/config.md
|
110
|
+
- docs/nginx.md
|
111
|
+
- ext/puma_http11/PumaHttp11Service.java
|
112
|
+
- ext/puma_http11/ext_help.h
|
113
|
+
- ext/puma_http11/extconf.rb
|
114
|
+
- ext/puma_http11/http11_parser.c
|
115
|
+
- ext/puma_http11/http11_parser.h
|
116
|
+
- ext/puma_http11/http11_parser.java.rl
|
117
|
+
- ext/puma_http11/http11_parser.rl
|
118
|
+
- ext/puma_http11/http11_parser_common.rl
|
119
|
+
- ext/puma_http11/io_buffer.c
|
120
|
+
- ext/puma_http11/mini_ssl.c
|
121
|
+
- ext/puma_http11/org/jruby/puma/Http11.java
|
122
|
+
- ext/puma_http11/org/jruby/puma/Http11Parser.java
|
123
|
+
- ext/puma_http11/org/jruby/puma/MiniSSL.java
|
124
|
+
- ext/puma_http11/puma_http11.c
|
125
|
+
- lib/puma.rb
|
126
|
+
- lib/puma/accept_nonblock.rb
|
127
|
+
- lib/puma/app/status.rb
|
128
|
+
- lib/puma/binder.rb
|
129
|
+
- lib/puma/capistrano.rb
|
130
|
+
- lib/puma/cli.rb
|
131
|
+
- lib/puma/client.rb
|
132
|
+
- lib/puma/compat.rb
|
133
|
+
- lib/puma/configuration.rb
|
134
|
+
- lib/puma/const.rb
|
135
|
+
- lib/puma/control_cli.rb
|
136
|
+
- lib/puma/daemon_ext.rb
|
137
|
+
- lib/puma/delegation.rb
|
138
|
+
- lib/puma/detect.rb
|
139
|
+
- lib/puma/events.rb
|
140
|
+
- lib/puma/io_buffer.rb
|
141
|
+
- lib/puma/java_io_buffer.rb
|
142
|
+
- lib/puma/jruby_restart.rb
|
143
|
+
- lib/puma/minissl.rb
|
144
|
+
- lib/puma/null_io.rb
|
145
|
+
- lib/puma/rack_default.rb
|
146
|
+
- lib/puma/rack_patch.rb
|
147
|
+
- lib/puma/reactor.rb
|
148
|
+
- lib/puma/server.rb
|
149
|
+
- lib/puma/thread_pool.rb
|
150
|
+
- lib/puma/util.rb
|
151
|
+
- lib/rack/handler/puma.rb
|
152
|
+
- puma.gemspec
|
153
|
+
- tools/jungle/init.d/README.md
|
154
|
+
- tools/jungle/init.d/puma
|
155
|
+
- tools/jungle/init.d/run-puma
|
156
|
+
- tools/jungle/upstart/README.md
|
157
|
+
- tools/jungle/upstart/puma-manager.conf
|
158
|
+
- tools/jungle/upstart/puma.conf
|
159
|
+
- test/test_app_status.rb
|
160
|
+
- test/test_cli.rb
|
161
|
+
- test/test_config.rb
|
162
|
+
- test/test_http10.rb
|
163
|
+
- test/test_http11.rb
|
164
|
+
- test/test_integration.rb
|
165
|
+
- test/test_iobuffer.rb
|
166
|
+
- test/test_minissl.rb
|
167
|
+
- test/test_null_io.rb
|
168
|
+
- test/test_persistent.rb
|
169
|
+
- test/test_puma_server.rb
|
170
|
+
- test/test_rack_handler.rb
|
171
|
+
- test/test_rack_server.rb
|
172
|
+
- test/test_thread_pool.rb
|
173
|
+
- test/test_unix_socket.rb
|
174
|
+
- test/test_ws.rb
|
157
175
|
homepage: http://puma.io
|
158
176
|
licenses: []
|
159
|
-
|
160
177
|
post_install_message:
|
161
|
-
rdoc_options:
|
162
|
-
|
163
|
-
|
164
|
-
require_paths:
|
165
|
-
|
166
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
178
|
+
rdoc_options:
|
179
|
+
- --main
|
180
|
+
- README.md
|
181
|
+
require_paths:
|
182
|
+
- lib
|
183
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
167
184
|
none: false
|
168
|
-
requirements:
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
|
+
requirements:
|
186
|
+
- - ! '>='
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: 1.8.7
|
189
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
190
|
none: false
|
174
|
-
requirements:
|
175
|
-
|
176
|
-
|
177
|
-
|
191
|
+
requirements:
|
192
|
+
- - ! '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
178
195
|
requirements: []
|
179
|
-
|
180
196
|
rubyforge_project: puma
|
181
|
-
rubygems_version: 1.8.
|
197
|
+
rubygems_version: 1.8.25
|
182
198
|
signing_key:
|
183
199
|
specification_version: 3
|
184
|
-
summary: Puma is a simple, fast, and highly concurrent HTTP 1.1 server for
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
200
|
+
summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
|
201
|
+
Ruby/Rack applications
|
202
|
+
test_files:
|
203
|
+
- test/test_app_status.rb
|
204
|
+
- test/test_cli.rb
|
205
|
+
- test/test_config.rb
|
206
|
+
- test/test_http10.rb
|
207
|
+
- test/test_http11.rb
|
208
|
+
- test/test_integration.rb
|
209
|
+
- test/test_iobuffer.rb
|
210
|
+
- test/test_minissl.rb
|
211
|
+
- test/test_null_io.rb
|
212
|
+
- test/test_persistent.rb
|
213
|
+
- test/test_puma_server.rb
|
214
|
+
- test/test_rack_handler.rb
|
215
|
+
- test/test_rack_server.rb
|
216
|
+
- test/test_thread_pool.rb
|
217
|
+
- test/test_unix_socket.rb
|
218
|
+
- test/test_ws.rb
|