puma 1.2.1 → 1.2.2
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 +9 -0
- data/Manifest.txt +1 -0
- data/README.md +35 -0
- data/lib/puma/const.rb +9 -44
- data/lib/puma/server.rb +8 -4
- data/puma.gemspec +11 -11
- data/test/test_rack_server.rb +19 -0
- metadata +6 -6
data/Gemfile
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 1.2.2 / 2012-04-28
|
2
|
+
|
3
|
+
* 4 bug fixes:
|
4
|
+
|
5
|
+
* Report a lowlevel error to stderr
|
6
|
+
* Set a fallback SERVER_NAME and SERVER_PORT
|
7
|
+
* Keep the encoding of the body correct. Fixes #79
|
8
|
+
* show error.to_s along with backtrace for low-level error
|
9
|
+
|
1
10
|
=== 1.2.1 / 2012-04-11
|
2
11
|
|
3
12
|
1 bug fix:
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -87,6 +87,41 @@ Need a bit of security? Use SSL sockets!
|
|
87
87
|
|
88
88
|
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
|
89
89
|
|
90
|
+
### Control/Status Server
|
91
|
+
|
92
|
+
Puma comes with a builtin status/control app that can be used query and control puma itself. Here is an example of starting puma with the control server:
|
93
|
+
|
94
|
+
$ puma --control tcp://127.0.0.1:9293 --control-token foo
|
95
|
+
|
96
|
+
This directly puma to start the control server on localhost port 9293. Additionally, all requests to the control server will need to include `token=foo` as a query parameter. This allows for simple authentication. Check out https://github.com/puma/puma/blob/master/lib/puma/app/status.rb to see what the app has available.
|
97
|
+
|
98
|
+
## Restart
|
99
|
+
|
100
|
+
Puma includes the ability to restart itself, allowing for new versions to be easily upgraded to. When available (currently anywhere but JRuby), puma performs a "hot restart". This is the same functionality available in *unicorn* and *nginx* which keep the server sockets open between restarts. This makes sure that no pending requests are dropped while the restart is taking place.
|
101
|
+
|
102
|
+
To perform a restart, there are 2 builtin mechanism:
|
103
|
+
|
104
|
+
* Send the puma process the `SIGUSR2` signal
|
105
|
+
* Use the status server and issue `/restart`
|
106
|
+
|
107
|
+
No code is shared between the current and restarted process, so it should be safe to issue a restart any place where you would manually stop puma and start it again.
|
108
|
+
|
109
|
+
If the new process is unable to load, it will simply exit. You should therefore run puma under a supervisor when using it in production.
|
110
|
+
|
111
|
+
### Cleanup Code
|
112
|
+
|
113
|
+
Puma isn't able to understand all the resources that your app may use, so it provides a hook in the configuration file you pass to `-C` call `on_restart`. The block passed to `on_restart` will be called, unsurprisingly, just before puma restarts itself.
|
114
|
+
|
115
|
+
You should place code to close global log files, redis connections, etc in this block so that their file descriptors don't leak into the restarted process. Failure to do so will result in slowly running out of descriptors and eventually obscure crashes as the server is restart many times.
|
116
|
+
|
117
|
+
## pumactl
|
118
|
+
|
119
|
+
If you start puma with `-S some/path` then you can pass that same path to the `pumactl` program to control your server. For instance:
|
120
|
+
|
121
|
+
$ pumactl -S some/path restart
|
122
|
+
|
123
|
+
will cause the server to perform a restart. `pumactl` is a simple CLI frontend to the contro/status app described above.
|
124
|
+
|
90
125
|
## License
|
91
126
|
|
92
127
|
Puma is copyright 2011 Evan Phoenix and contributors. It is licensed under the BSD license. See the include LICENSE file for details.
|
data/lib/puma/const.rb
CHANGED
@@ -1,52 +1,16 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
1
3
|
module Puma
|
2
4
|
|
3
5
|
# Every standard HTTP code mapped to the appropriate message. These are
|
4
6
|
# used so frequently that they are placed directly in Puma for easy
|
5
7
|
# access rather than Puma::Const itself.
|
6
|
-
HTTP_STATUS_CODES =
|
7
|
-
100 => 'Continue',
|
8
|
-
101 => 'Switching Protocols',
|
9
|
-
200 => 'OK',
|
10
|
-
201 => 'Created',
|
11
|
-
202 => 'Accepted',
|
12
|
-
203 => 'Non-Authoritative Information',
|
13
|
-
204 => 'No Content',
|
14
|
-
205 => 'Reset Content',
|
15
|
-
206 => 'Partial Content',
|
16
|
-
300 => 'Multiple Choices',
|
17
|
-
301 => 'Moved Permanently',
|
18
|
-
302 => 'Moved Temporarily',
|
19
|
-
303 => 'See Other',
|
20
|
-
304 => 'Not Modified',
|
21
|
-
305 => 'Use Proxy',
|
22
|
-
400 => 'Bad Request',
|
23
|
-
401 => 'Unauthorized',
|
24
|
-
402 => 'Payment Required',
|
25
|
-
403 => 'Forbidden',
|
26
|
-
404 => 'Not Found',
|
27
|
-
405 => 'Method Not Allowed',
|
28
|
-
406 => 'Not Acceptable',
|
29
|
-
407 => 'Proxy Authentication Required',
|
30
|
-
408 => 'Request Time-out',
|
31
|
-
409 => 'Conflict',
|
32
|
-
410 => 'Gone',
|
33
|
-
411 => 'Length Required',
|
34
|
-
412 => 'Precondition Failed',
|
35
|
-
413 => 'Request Entity Too Large',
|
36
|
-
414 => 'Request-URI Too Large',
|
37
|
-
415 => 'Unsupported Media Type',
|
38
|
-
500 => 'Internal Server Error',
|
39
|
-
501 => 'Not Implemented',
|
40
|
-
502 => 'Bad Gateway',
|
41
|
-
503 => 'Service Unavailable',
|
42
|
-
504 => 'Gateway Time-out',
|
43
|
-
505 => 'HTTP Version not supported'
|
44
|
-
}
|
8
|
+
HTTP_STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES
|
45
9
|
|
46
10
|
# For some HTTP status codes the client only expects headers.
|
47
|
-
STATUS_WITH_NO_ENTITY_BODY = {
|
48
|
-
|
49
|
-
}
|
11
|
+
STATUS_WITH_NO_ENTITY_BODY = Hash[Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.map { |s|
|
12
|
+
[s, true]
|
13
|
+
}]
|
50
14
|
|
51
15
|
# Frequently used constants when constructing requests or responses. Many times
|
52
16
|
# the constant just refers to a string with the same contents. Using these constants
|
@@ -61,6 +25,8 @@ module Puma
|
|
61
25
|
# too taxing on performance.
|
62
26
|
module Const
|
63
27
|
|
28
|
+
PUMA_VERSION = VERSION = "1.2.2".freeze
|
29
|
+
|
64
30
|
# The default number of seconds for another request within a persistent
|
65
31
|
# session.
|
66
32
|
PERSISTENT_TIMEOUT = 20
|
@@ -75,8 +41,6 @@ module Puma
|
|
75
41
|
|
76
42
|
PATH_INFO = 'PATH_INFO'.freeze
|
77
43
|
|
78
|
-
PUMA_VERSION = VERSION = "1.2.1".freeze
|
79
|
-
|
80
44
|
PUMA_TMP_BASE = "puma".freeze
|
81
45
|
|
82
46
|
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
@@ -122,6 +86,7 @@ module Puma
|
|
122
86
|
SERVER_PORT = "SERVER_PORT".freeze
|
123
87
|
HTTP_HOST = "HTTP_HOST".freeze
|
124
88
|
PORT_80 = "80".freeze
|
89
|
+
LOCALHOST = "localhost".freeze
|
125
90
|
|
126
91
|
SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
|
127
92
|
HTTP_11 = "HTTP/1.1".freeze
|
data/lib/puma/server.rb
CHANGED
@@ -356,6 +356,9 @@ module Puma
|
|
356
356
|
env[SERVER_NAME] = host
|
357
357
|
env[SERVER_PORT] = PORT_80
|
358
358
|
end
|
359
|
+
else
|
360
|
+
env[SERVER_NAME] = LOCALHOST
|
361
|
+
env[SERVER_PORT] = PORT_80
|
359
362
|
end
|
360
363
|
|
361
364
|
unless env[REQUEST_PATH]
|
@@ -422,6 +425,8 @@ module Puma
|
|
422
425
|
return :async
|
423
426
|
end
|
424
427
|
rescue => e
|
428
|
+
@events.unknown_error self, e, "Rack app"
|
429
|
+
|
425
430
|
status, headers, res_body = lowlevel_error(e)
|
426
431
|
end
|
427
432
|
|
@@ -568,12 +573,11 @@ module Puma
|
|
568
573
|
if remain > MAX_BODY
|
569
574
|
stream = Tempfile.new(Const::PUMA_TMP_BASE)
|
570
575
|
stream.binmode
|
576
|
+
stream.write body
|
571
577
|
else
|
572
|
-
stream = StringIO.new
|
578
|
+
stream = StringIO.new body
|
573
579
|
end
|
574
580
|
|
575
|
-
stream.write body
|
576
|
-
|
577
581
|
# Read an odd sized chunk so we can read even sized ones
|
578
582
|
# after this
|
579
583
|
chunk = client.readpartial(remain % CHUNK_SIZE)
|
@@ -605,7 +609,7 @@ module Puma
|
|
605
609
|
# A fallback rack response if +@app+ raises as exception.
|
606
610
|
#
|
607
611
|
def lowlevel_error(e)
|
608
|
-
[500, {}, ["Puma caught this error
|
612
|
+
[500, {}, ["Puma caught this error: #{e}\n#{e.backtrace.join("\n")}"]]
|
609
613
|
end
|
610
614
|
|
611
615
|
# Wait for all outstanding requests to finish.
|
data/puma.gemspec
CHANGED
@@ -2,23 +2,23 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "puma"
|
5
|
-
s.version = "1.2.
|
5
|
+
s.version = "1.2.2"
|
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 = "2012-04-
|
9
|
+
s.date = "2012-04-28"
|
10
10
|
s.description = "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.\n\nUnder 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!\n\nWith Rubinius 2.0, Puma will utilize all cores on your CPU with real threads, meaning you won't have to spawn multiple processes to increase throughput. You can expect to see a similar benefit from JRuby.\n\nOn MRI, there is a Global Interpreter Lock (GIL) that ensures only one thread can be run at a time. But if you're doing a lot of blocking IO (such as HTTP calls to external APIs like Twitter), Puma still improves MRI's throughput by allowing blocking IO to be run concurrently (EventMachine-based servers such as Thin turn off this ability, requiring you to use special libraries). Your mileage may vary. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like [Rubinius](http://rubini.us) or [JRuby](http://jruby.org)."
|
11
11
|
s.email = ["evan@phx.io"]
|
12
12
|
s.executables = ["puma", "pumactl"]
|
13
13
|
s.extensions = ["ext/puma_http11/extconf.rb"]
|
14
14
|
s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
|
15
|
-
s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "examples/CA/cacert.pem", "examples/CA/newcerts/cert_1.pem", "examples/CA/newcerts/cert_2.pem", "examples/CA/private/cakeypair.pem", "examples/CA/serial", "examples/config.rb", "examples/puma/cert_puma.pem", "examples/puma/csr_puma.pem", "examples/puma/puma_keypair.pem", "examples/qc_config.rb", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/app/status.rb", "lib/puma/cli.rb", "lib/puma/compat.rb", "lib/puma/configuration.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/events.rb", "lib/puma/jruby_restart.rb", "lib/puma/null_io.rb", "lib/puma/rack_patch.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "test/ab_rs.rb", "test/config/app.rb", "test/hello.ru", "test/lobster.ru", "test/mime.yaml", "test/slow.ru", "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_persistent.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", "test/testhelp.rb", "tools/trickletest.rb"
|
16
|
-
s.homepage = "http://puma.
|
15
|
+
s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "examples/CA/cacert.pem", "examples/CA/newcerts/cert_1.pem", "examples/CA/newcerts/cert_2.pem", "examples/CA/private/cakeypair.pem", "examples/CA/serial", "examples/config.rb", "examples/puma/cert_puma.pem", "examples/puma/csr_puma.pem", "examples/puma/puma_keypair.pem", "examples/qc_config.rb", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/app/status.rb", "lib/puma/cli.rb", "lib/puma/compat.rb", "lib/puma/configuration.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/events.rb", "lib/puma/jruby_restart.rb", "lib/puma/null_io.rb", "lib/puma/rack_patch.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "test/ab_rs.rb", "test/config/app.rb", "test/hello.ru", "test/lobster.ru", "test/mime.yaml", "test/slow.ru", "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_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", "test/testhelp.rb", "tools/trickletest.rb"]
|
16
|
+
s.homepage = "[![Build Status](https://secure.travis-ci.org/puma/puma.png)](http://travis-ci.org/puma/puma) [![Dependency Status](https://gemnasium.com/puma/puma.png)](https://gemnasium.com/puma/puma)"
|
17
17
|
s.rdoc_options = ["--main", "README.md"]
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
20
20
|
s.rubyforge_project = "puma"
|
21
|
-
s.rubygems_version = "1.8.
|
21
|
+
s.rubygems_version = "1.8.18"
|
22
22
|
s.summary = "Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web 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_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
|
|
@@ -27,19 +27,19 @@ Gem::Specification.new do |s|
|
|
27
27
|
|
28
28
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
29
29
|
s.add_runtime_dependency(%q<rack>, ["~> 1.2"])
|
30
|
-
s.add_development_dependency(%q<rdoc>, ["~> 3.10"])
|
31
30
|
s.add_development_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
32
|
-
s.add_development_dependency(%q<
|
31
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.10"])
|
32
|
+
s.add_development_dependency(%q<hoe>, ["~> 2.14"])
|
33
33
|
else
|
34
34
|
s.add_dependency(%q<rack>, ["~> 1.2"])
|
35
|
-
s.add_dependency(%q<rdoc>, ["~> 3.10"])
|
36
35
|
s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
37
|
-
s.add_dependency(%q<
|
36
|
+
s.add_dependency(%q<rdoc>, ["~> 3.10"])
|
37
|
+
s.add_dependency(%q<hoe>, ["~> 2.14"])
|
38
38
|
end
|
39
39
|
else
|
40
40
|
s.add_dependency(%q<rack>, ["~> 1.2"])
|
41
|
-
s.add_dependency(%q<rdoc>, ["~> 3.10"])
|
42
41
|
s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
43
|
-
s.add_dependency(%q<
|
42
|
+
s.add_dependency(%q<rdoc>, ["~> 3.10"])
|
43
|
+
s.add_dependency(%q<hoe>, ["~> 2.14"])
|
44
44
|
end
|
45
45
|
end
|
data/test/test_rack_server.rb
CHANGED
@@ -75,6 +75,24 @@ class TestRackServer < Test::Unit::TestCase
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
def test_large_post_body
|
79
|
+
@checker = ErrorChecker.new ServerLint.new(@simple)
|
80
|
+
@server.app = @checker
|
81
|
+
|
82
|
+
@server.run
|
83
|
+
|
84
|
+
big = "x" * (1024 * 16)
|
85
|
+
|
86
|
+
Net::HTTP.post_form URI.parse('http://localhost:9998/test'),
|
87
|
+
{ "big" => big }
|
88
|
+
|
89
|
+
stop
|
90
|
+
|
91
|
+
if exc = @checker.exception
|
92
|
+
raise exc
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
78
96
|
def test_path_info
|
79
97
|
input = nil
|
80
98
|
@server.app = lambda { |env| input = env; @simple.call(env) }
|
@@ -119,4 +137,5 @@ class TestRackServer < Test::Unit::TestCase
|
|
119
137
|
|
120
138
|
assert_match %r!GET /test HTTP/1\.1!, log.string
|
121
139
|
end
|
140
|
+
|
122
141
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 1.2.
|
9
|
+
- 2
|
10
|
+
version: 1.2.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Evan Phoenix
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-04-
|
18
|
+
date: 2012-04-28 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rack
|
@@ -156,6 +156,7 @@ files:
|
|
156
156
|
- test/test_http11.rb
|
157
157
|
- test/test_integration.rb
|
158
158
|
- test/test_persistent.rb
|
159
|
+
- test/test_puma_server.rb
|
159
160
|
- test/test_rack_handler.rb
|
160
161
|
- test/test_rack_server.rb
|
161
162
|
- test/test_thread_pool.rb
|
@@ -163,7 +164,6 @@ files:
|
|
163
164
|
- test/test_ws.rb
|
164
165
|
- test/testhelp.rb
|
165
166
|
- tools/trickletest.rb
|
166
|
-
- test/test_puma_server.rb
|
167
167
|
homepage: http://puma.io
|
168
168
|
licenses: []
|
169
169
|
|
@@ -196,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
196
|
requirements: []
|
197
197
|
|
198
198
|
rubyforge_project: puma
|
199
|
-
rubygems_version: 1.8.
|
199
|
+
rubygems_version: 1.8.18
|
200
200
|
signing_key:
|
201
201
|
specification_version: 3
|
202
202
|
summary: Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web applications
|