puma 0.8.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.

Files changed (59) hide show
  1. data/.gemtest +0 -0
  2. data/COPYING +55 -0
  3. data/History.txt +69 -0
  4. data/LICENSE +26 -0
  5. data/Manifest.txt +57 -0
  6. data/README.md +60 -0
  7. data/Rakefile +10 -0
  8. data/TODO +5 -0
  9. data/bin/puma +15 -0
  10. data/examples/builder.rb +29 -0
  11. data/examples/camping/README +3 -0
  12. data/examples/camping/blog.rb +294 -0
  13. data/examples/camping/tepee.rb +149 -0
  14. data/examples/httpd.conf +474 -0
  15. data/examples/mime.yaml +3 -0
  16. data/examples/mongrel.conf +9 -0
  17. data/examples/monitrc +57 -0
  18. data/examples/random_thrash.rb +19 -0
  19. data/examples/simpletest.rb +52 -0
  20. data/examples/webrick_compare.rb +20 -0
  21. data/ext/puma_http11/Http11Service.java +13 -0
  22. data/ext/puma_http11/ext_help.h +15 -0
  23. data/ext/puma_http11/extconf.rb +5 -0
  24. data/ext/puma_http11/http11_parser.c +1225 -0
  25. data/ext/puma_http11/http11_parser.h +63 -0
  26. data/ext/puma_http11/http11_parser.java.rl +159 -0
  27. data/ext/puma_http11/http11_parser.rl +146 -0
  28. data/ext/puma_http11/http11_parser_common.rl +54 -0
  29. data/ext/puma_http11/org/jruby/mongrel/Http11.java +241 -0
  30. data/ext/puma_http11/org/jruby/mongrel/Http11Parser.java +486 -0
  31. data/ext/puma_http11/puma_http11.c +482 -0
  32. data/lib/puma.rb +18 -0
  33. data/lib/puma/cli.rb +131 -0
  34. data/lib/puma/const.rb +132 -0
  35. data/lib/puma/events.rb +36 -0
  36. data/lib/puma/gems.rb +20 -0
  37. data/lib/puma/mime_types.yml +616 -0
  38. data/lib/puma/server.rb +419 -0
  39. data/lib/puma/thread_pool.rb +95 -0
  40. data/lib/puma/utils.rb +44 -0
  41. data/lib/rack/handler/puma.rb +33 -0
  42. data/puma.gemspec +37 -0
  43. data/tasks/gem.rake +22 -0
  44. data/tasks/java.rake +12 -0
  45. data/tasks/native.rake +25 -0
  46. data/tasks/ragel.rake +20 -0
  47. data/test/lobster.ru +4 -0
  48. data/test/mime.yaml +3 -0
  49. data/test/test_http10.rb +27 -0
  50. data/test/test_http11.rb +151 -0
  51. data/test/test_persistent.rb +159 -0
  52. data/test/test_rack_handler.rb +10 -0
  53. data/test/test_rack_server.rb +107 -0
  54. data/test/test_thread_pool.rb +102 -0
  55. data/test/test_unix_socket.rb +34 -0
  56. data/test/test_ws.rb +97 -0
  57. data/test/testhelp.rb +41 -0
  58. data/tools/trickletest.rb +45 -0
  59. metadata +165 -0
@@ -0,0 +1,10 @@
1
+ require 'test/unit'
2
+
3
+ class TestPumaUnixSocket < Test::Unit::TestCase
4
+ def test_handler
5
+ handler = Rack::Handler.get(:puma)
6
+ assert_equal Rack::Handler::Puma, handler
7
+ handler = Rack::Handler.get('Puma')
8
+ assert_equal Rack::Handler::Puma, handler
9
+ end
10
+ end
@@ -0,0 +1,107 @@
1
+ require 'test/unit'
2
+ require 'puma'
3
+ require 'rack/lint'
4
+ require 'test/testhelp'
5
+ require 'rack/commonlogger'
6
+ require 'puma/rack_patch'
7
+
8
+ class TestRackServer < Test::Unit::TestCase
9
+
10
+ class ErrorChecker
11
+ def initialize(app)
12
+ @app = app
13
+ @exception = nil
14
+ @env = nil
15
+ end
16
+
17
+ attr_reader :exception, :env
18
+
19
+ def call(env)
20
+ begin
21
+ @env = env
22
+ return @app.call(env)
23
+ rescue Exception => e
24
+ @exception = e
25
+
26
+ [
27
+ 500,
28
+ { "X-Exception" => e.message, "X-Exception-Class" => e.class.to_s },
29
+ ["Error detected"]
30
+ ]
31
+ end
32
+ end
33
+ end
34
+
35
+ class ServerLint < Rack::Lint
36
+ def call(env)
37
+ assert("No env given") { env }
38
+ check_env env
39
+
40
+ @app.call(env)
41
+ end
42
+ end
43
+
44
+ def setup
45
+ @valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
46
+
47
+ @simple = lambda { |env| [200, { "X-Header" => "Works" }, ["Hello"]] }
48
+ @server = Puma::Server.new @simple
49
+ @server.add_tcp_listener "127.0.0.1", 9998
50
+ end
51
+
52
+ def teardown
53
+ @server.stop(true)
54
+ end
55
+
56
+ def test_lint
57
+ @checker = ErrorChecker.new ServerLint.new(@simple)
58
+ @server.app = @checker
59
+
60
+ @server.run
61
+
62
+ hit(['http://localhost:9998/test'])
63
+
64
+ if exc = @checker.exception
65
+ raise exc
66
+ end
67
+ end
68
+
69
+ def test_path_info
70
+ input = nil
71
+ @server.app = lambda { |env| input = env; @simple.call(env) }
72
+ @server.run
73
+
74
+ hit(['http://localhost:9998/test/a/b/c'])
75
+
76
+ assert_equal "/test/a/b/c", input['PATH_INFO']
77
+ end
78
+
79
+ def test_after_reply
80
+ closed = false
81
+
82
+ @server.app = lambda do |env|
83
+ env['rack.after_reply'] << lambda { closed = true }
84
+ @simple.call(env)
85
+ end
86
+
87
+ @server.run
88
+
89
+ hit(['http://localhost:9998/test'])
90
+
91
+ assert_equal true, closed
92
+ end
93
+
94
+ def test_common_logger
95
+ log = StringIO.new
96
+
97
+ logger = Rack::CommonLogger.new(@simple, log)
98
+
99
+ @server.app = logger
100
+
101
+ @server.run
102
+
103
+ hit(['http://localhost:9998/test'])
104
+
105
+ assert_match %r!GET /test HTTP/1\.1!, log.string
106
+ end
107
+ end
@@ -0,0 +1,102 @@
1
+ require 'test/unit'
2
+
3
+ require 'puma/thread_pool'
4
+
5
+ class TestThreadPool < Test::Unit::TestCase
6
+
7
+ def teardown
8
+ @pool.shutdown if @pool
9
+ end
10
+
11
+ def new_pool(min, max, &blk)
12
+ blk = proc { } unless blk
13
+ @pool = Puma::ThreadPool.new(min, max, &blk)
14
+ end
15
+
16
+ def pause
17
+ sleep 0.2
18
+ end
19
+
20
+ def test_append_spawns
21
+ saw = []
22
+
23
+ pool = new_pool(0, 1) do |work|
24
+ saw << work
25
+ end
26
+
27
+ pool << 1
28
+
29
+ pause
30
+
31
+ assert_equal [1], saw
32
+ assert_equal 1, pool.spawned
33
+ end
34
+
35
+ def test_append_queues_on_max
36
+ finish = false
37
+ pool = new_pool(0, 1) { Thread.pass until finish }
38
+
39
+ pool << 1
40
+ pool << 2
41
+ pool << 3
42
+
43
+ pause
44
+
45
+ assert_equal 2, pool.backlog
46
+
47
+ finish = true
48
+ end
49
+
50
+ def test_trim
51
+ pool = new_pool(0, 1)
52
+
53
+ pool << 1
54
+
55
+ pause
56
+
57
+ assert_equal 1, pool.spawned
58
+ pool.trim
59
+
60
+ pause
61
+ assert_equal 0, pool.spawned
62
+ end
63
+
64
+ def test_trim_leaves_min
65
+ finish = false
66
+ pool = new_pool(1, 2) { Thread.pass until finish }
67
+
68
+ pool << 1
69
+ pool << 2
70
+
71
+ finish = true
72
+
73
+ assert_equal 2, pool.spawned
74
+ pool.trim
75
+ pause
76
+
77
+ assert_equal 1, pool.spawned
78
+ pool.trim
79
+ pause
80
+
81
+ assert_equal 1, pool.spawned
82
+
83
+ end
84
+
85
+ def test_trim_doesnt_overtrim
86
+ finish = false
87
+ pool = new_pool(1, 2) { Thread.pass until finish }
88
+
89
+ pool << 1
90
+ pool << 2
91
+
92
+ assert_equal 2, pool.spawned
93
+ pool.trim
94
+ pool.trim
95
+
96
+ finish = true
97
+
98
+ pause
99
+
100
+ assert_equal 1, pool.spawned
101
+ end
102
+ end
@@ -0,0 +1,34 @@
1
+ require 'test/unit'
2
+ require 'puma/server'
3
+
4
+ require 'socket'
5
+
6
+ class TestPumaUnixSocket < Test::Unit::TestCase
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.exists? 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\nConnection: close\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
@@ -0,0 +1,97 @@
1
+ # Copyright (c) 2011 Evan Phoenix
2
+ # Copyright (c) 2005 Zed A. Shaw
3
+
4
+ require 'test/testhelp'
5
+
6
+ include Puma
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 < Test::Unit::TestCase
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 = Server.new @tester, Events.strings
26
+ @server.add_tcp_listener "127.0.0.1", 9998
27
+
28
+ redirect_test_io do
29
+ @server.run
30
+ end
31
+ end
32
+
33
+ def teardown
34
+ redirect_test_io do
35
+ @server.stop(true)
36
+ end
37
+ end
38
+
39
+ def test_simple_server
40
+ hit(['http://localhost:9998/test'])
41
+ assert @tester.ran_test, "Handler didn't really run"
42
+ end
43
+
44
+
45
+ def do_test(string, chunk, close_after=nil, shutdown_delay=0)
46
+ # Do not use instance variables here, because it needs to be thread safe
47
+ socket = TCPSocket.new("127.0.0.1", 9998);
48
+ request = StringIO.new(string)
49
+ chunks_out = 0
50
+
51
+ while data = request.read(chunk)
52
+ chunks_out += socket.write(data)
53
+ socket.flush
54
+ sleep 0.2
55
+ if close_after and chunks_out > close_after
56
+ socket.close
57
+ sleep 1
58
+ end
59
+ end
60
+ sleep(shutdown_delay)
61
+ socket.write(" ") # Some platforms only raise the exception on attempted write
62
+ socket.flush
63
+ end
64
+
65
+ def test_trickle_attack
66
+ do_test(@valid_request, 3)
67
+ end
68
+
69
+ def test_close_client
70
+ assert_raises IOError do
71
+ do_test(@valid_request, 10, 20)
72
+ end
73
+ end
74
+
75
+ def test_bad_client
76
+ redirect_test_io do
77
+ do_test("GET /test HTTP/BAD", 3)
78
+ end
79
+ end
80
+
81
+ def test_header_is_too_long
82
+ redirect_test_io do
83
+ long = "GET /test HTTP/1.1\r\n" + ("X-Big: stuff\r\n" * 15000) + "\r\n"
84
+ assert_raises Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED, Errno::EINVAL, IOError do
85
+ do_test(long, long.length/2, 10)
86
+ end
87
+ end
88
+ end
89
+
90
+ def test_file_streamed_request
91
+ body = "a" * (Puma::Const::MAX_BODY * 2)
92
+ long = "GET /test HTTP/1.1\r\nContent-length: #{body.length}\r\n\r\n" + body
93
+ do_test(long, Puma::Const::CHUNK_SIZE * 2 -400)
94
+ end
95
+
96
+ end
97
+
@@ -0,0 +1,41 @@
1
+ # Copyright (c) 2011 Evan Phoenix
2
+ # Copyright (c) 2005 Zed A. Shaw
3
+
4
+
5
+ %w(lib ext bin test).each do |dir|
6
+ $LOAD_PATH.unshift File.expand_path("../../#{dir}", __FILE__)
7
+ end
8
+
9
+ require 'rubygems'
10
+ require 'test/unit'
11
+ require 'net/http'
12
+ require 'digest/sha1'
13
+ require 'uri'
14
+ require 'stringio'
15
+
16
+ require 'puma'
17
+
18
+ def redirect_test_io
19
+ yield
20
+ end
21
+
22
+ # Either takes a string to do a get request against, or a tuple of [URI, HTTP] where
23
+ # HTTP is some kind of Net::HTTP request object (POST, HEAD, etc.)
24
+ def hit(uris)
25
+ results = []
26
+ uris.each do |u|
27
+ res = nil
28
+
29
+ if u.kind_of? String
30
+ res = Net::HTTP.get(URI.parse(u))
31
+ else
32
+ url = URI.parse(u[0])
33
+ res = Net::HTTP.new(url.host, url.port).start {|h| h.request(u[1]) }
34
+ end
35
+
36
+ assert res != nil, "Didn't get a response: #{u}"
37
+ results << res
38
+ end
39
+
40
+ return results
41
+ end
@@ -0,0 +1,45 @@
1
+ require 'socket'
2
+ require 'stringio'
3
+
4
+ def do_test(st, chunk)
5
+ s = TCPSocket.new('127.0.0.1',ARGV[0].to_i);
6
+ req = StringIO.new(st)
7
+ nout = 0
8
+ randstop = rand(st.length / 10)
9
+ STDERR.puts "stopping after: #{randstop}"
10
+
11
+ begin
12
+ while data = req.read(chunk)
13
+ nout += s.write(data)
14
+ s.flush
15
+ sleep 0.1
16
+ if nout > randstop
17
+ STDERR.puts "BANG! after #{nout} bytes."
18
+ break
19
+ end
20
+ end
21
+ rescue Object => e
22
+ STDERR.puts "ERROR: #{e}"
23
+ ensure
24
+ s.close
25
+ end
26
+ end
27
+
28
+ content = "-" * (1024 * 240)
29
+ st = "GET / HTTP/1.1\r\nHost: www.zedshaw.com\r\nContent-Type: text/plain\r\nContent-Length: #{content.length}\r\n\r\n#{content}"
30
+
31
+ puts "length: #{content.length}"
32
+
33
+ threads = []
34
+ ARGV[1].to_i.times do
35
+ t = Thread.new do
36
+ size = 100
37
+ puts ">>>> #{size} sized chunks"
38
+ do_test(st, size)
39
+ end
40
+
41
+ t.abort_on_exception = true
42
+ threads << t
43
+ end
44
+
45
+ threads.each {|t| t.join}
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: puma
3
+ version: !ruby/object:Gem::Version
4
+ hash: 63
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 8
9
+ - 0
10
+ version: 0.8.0
11
+ platform: ruby
12
+ authors:
13
+ - Evan Phoenix
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-10-25 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rake-compiler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ - 7
32
+ - 0
33
+ version: 0.7.0
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: hoe
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 23
45
+ segments:
46
+ - 2
47
+ - 10
48
+ version: "2.10"
49
+ type: :development
50
+ version_requirements: *id002
51
+ description: |-
52
+ Puma is a small library that provides a very fast and concurrent HTTP 1.1 server for Ruby web applications. It is designed for running rack apps only.
53
+
54
+ What makes Puma so fast is the careful use of an Ragel extension to provide fast, accurate HTTP 1.1 protocol parsing. This makes the server scream without too many portability issues.
55
+ email:
56
+ - evan@phx.io
57
+ executables:
58
+ - puma
59
+ extensions:
60
+ - ext/puma_http11/extconf.rb
61
+ extra_rdoc_files:
62
+ - History.txt
63
+ - Manifest.txt
64
+ files:
65
+ - COPYING
66
+ - History.txt
67
+ - LICENSE
68
+ - Manifest.txt
69
+ - README.md
70
+ - Rakefile
71
+ - TODO
72
+ - bin/puma
73
+ - examples/builder.rb
74
+ - examples/camping/README
75
+ - examples/camping/blog.rb
76
+ - examples/camping/tepee.rb
77
+ - examples/httpd.conf
78
+ - examples/mime.yaml
79
+ - examples/mongrel.conf
80
+ - examples/monitrc
81
+ - examples/random_thrash.rb
82
+ - examples/simpletest.rb
83
+ - examples/webrick_compare.rb
84
+ - ext/puma_http11/Http11Service.java
85
+ - ext/puma_http11/ext_help.h
86
+ - ext/puma_http11/extconf.rb
87
+ - ext/puma_http11/puma_http11.c
88
+ - ext/puma_http11/http11_parser.c
89
+ - ext/puma_http11/http11_parser.h
90
+ - ext/puma_http11/http11_parser.java.rl
91
+ - ext/puma_http11/http11_parser.rl
92
+ - ext/puma_http11/http11_parser_common.rl
93
+ - ext/puma_http11/org/jruby/mongrel/Http11.java
94
+ - ext/puma_http11/org/jruby/mongrel/Http11Parser.java
95
+ - lib/puma.rb
96
+ - lib/puma/cli.rb
97
+ - lib/puma/const.rb
98
+ - lib/puma/events.rb
99
+ - lib/puma/gems.rb
100
+ - lib/puma/mime_types.yml
101
+ - lib/puma/server.rb
102
+ - lib/puma/thread_pool.rb
103
+ - lib/puma/utils.rb
104
+ - lib/rack/handler/puma.rb
105
+ - puma.gemspec
106
+ - tasks/gem.rake
107
+ - tasks/java.rake
108
+ - tasks/native.rake
109
+ - tasks/ragel.rake
110
+ - test/lobster.ru
111
+ - test/mime.yaml
112
+ - test/test_http10.rb
113
+ - test/test_http11.rb
114
+ - test/test_persistent.rb
115
+ - test/test_rack_handler.rb
116
+ - test/test_rack_server.rb
117
+ - test/test_thread_pool.rb
118
+ - test/test_unix_socket.rb
119
+ - test/test_ws.rb
120
+ - test/testhelp.rb
121
+ - tools/trickletest.rb
122
+ - .gemtest
123
+ homepage:
124
+ licenses: []
125
+
126
+ post_install_message:
127
+ rdoc_options:
128
+ - --main
129
+ - README.md
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ hash: 3
138
+ segments:
139
+ - 0
140
+ version: "0"
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ hash: 3
147
+ segments:
148
+ - 0
149
+ version: "0"
150
+ requirements: []
151
+
152
+ rubyforge_project: puma
153
+ rubygems_version: 1.8.10
154
+ signing_key:
155
+ specification_version: 3
156
+ summary: Puma is a small library that provides a very fast and concurrent HTTP 1.1 server for Ruby web applications
157
+ test_files:
158
+ - test/test_http10.rb
159
+ - test/test_http11.rb
160
+ - test/test_persistent.rb
161
+ - test/test_rack_handler.rb
162
+ - test/test_rack_server.rb
163
+ - test/test_thread_pool.rb
164
+ - test/test_unix_socket.rb
165
+ - test/test_ws.rb