puma 2.7.0 → 3.1.1
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.
- checksums.yaml +5 -13
- data/DEPLOYMENT.md +91 -0
- data/Gemfile +3 -2
- data/History.txt +624 -1
- data/Manifest.txt +15 -3
- data/README.md +129 -14
- data/Rakefile +3 -3
- data/bin/puma-wild +31 -0
- data/bin/pumactl +1 -1
- data/docs/nginx.md +1 -1
- data/docs/signals.md +43 -0
- data/ext/puma_http11/extconf.rb +7 -2
- data/ext/puma_http11/http11_parser.java.rl +5 -5
- data/ext/puma_http11/io_buffer.c +1 -1
- data/ext/puma_http11/mini_ssl.c +233 -18
- data/ext/puma_http11/org/jruby/puma/Http11.java +12 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +39 -39
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +245 -195
- data/ext/puma_http11/puma_http11.c +12 -4
- data/lib/puma.rb +1 -0
- data/lib/puma/app/status.rb +7 -0
- data/lib/puma/binder.rb +108 -39
- data/lib/puma/capistrano.rb +23 -6
- data/lib/puma/cli.rb +141 -446
- data/lib/puma/client.rb +48 -1
- data/lib/puma/cluster.rb +207 -58
- data/lib/puma/commonlogger.rb +107 -0
- data/lib/puma/configuration.rb +262 -235
- data/lib/puma/const.rb +97 -14
- data/lib/puma/control_cli.rb +85 -77
- data/lib/puma/convenient.rb +23 -0
- data/lib/puma/daemon_ext.rb +11 -4
- data/lib/puma/detect.rb +8 -1
- data/lib/puma/dsl.rb +456 -0
- data/lib/puma/events.rb +35 -18
- data/lib/puma/jruby_restart.rb +1 -1
- data/lib/puma/launcher.rb +399 -0
- data/lib/puma/minissl.rb +49 -20
- data/lib/puma/null_io.rb +15 -0
- data/lib/puma/plugin.rb +104 -0
- data/lib/puma/plugin/tmp_restart.rb +35 -0
- data/lib/puma/rack/backports/uri/common_18.rb +56 -0
- data/lib/puma/rack/backports/uri/common_192.rb +52 -0
- data/lib/puma/rack/backports/uri/common_193.rb +29 -0
- data/lib/puma/rack/builder.rb +295 -0
- data/lib/puma/rack/urlmap.rb +90 -0
- data/lib/puma/reactor.rb +14 -1
- data/lib/puma/runner.rb +35 -17
- data/lib/puma/server.rb +161 -58
- data/lib/puma/single.rb +15 -10
- data/lib/puma/state_file.rb +29 -0
- data/lib/puma/thread_pool.rb +88 -13
- data/lib/puma/util.rb +123 -0
- data/lib/rack/handler/puma.rb +35 -29
- data/puma.gemspec +2 -4
- data/tools/jungle/init.d/README.md +2 -2
- data/tools/jungle/init.d/puma +69 -7
- data/tools/jungle/upstart/puma.conf +8 -2
- metadata +51 -71
- data/COPYING +0 -55
- data/TODO +0 -5
- data/lib/puma/rack_patch.rb +0 -45
- data/test/test_app_status.rb +0 -92
- data/test/test_cli.rb +0 -173
- data/test/test_config.rb +0 -16
- data/test/test_http10.rb +0 -27
- data/test/test_http11.rb +0 -145
- data/test/test_integration.rb +0 -165
- data/test/test_iobuffer.rb +0 -38
- data/test/test_minissl.rb +0 -25
- data/test/test_null_io.rb +0 -31
- data/test/test_persistent.rb +0 -238
- data/test/test_puma_server.rb +0 -292
- data/test/test_rack_handler.rb +0 -10
- data/test/test_rack_server.rb +0 -141
- data/test/test_tcp_rack.rb +0 -42
- data/test/test_thread_pool.rb +0 -156
- data/test/test_unix_socket.rb +0 -39
- data/test/test_ws.rb +0 -89
data/COPYING
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw
|
2
|
-
<zedshaw at zedshaw dot com> You can redistribute it and/or modify it under
|
3
|
-
either the terms of the GPL or the conditions below:
|
4
|
-
|
5
|
-
1. You may make and give away verbatim copies of the source form of the
|
6
|
-
software without restriction, provided that you duplicate all of the
|
7
|
-
original copyright notices and associated disclaimers.
|
8
|
-
|
9
|
-
2. You may modify your copy of the software in any way, provided that
|
10
|
-
you do at least ONE of the following:
|
11
|
-
|
12
|
-
a) place your modifications in the Public Domain or otherwise make them
|
13
|
-
Freely Available, such as by posting said modifications to Usenet or an
|
14
|
-
equivalent medium, or by allowing the author to include your
|
15
|
-
modifications in the software.
|
16
|
-
|
17
|
-
b) use the modified software only within your corporation or
|
18
|
-
organization.
|
19
|
-
|
20
|
-
c) rename any non-standard executables so the names do not conflict with
|
21
|
-
standard executables, which must also be provided.
|
22
|
-
|
23
|
-
d) make other distribution arrangements with the author.
|
24
|
-
|
25
|
-
3. You may distribute the software in object code or executable
|
26
|
-
form, provided that you do at least ONE of the following:
|
27
|
-
|
28
|
-
a) distribute the executables and library files of the software,
|
29
|
-
together with instructions (in the manual page or equivalent) on where
|
30
|
-
to get the original distribution.
|
31
|
-
|
32
|
-
b) accompany the distribution with the machine-readable source of the
|
33
|
-
software.
|
34
|
-
|
35
|
-
c) give non-standard executables non-standard names, with
|
36
|
-
instructions on where to get the original software distribution.
|
37
|
-
|
38
|
-
d) make other distribution arrangements with the author.
|
39
|
-
|
40
|
-
4. You may modify and include the part of the software into any other
|
41
|
-
software (possibly commercial). But some files in the distribution
|
42
|
-
are not written by the author, so that they are not under this terms.
|
43
|
-
|
44
|
-
5. The scripts and library files supplied as input to or produced as
|
45
|
-
output from the software do not automatically fall under the
|
46
|
-
copyright of the software, but belong to whomever generated them,
|
47
|
-
and may be sold commercially, and may be aggregated with this
|
48
|
-
software.
|
49
|
-
|
50
|
-
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
51
|
-
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
52
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
53
|
-
PURPOSE.
|
54
|
-
|
55
|
-
|
data/TODO
DELETED
data/lib/puma/rack_patch.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'rack/commonlogger'
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
# Patch CommonLogger to use after_reply.
|
5
|
-
#
|
6
|
-
# Simply request this file and CommonLogger will be a bit more
|
7
|
-
# efficient.
|
8
|
-
class CommonLogger
|
9
|
-
remove_method :call
|
10
|
-
|
11
|
-
def call(env)
|
12
|
-
began_at = Time.now
|
13
|
-
status, header, body = @app.call(env)
|
14
|
-
header = Utils::HeaderHash.new(header)
|
15
|
-
|
16
|
-
# If we've been hijacked, then output a special line
|
17
|
-
if env['rack.hijack_io']
|
18
|
-
log_hijacking(env, 'HIJACK', header, began_at)
|
19
|
-
elsif ary = env['rack.after_reply']
|
20
|
-
ary << lambda { log(env, status, header, began_at) }
|
21
|
-
else
|
22
|
-
body = BodyProxy.new(body) { log(env, status, header, began_at) }
|
23
|
-
end
|
24
|
-
|
25
|
-
[status, header, body]
|
26
|
-
end
|
27
|
-
|
28
|
-
HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
|
29
|
-
|
30
|
-
def log_hijacking(env, status, header, began_at)
|
31
|
-
now = Time.now
|
32
|
-
|
33
|
-
logger = @logger || env['rack.errors']
|
34
|
-
logger.write HIJACK_FORMAT % [
|
35
|
-
env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
|
36
|
-
env["REMOTE_USER"] || "-",
|
37
|
-
now.strftime("%d/%b/%Y %H:%M:%S"),
|
38
|
-
env["REQUEST_METHOD"],
|
39
|
-
env["PATH_INFO"],
|
40
|
-
env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
|
41
|
-
env["HTTP_VERSION"],
|
42
|
-
now - began_at ]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/test/test_app_status.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rack'
|
3
|
-
require 'puma/app/status'
|
4
|
-
|
5
|
-
class TestAppStatus < Test::Unit::TestCase
|
6
|
-
class FakeServer
|
7
|
-
def initialize
|
8
|
-
@status = :running
|
9
|
-
@backlog = 0
|
10
|
-
@running = 0
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :status
|
14
|
-
attr_accessor :backlog, :running
|
15
|
-
|
16
|
-
def stop
|
17
|
-
@status = :stop
|
18
|
-
end
|
19
|
-
|
20
|
-
def halt
|
21
|
-
@status = :halt
|
22
|
-
end
|
23
|
-
|
24
|
-
def stats
|
25
|
-
"{}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def setup
|
30
|
-
@server = FakeServer.new
|
31
|
-
@app = Puma::App::Status.new(@server)
|
32
|
-
@app.auth_token = nil
|
33
|
-
end
|
34
|
-
|
35
|
-
def lint(uri)
|
36
|
-
app = Rack::Lint.new @app
|
37
|
-
mock_env = Rack::MockRequest.env_for uri
|
38
|
-
app.call mock_env
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_bad_token
|
42
|
-
@app.auth_token = "abcdef"
|
43
|
-
|
44
|
-
status, _, _ = lint('/whatever')
|
45
|
-
|
46
|
-
assert_equal 403, status
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_good_token
|
50
|
-
@app.auth_token = "abcdef"
|
51
|
-
|
52
|
-
status, _, _ = lint('/whatever?token=abcdef')
|
53
|
-
|
54
|
-
assert_equal 404, status
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_unsupported
|
58
|
-
status, _, _ = lint('/not-real')
|
59
|
-
|
60
|
-
assert_equal 404, status
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_stop
|
64
|
-
status, _ , app = lint('/stop')
|
65
|
-
|
66
|
-
assert_equal :stop, @server.status
|
67
|
-
assert_equal 200, status
|
68
|
-
assert_equal ['{ "status": "ok" }'], app.enum_for.to_a
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_halt
|
72
|
-
status, _ , app = lint('/halt')
|
73
|
-
|
74
|
-
assert_equal :halt, @server.status
|
75
|
-
assert_equal 200, status
|
76
|
-
assert_equal ['{ "status": "ok" }'], app.enum_for.to_a
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_stats
|
80
|
-
@server.backlog = 1
|
81
|
-
@server.running = 9
|
82
|
-
status, _ , app = lint('/stats')
|
83
|
-
|
84
|
-
assert_equal 200, status
|
85
|
-
assert_equal ['{}'], app.enum_for.to_a
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_alternate_location
|
89
|
-
status, _ , _ = lint('__alternatE_location_/stats')
|
90
|
-
assert_equal 200, status
|
91
|
-
end
|
92
|
-
end
|
data/test/test_cli.rb
DELETED
@@ -1,173 +0,0 @@
|
|
1
|
-
require "rbconfig"
|
2
|
-
require 'test/unit'
|
3
|
-
require 'puma/cli'
|
4
|
-
require 'tempfile'
|
5
|
-
|
6
|
-
class TestCLI < Test::Unit::TestCase
|
7
|
-
def setup
|
8
|
-
@environment = 'production'
|
9
|
-
@tmp_file = Tempfile.new("puma-test")
|
10
|
-
@tmp_path = @tmp_file.path
|
11
|
-
@tmp_file.close!
|
12
|
-
|
13
|
-
@tmp_path2 = "#{@tmp_path}2"
|
14
|
-
|
15
|
-
File.unlink @tmp_path if File.exist? @tmp_path
|
16
|
-
File.unlink @tmp_path2 if File.exist? @tmp_path2
|
17
|
-
|
18
|
-
@wait, @ready = IO.pipe
|
19
|
-
|
20
|
-
@events = Events.strings
|
21
|
-
@events.on_booted { @ready << "!" }
|
22
|
-
end
|
23
|
-
|
24
|
-
def wait_booted
|
25
|
-
@wait.sysread 1
|
26
|
-
end
|
27
|
-
|
28
|
-
def teardown
|
29
|
-
File.unlink @tmp_path if File.exist? @tmp_path
|
30
|
-
File.unlink @tmp_path2 if File.exist? @tmp_path2
|
31
|
-
|
32
|
-
@wait.close
|
33
|
-
@ready.close
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_pid_file
|
37
|
-
cli = Puma::CLI.new ["--pidfile", @tmp_path]
|
38
|
-
cli.parse_options
|
39
|
-
cli.write_pid
|
40
|
-
|
41
|
-
assert_equal File.read(@tmp_path).strip.to_i, Process.pid
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_control_for_tcp
|
45
|
-
url = "tcp://127.0.0.1:9877/"
|
46
|
-
cli = Puma::CLI.new ["-b", "tcp://127.0.0.1:9876",
|
47
|
-
"--control", url,
|
48
|
-
"--control-token", "",
|
49
|
-
"test/lobster.ru"], @events
|
50
|
-
|
51
|
-
cli.parse_options
|
52
|
-
|
53
|
-
thread_exception = nil
|
54
|
-
t = Thread.new do
|
55
|
-
begin
|
56
|
-
cli.run
|
57
|
-
rescue Exception => e
|
58
|
-
thread_exception = e
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
wait_booted
|
63
|
-
|
64
|
-
s = TCPSocket.new "127.0.0.1", 9877
|
65
|
-
s << "GET /stats HTTP/1.0\r\n\r\n"
|
66
|
-
body = s.read
|
67
|
-
assert_equal '{ "backlog": 0, "running": 0 }', body.split("\r\n").last
|
68
|
-
|
69
|
-
cli.stop
|
70
|
-
t.join
|
71
|
-
assert_equal nil, thread_exception
|
72
|
-
end
|
73
|
-
|
74
|
-
unless defined?(JRUBY_VERSION) || RbConfig::CONFIG["host_os"] =~ /mingw|mswin/
|
75
|
-
def test_control
|
76
|
-
url = "unix://#{@tmp_path}"
|
77
|
-
|
78
|
-
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
|
79
|
-
"--control", url,
|
80
|
-
"--control-token", "",
|
81
|
-
"test/lobster.ru"], @events
|
82
|
-
cli.parse_options
|
83
|
-
|
84
|
-
t = Thread.new { cli.run }
|
85
|
-
|
86
|
-
wait_booted
|
87
|
-
|
88
|
-
s = UNIXSocket.new @tmp_path
|
89
|
-
s << "GET /stats HTTP/1.0\r\n\r\n"
|
90
|
-
body = s.read
|
91
|
-
|
92
|
-
assert_equal '{ "backlog": 0, "running": 0 }', body.split("\r\n").last
|
93
|
-
|
94
|
-
cli.stop
|
95
|
-
t.join
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_control_stop
|
99
|
-
url = "unix://#{@tmp_path}"
|
100
|
-
|
101
|
-
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
|
102
|
-
"--control", url,
|
103
|
-
"--control-token", "",
|
104
|
-
"test/lobster.ru"], @events
|
105
|
-
cli.parse_options
|
106
|
-
|
107
|
-
t = Thread.new { cli.run }
|
108
|
-
|
109
|
-
wait_booted
|
110
|
-
|
111
|
-
s = UNIXSocket.new @tmp_path
|
112
|
-
s << "GET /stop HTTP/1.0\r\n\r\n"
|
113
|
-
body = s.read
|
114
|
-
|
115
|
-
assert_equal '{ "status": "ok" }', body.split("\r\n").last
|
116
|
-
|
117
|
-
t.join
|
118
|
-
end
|
119
|
-
|
120
|
-
def test_tmp_control
|
121
|
-
url = "tcp://127.0.0.1:8232"
|
122
|
-
cli = Puma::CLI.new ["--state", @tmp_path, "--control", "auto"]
|
123
|
-
cli.parse_options
|
124
|
-
cli.write_state
|
125
|
-
|
126
|
-
data = YAML.load File.read(@tmp_path)
|
127
|
-
|
128
|
-
assert_equal Process.pid, data["pid"]
|
129
|
-
|
130
|
-
url = data["config"].options[:control_url]
|
131
|
-
|
132
|
-
m = %r!unix://(.*)!.match(url)
|
133
|
-
|
134
|
-
assert m, "'#{url}' is not a URL"
|
135
|
-
end
|
136
|
-
end # JRUBY or Windows
|
137
|
-
|
138
|
-
def test_state
|
139
|
-
url = "tcp://127.0.0.1:8232"
|
140
|
-
cli = Puma::CLI.new ["--state", @tmp_path, "--control", url]
|
141
|
-
cli.parse_options
|
142
|
-
cli.write_state
|
143
|
-
|
144
|
-
data = YAML.load File.read(@tmp_path)
|
145
|
-
|
146
|
-
assert_equal Process.pid, data["pid"]
|
147
|
-
assert_equal url, data["config"].options[:control_url]
|
148
|
-
end
|
149
|
-
|
150
|
-
def test_load_path
|
151
|
-
cli = Puma::CLI.new ["--include", 'foo/bar']
|
152
|
-
cli.parse_options
|
153
|
-
|
154
|
-
assert_equal 'foo/bar', $LOAD_PATH[0]
|
155
|
-
$LOAD_PATH.shift
|
156
|
-
|
157
|
-
cli = Puma::CLI.new ["--include", 'foo/bar:baz/qux']
|
158
|
-
cli.parse_options
|
159
|
-
|
160
|
-
assert_equal 'foo/bar', $LOAD_PATH[0]
|
161
|
-
$LOAD_PATH.shift
|
162
|
-
assert_equal 'baz/qux', $LOAD_PATH[0]
|
163
|
-
$LOAD_PATH.shift
|
164
|
-
end
|
165
|
-
|
166
|
-
def test_environment
|
167
|
-
cli = Puma::CLI.new ["--environment", @environment]
|
168
|
-
cli.parse_options
|
169
|
-
cli.set_rack_environment
|
170
|
-
|
171
|
-
assert_equal ENV['RACK_ENV'], @environment
|
172
|
-
end
|
173
|
-
end
|
data/test/test_config.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
|
3
|
-
require 'puma'
|
4
|
-
require 'puma/configuration'
|
5
|
-
|
6
|
-
class TestConfigFile < Test::Unit::TestCase
|
7
|
-
def test_app_from_app_DSL
|
8
|
-
opts = { :config_file => "test/config/app.rb" }
|
9
|
-
conf = Puma::Configuration.new opts
|
10
|
-
conf.load
|
11
|
-
|
12
|
-
app = conf.app
|
13
|
-
|
14
|
-
assert_equal [200, {}, ["embedded app"]], app.call({})
|
15
|
-
end
|
16
|
-
end
|
data/test/test_http10.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'test/testhelp'
|
2
|
-
|
3
|
-
class Http10ParserTest < Test::Unit::TestCase
|
4
|
-
include Puma
|
5
|
-
|
6
|
-
def test_parse_simple
|
7
|
-
parser = HttpParser.new
|
8
|
-
req = {}
|
9
|
-
http = "GET / HTTP/1.0\r\n\r\n"
|
10
|
-
nread = parser.execute(req, http, 0)
|
11
|
-
|
12
|
-
assert nread == http.length, "Failed to parse the full HTTP request"
|
13
|
-
assert parser.finished?, "Parser didn't finish"
|
14
|
-
assert !parser.error?, "Parser had error"
|
15
|
-
assert nread == parser.nread, "Number read returned from execute does not match"
|
16
|
-
|
17
|
-
assert_equal '/', req['REQUEST_PATH']
|
18
|
-
assert_equal 'HTTP/1.0', req['HTTP_VERSION']
|
19
|
-
assert_equal '/', req['REQUEST_URI']
|
20
|
-
assert_equal 'GET', req['REQUEST_METHOD']
|
21
|
-
assert_nil req['FRAGMENT']
|
22
|
-
assert_nil req['QUERY_STRING']
|
23
|
-
|
24
|
-
parser.reset
|
25
|
-
assert parser.nread == 0, "Number read after reset should be 0"
|
26
|
-
end
|
27
|
-
end
|
data/test/test_http11.rb
DELETED
@@ -1,145 +0,0 @@
|
|
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 Http11ParserTest < Test::Unit::TestCase
|
9
|
-
|
10
|
-
def test_parse_simple
|
11
|
-
parser = HttpParser.new
|
12
|
-
req = {}
|
13
|
-
http = "GET / HTTP/1.1\r\n\r\n"
|
14
|
-
nread = parser.execute(req, http, 0)
|
15
|
-
|
16
|
-
assert nread == http.length, "Failed to parse the full HTTP request"
|
17
|
-
assert parser.finished?, "Parser didn't finish"
|
18
|
-
assert !parser.error?, "Parser had error"
|
19
|
-
assert nread == parser.nread, "Number read returned from execute does not match"
|
20
|
-
|
21
|
-
assert_equal '/', req['REQUEST_PATH']
|
22
|
-
assert_equal 'HTTP/1.1', req['HTTP_VERSION']
|
23
|
-
assert_equal '/', req['REQUEST_URI']
|
24
|
-
assert_equal 'GET', req['REQUEST_METHOD']
|
25
|
-
assert_nil req['FRAGMENT']
|
26
|
-
assert_nil req['QUERY_STRING']
|
27
|
-
|
28
|
-
parser.reset
|
29
|
-
assert parser.nread == 0, "Number read after reset should be 0"
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_parse_dumbfuck_headers
|
33
|
-
parser = HttpParser.new
|
34
|
-
req = {}
|
35
|
-
should_be_good = "GET / HTTP/1.1\r\naaaaaaaaaaaaa:++++++++++\r\n\r\n"
|
36
|
-
nread = parser.execute(req, should_be_good, 0)
|
37
|
-
assert_equal should_be_good.length, nread
|
38
|
-
assert parser.finished?
|
39
|
-
assert !parser.error?
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_parse_error
|
43
|
-
parser = HttpParser.new
|
44
|
-
req = {}
|
45
|
-
bad_http = "GET / SsUTF/1.1"
|
46
|
-
|
47
|
-
error = false
|
48
|
-
begin
|
49
|
-
parser.execute(req, bad_http, 0)
|
50
|
-
rescue
|
51
|
-
error = true
|
52
|
-
end
|
53
|
-
|
54
|
-
assert error, "failed to throw exception"
|
55
|
-
assert !parser.finished?, "Parser shouldn't be finished"
|
56
|
-
assert parser.error?, "Parser SHOULD have error"
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_fragment_in_uri
|
60
|
-
parser = HttpParser.new
|
61
|
-
req = {}
|
62
|
-
get = "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n\r\n"
|
63
|
-
assert_nothing_raised do
|
64
|
-
parser.execute(req, get, 0)
|
65
|
-
end
|
66
|
-
assert parser.finished?
|
67
|
-
assert_equal '/forums/1/topics/2375?page=1', req['REQUEST_URI']
|
68
|
-
assert_equal 'posts-17408', req['FRAGMENT']
|
69
|
-
end
|
70
|
-
|
71
|
-
# lame random garbage maker
|
72
|
-
def rand_data(min, max, readable=true)
|
73
|
-
count = min + ((rand(max)+1) *10).to_i
|
74
|
-
res = count.to_s + "/"
|
75
|
-
|
76
|
-
if readable
|
77
|
-
res << Digest::SHA1.hexdigest(rand(count * 100).to_s) * (count / 40)
|
78
|
-
else
|
79
|
-
res << Digest::SHA1.digest(rand(count * 100).to_s) * (count / 20)
|
80
|
-
end
|
81
|
-
|
82
|
-
return res
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_max_uri_path_length
|
86
|
-
parser = HttpParser.new
|
87
|
-
req = {}
|
88
|
-
|
89
|
-
# Support URI path length to a max of 2048
|
90
|
-
path = "/" + rand_data(1000, 100)
|
91
|
-
http = "GET #{path} HTTP/1.1\r\n\r\n"
|
92
|
-
parser.execute(req, http, 0)
|
93
|
-
assert_equal path, req['REQUEST_PATH']
|
94
|
-
parser.reset
|
95
|
-
|
96
|
-
# Raise exception if URI path length > 2048
|
97
|
-
path = "/" + rand_data(2048, 100)
|
98
|
-
http = "GET #{path} HTTP/1.1\r\n\r\n"
|
99
|
-
assert_raises Puma::HttpParserError do
|
100
|
-
parser.execute(req, http, 0)
|
101
|
-
parser.reset
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_horrible_queries
|
106
|
-
parser = HttpParser.new
|
107
|
-
|
108
|
-
# then that large header names are caught
|
109
|
-
10.times do |c|
|
110
|
-
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
|
111
|
-
assert_raises Puma::HttpParserError do
|
112
|
-
parser.execute({}, get, 0)
|
113
|
-
parser.reset
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# then that large mangled field values are caught
|
118
|
-
10.times do |c|
|
119
|
-
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
120
|
-
assert_raises Puma::HttpParserError do
|
121
|
-
parser.execute({}, get, 0)
|
122
|
-
parser.reset
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# then large headers are rejected too
|
127
|
-
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
|
128
|
-
get << "X-Test: test\r\n" * (80 * 1024)
|
129
|
-
assert_raises Puma::HttpParserError do
|
130
|
-
parser.execute({}, get, 0)
|
131
|
-
parser.reset
|
132
|
-
end
|
133
|
-
|
134
|
-
# finally just that random garbage gets blocked all the time
|
135
|
-
10.times do |c|
|
136
|
-
get = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
137
|
-
assert_raises Puma::HttpParserError do
|
138
|
-
parser.execute({}, get, 0)
|
139
|
-
parser.reset
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|