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 CHANGED
@@ -4,3 +4,5 @@ gem "hoe"
4
4
  gem "rdoc"
5
5
  gem "rake-compiler"
6
6
  gem "rack"
7
+
8
+ gem "jruby-openssl", :platform => "jruby"
@@ -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:
@@ -57,6 +57,7 @@ test/test_http10.rb
57
57
  test/test_http11.rb
58
58
  test/test_integration.rb
59
59
  test/test_persistent.rb
60
+ test/test_puma_server.rb
60
61
  test/test_rack_handler.rb
61
62
  test/test_rack_server.rb
62
63
  test/test_thread_pool.rb
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.
@@ -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
- 204 => true, 205 => true, 304 => true
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
@@ -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:\n#{e.backtrace.join("\n")}"]]
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.
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "puma"
5
- s.version = "1.2.1"
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-11"
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", "test/test_puma_server.rb"]
16
- s.homepage = "http://puma.io"
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"
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<hoe>, ["~> 3.0"])
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<hoe>, ["~> 3.0"])
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<hoe>, ["~> 3.0"])
42
+ s.add_dependency(%q<rdoc>, ["~> 3.10"])
43
+ s.add_dependency(%q<hoe>, ["~> 2.14"])
44
44
  end
45
45
  end
@@ -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: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
- - 1
10
- version: 1.2.1
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-11 00:00:00 Z
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.21
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