puma 0.9.1 → 0.9.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/Manifest.txt +6 -1
- data/bin/pumactl +0 -0
- data/lib/puma/app/status.rb +12 -0
- data/lib/puma/cli.rb +18 -35
- data/lib/puma/configuration.rb +190 -0
- data/lib/puma/const.rb +1 -1
- data/lib/puma/control_cli.rb +32 -20
- data/lib/puma/server.rb +12 -3
- data/lib/rack/handler/puma.rb +2 -2
- data/puma.gemspec +10 -7
- data/test/config/app.rb +3 -0
- data/test/hello.ru +1 -0
- data/test/slow.ru +4 -0
- data/test/test_app_status.rb +28 -4
- data/test/test_cli.rb +8 -2
- data/test/test_config.rb +16 -0
- data/test/test_http11.rb +2 -10
- data/test/test_integration.rb +48 -0
- data/test/test_ws.rb +1 -1
- metadata +12 -5
- data/lib/puma/config.rb +0 -98
data/Manifest.txt
CHANGED
@@ -23,7 +23,7 @@ ext/puma_http11/puma_http11.c
|
|
23
23
|
lib/puma.rb
|
24
24
|
lib/puma/app/status.rb
|
25
25
|
lib/puma/cli.rb
|
26
|
-
lib/puma/
|
26
|
+
lib/puma/configuration.rb
|
27
27
|
lib/puma/const.rb
|
28
28
|
lib/puma/control_cli.rb
|
29
29
|
lib/puma/events.rb
|
@@ -35,12 +35,17 @@ lib/puma/thread_pool.rb
|
|
35
35
|
lib/rack/handler/puma.rb
|
36
36
|
puma.gemspec
|
37
37
|
test/ab_rs.rb
|
38
|
+
test/config/app.rb
|
39
|
+
test/hello.ru
|
38
40
|
test/lobster.ru
|
39
41
|
test/mime.yaml
|
42
|
+
test/slow.ru
|
40
43
|
test/test_app_status.rb
|
41
44
|
test/test_cli.rb
|
45
|
+
test/test_config.rb
|
42
46
|
test/test_http10.rb
|
43
47
|
test/test_http11.rb
|
48
|
+
test/test_integration.rb
|
44
49
|
test/test_persistent.rb
|
45
50
|
test/test_rack_handler.rb
|
46
51
|
test/test_rack_server.rb
|
data/bin/pumactl
CHANGED
File without changes
|
data/lib/puma/app/status.rb
CHANGED
@@ -4,9 +4,21 @@ module Puma
|
|
4
4
|
def initialize(server, cli)
|
5
5
|
@server = server
|
6
6
|
@cli = cli
|
7
|
+
@auth_token = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :auth_token
|
11
|
+
|
12
|
+
def authenticate(env)
|
13
|
+
return true unless @auth_token
|
14
|
+
env['QUERY_STRING'].to_s.split(/&;/).include?("token=#{@auth_token}")
|
7
15
|
end
|
8
16
|
|
9
17
|
def call(env)
|
18
|
+
unless authenticate(env)
|
19
|
+
return [403, {}, ["Invalid auth token"]]
|
20
|
+
end
|
21
|
+
|
10
22
|
case env['PATH_INFO']
|
11
23
|
when "/stop"
|
12
24
|
@server.stop
|
data/lib/puma/cli.rb
CHANGED
@@ -3,7 +3,7 @@ require 'uri'
|
|
3
3
|
|
4
4
|
require 'puma/server'
|
5
5
|
require 'puma/const'
|
6
|
-
require 'puma/
|
6
|
+
require 'puma/configuration'
|
7
7
|
|
8
8
|
require 'rack/commonlogger'
|
9
9
|
|
@@ -11,7 +11,6 @@ module Puma
|
|
11
11
|
# Handles invoke a Puma::Server in a command line style.
|
12
12
|
#
|
13
13
|
class CLI
|
14
|
-
DefaultRackup = "config.ru"
|
15
14
|
IS_JRUBY = defined?(JRUBY_VERSION)
|
16
15
|
|
17
16
|
# Create a new CLI object using +argv+ as the command line
|
@@ -142,6 +141,11 @@ module Puma
|
|
142
141
|
end
|
143
142
|
end
|
144
143
|
|
144
|
+
o.on "--control-token TOKEN",
|
145
|
+
"The token to use as authentication for the control server" do |arg|
|
146
|
+
@options[:control_auth_token] = arg
|
147
|
+
end
|
148
|
+
|
145
149
|
o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
|
146
150
|
min, max = arg.split(":")
|
147
151
|
if max
|
@@ -163,20 +167,6 @@ module Puma
|
|
163
167
|
end
|
164
168
|
end
|
165
169
|
|
166
|
-
# Load the specified rackup file, pull an options from
|
167
|
-
# the rackup file, and set @app.
|
168
|
-
#
|
169
|
-
def load_rackup
|
170
|
-
@app, options = Rack::Builder.parse_file @options[:rackup]
|
171
|
-
@options.merge! options
|
172
|
-
|
173
|
-
options.each do |key,val|
|
174
|
-
if key.to_s[0,4] == "bind"
|
175
|
-
@binds << val
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
170
|
# If configured, write the pid of the current process out
|
181
171
|
# to a file.
|
182
172
|
#
|
@@ -206,17 +196,14 @@ module Puma
|
|
206
196
|
def parse_options
|
207
197
|
@parser.parse! @argv
|
208
198
|
|
199
|
+
if @argv.last
|
200
|
+
@options[:rackup] = @argv.shift
|
201
|
+
end
|
202
|
+
|
209
203
|
@config = Puma::Configuration.new @options
|
210
204
|
@config.load
|
211
205
|
|
212
|
-
|
213
|
-
@options[:rackup] = @argv.shift || DefaultRackup
|
214
|
-
end
|
215
|
-
|
216
|
-
if @options[:control_url] == "auto"
|
217
|
-
path = @temp_status_path = Configuration.temp_path
|
218
|
-
@options[:control_url] = "unix://#{path}"
|
219
|
-
end
|
206
|
+
@temp_status_path = @options[:control_path_temp]
|
220
207
|
end
|
221
208
|
|
222
209
|
# Parse the options, load the rackup, start the server and wait
|
@@ -225,24 +212,15 @@ module Puma
|
|
225
212
|
def run
|
226
213
|
parse_options
|
227
214
|
|
228
|
-
|
229
|
-
|
230
|
-
unless File.exists?(rackup)
|
231
|
-
raise "Missing rackup file '#{rackup}'"
|
232
|
-
end
|
215
|
+
app = @config.app
|
233
216
|
|
234
|
-
load_rackup
|
235
217
|
write_pid
|
236
218
|
write_state
|
237
219
|
|
238
|
-
unless @options[:quiet]
|
239
|
-
@app = Rack::CommonLogger.new(@app, STDOUT)
|
240
|
-
end
|
241
|
-
|
242
220
|
min_t = @options[:min_threads]
|
243
221
|
max_t = @options[:max_threads]
|
244
222
|
|
245
|
-
server = Puma::Server.new
|
223
|
+
server = Puma::Server.new app, @events
|
246
224
|
server.min_threads = min_t
|
247
225
|
server.max_threads = max_t
|
248
226
|
|
@@ -273,6 +251,11 @@ module Puma
|
|
273
251
|
uri = URI.parse str
|
274
252
|
|
275
253
|
app = Puma::App::Status.new server, self
|
254
|
+
|
255
|
+
if token = @options[:control_auth_token]
|
256
|
+
app.auth_token = token unless token.empty? or token == :none
|
257
|
+
end
|
258
|
+
|
276
259
|
status = Puma::Server.new app, @events
|
277
260
|
status.min_threads = 0
|
278
261
|
status.max_threads = 1
|
@@ -0,0 +1,190 @@
|
|
1
|
+
module Puma
|
2
|
+
class Configuration
|
3
|
+
DefaultRackup = "config.ru"
|
4
|
+
|
5
|
+
DefaultTCPHost = "0.0.0.0"
|
6
|
+
DefaultTCPPort = 9292
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
@options[:binds] ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :options
|
14
|
+
|
15
|
+
def load
|
16
|
+
if path = @options[:config_file]
|
17
|
+
DSL.new(@options)._load_from path
|
18
|
+
end
|
19
|
+
|
20
|
+
# Rakeup default option support
|
21
|
+
if host = @options[:Host]
|
22
|
+
port = @options[:Port] || DefaultTCPPort
|
23
|
+
|
24
|
+
@options[:binds] << "tcp://#{host}:#{port}"
|
25
|
+
end
|
26
|
+
|
27
|
+
if @options[:binds].empty?
|
28
|
+
@options[:binds] << "tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"
|
29
|
+
end
|
30
|
+
|
31
|
+
if @options[:control_url] == "auto"
|
32
|
+
path = Configuration.temp_path
|
33
|
+
@options[:control_url] = "unix://#{path}"
|
34
|
+
@options[:control_url_temp] = path
|
35
|
+
end
|
36
|
+
|
37
|
+
unless @options[:control_auth_token]
|
38
|
+
setup_random_token
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Load the specified rackup file, pull an options from
|
43
|
+
# the rackup file, and set @app.
|
44
|
+
#
|
45
|
+
def app
|
46
|
+
if app = @options[:app]
|
47
|
+
return app
|
48
|
+
end
|
49
|
+
|
50
|
+
path = @options[:rackup] || DefaultRackup
|
51
|
+
|
52
|
+
unless File.exists?(path)
|
53
|
+
raise "Missing rackup file '#{path}'"
|
54
|
+
end
|
55
|
+
|
56
|
+
app, options = Rack::Builder.parse_file path
|
57
|
+
@options.merge! options
|
58
|
+
|
59
|
+
options.each do |key,val|
|
60
|
+
if key.to_s[0,4] == "bind"
|
61
|
+
@options[:binds] << val
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
unless @options[:quiet]
|
66
|
+
app = Rack::CommonLogger.new(app, STDOUT)
|
67
|
+
end
|
68
|
+
|
69
|
+
return app
|
70
|
+
end
|
71
|
+
|
72
|
+
def setup_random_token
|
73
|
+
begin
|
74
|
+
require 'openssl'
|
75
|
+
rescue LoadError
|
76
|
+
end
|
77
|
+
|
78
|
+
count = 16
|
79
|
+
|
80
|
+
bytes = nil
|
81
|
+
|
82
|
+
if defined? OpenSSL::Random
|
83
|
+
bytes = OpenSSL::Random.random_bytes(count)
|
84
|
+
elsif File.exists?("/dev/urandom")
|
85
|
+
File.open("/dev/urandom") do |f|
|
86
|
+
bytes = f.read(count)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
if bytes
|
91
|
+
token = ""
|
92
|
+
bytes.each_byte { |b| token << b.to_s(16) }
|
93
|
+
else
|
94
|
+
token = (0..count).to_a.map { rand(255).to_s(16) }.join
|
95
|
+
end
|
96
|
+
|
97
|
+
@options[:control_auth_token] = token
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.temp_path
|
101
|
+
require 'tmpdir'
|
102
|
+
|
103
|
+
t = (Time.now.to_f * 1000).to_i
|
104
|
+
"#{Dir.tmpdir}/puma-status-#{t}-#{$$}"
|
105
|
+
end
|
106
|
+
|
107
|
+
# The methods that are available for use inside the config file.
|
108
|
+
#
|
109
|
+
class DSL
|
110
|
+
def initialize(options)
|
111
|
+
@options = options
|
112
|
+
end
|
113
|
+
|
114
|
+
def _load_from(path)
|
115
|
+
instance_eval File.read(path), path, 1
|
116
|
+
end
|
117
|
+
|
118
|
+
# Use +obj+ or +block+ as the Rack app. This allows a config file to
|
119
|
+
# be the app itself.
|
120
|
+
#
|
121
|
+
def app(obj=nil, &block)
|
122
|
+
obj ||= block
|
123
|
+
|
124
|
+
raise "Provide either a #call'able or a block" unless obj
|
125
|
+
|
126
|
+
@options[:app] = obj
|
127
|
+
end
|
128
|
+
|
129
|
+
# Start the Puma control rack app on +url+. This app can be communicated
|
130
|
+
# with to control the main server.
|
131
|
+
#
|
132
|
+
def activate_control_app(url="auto", opts=nil)
|
133
|
+
@options[:control_url] = url
|
134
|
+
|
135
|
+
if opts
|
136
|
+
if tok = opts[:auth_token]
|
137
|
+
@options[:control_auth_token] = tok
|
138
|
+
end
|
139
|
+
|
140
|
+
if opts[:no_token]
|
141
|
+
@options[:control_auth_token] = :none
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Bind the server to +url+. tcp:// and unix:// are the only accepted
|
147
|
+
# protocols.
|
148
|
+
#
|
149
|
+
def bind(url)
|
150
|
+
@options[:binds] << url
|
151
|
+
end
|
152
|
+
|
153
|
+
# Store the pid of the server in the file at +path+.
|
154
|
+
def pidfile(path)
|
155
|
+
@options[:pidfile] = path
|
156
|
+
end
|
157
|
+
|
158
|
+
# Disable request logging.
|
159
|
+
#
|
160
|
+
def quiet
|
161
|
+
@options[:quiet] = true
|
162
|
+
end
|
163
|
+
|
164
|
+
# Load +path+ as a rackup file.
|
165
|
+
#
|
166
|
+
def rackup(path)
|
167
|
+
@options[:rackup] = path.to_s
|
168
|
+
end
|
169
|
+
|
170
|
+
# Configure +min+ to be the minimum number of threads to use to answer
|
171
|
+
# requests and +max+ the maximum.
|
172
|
+
#
|
173
|
+
def threads(min, max)
|
174
|
+
if min > max
|
175
|
+
raise "The minimum number of threads must be less than the max"
|
176
|
+
end
|
177
|
+
|
178
|
+
@options[:min_threads] = min
|
179
|
+
@options[:max_threads] = max
|
180
|
+
end
|
181
|
+
|
182
|
+
# Use +path+ as the file to store the server info state. This is
|
183
|
+
# used by pumactl to query and control the server.
|
184
|
+
#
|
185
|
+
def state_path(path)
|
186
|
+
@options[:state] = path.to_s
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
data/lib/puma/const.rb
CHANGED
data/lib/puma/control_cli.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
|
3
3
|
require 'puma/const'
|
4
|
-
require 'puma/
|
4
|
+
require 'puma/configuration'
|
5
5
|
|
6
6
|
require 'yaml'
|
7
7
|
require 'uri'
|
@@ -11,8 +11,9 @@ require 'socket'
|
|
11
11
|
module Puma
|
12
12
|
class ControlCLI
|
13
13
|
|
14
|
-
def initialize(argv)
|
14
|
+
def initialize(argv, stdout=STDOUT)
|
15
15
|
@argv = argv
|
16
|
+
@stdout = stdout
|
16
17
|
end
|
17
18
|
|
18
19
|
def setup_options
|
@@ -59,57 +60,68 @@ module Puma
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
63
|
+
def request(sock, url)
|
64
|
+
token = @config.options[:control_auth_token]
|
65
|
+
if token
|
66
|
+
url = "#{url}?token=#{token}"
|
67
|
+
end
|
68
|
+
|
69
|
+
sock << "GET #{url} HTTP/1.0\r\n\r\n"
|
70
|
+
|
71
|
+
rep = sock.read.split("\r\n")
|
72
|
+
|
73
|
+
m = %r!HTTP/1.\d (\d+)!.match(rep.first)
|
74
|
+
if m[1] == "403"
|
75
|
+
raise "Unauthorized access to server (wrong auth token)"
|
76
|
+
elsif m[1] != "200"
|
77
|
+
raise "Bad response code from server: #{m[1]}"
|
78
|
+
end
|
79
|
+
|
80
|
+
return rep.last
|
81
|
+
end
|
82
|
+
|
62
83
|
def command_pid
|
63
|
-
puts "#{@state['pid']}"
|
84
|
+
@stdout.puts "#{@state['pid']}"
|
64
85
|
end
|
65
86
|
|
66
87
|
def command_stop
|
67
88
|
sock = connect
|
68
|
-
sock
|
69
|
-
rep = sock.read
|
89
|
+
body = request sock, "/stop"
|
70
90
|
|
71
|
-
body = rep.split("\r\n").last
|
72
91
|
if body != '{ "status": "ok" }'
|
73
92
|
raise "Invalid response: '#{body}'"
|
74
93
|
else
|
75
|
-
puts "Requested stop from server"
|
94
|
+
@stdout.puts "Requested stop from server"
|
76
95
|
end
|
77
96
|
end
|
78
97
|
|
79
98
|
def command_halt
|
80
99
|
sock = connect
|
81
|
-
|
82
|
-
rep = s.read
|
100
|
+
body = request sock, "/halt"
|
83
101
|
|
84
|
-
body = rep.split("\r\n").last
|
85
102
|
if body != '{ "status": "ok" }'
|
86
103
|
raise "Invalid response: '#{body}'"
|
87
104
|
else
|
88
|
-
puts "Requested halt from server"
|
105
|
+
@stdout.puts "Requested halt from server"
|
89
106
|
end
|
90
107
|
end
|
91
108
|
|
92
109
|
def command_restart
|
93
110
|
sock = connect
|
94
|
-
sock
|
95
|
-
rep = sock.read
|
111
|
+
body = request sock, "/restart"
|
96
112
|
|
97
|
-
body = rep.split("\r\n").last
|
98
113
|
if body != '{ "status": "ok" }'
|
99
114
|
raise "Invalid response: '#{body}'"
|
100
115
|
else
|
101
|
-
puts "Requested restart from server"
|
116
|
+
@stdout.puts "Requested restart from server"
|
102
117
|
end
|
103
118
|
end
|
104
119
|
|
105
120
|
def command_stats
|
106
121
|
sock = connect
|
107
|
-
sock
|
108
|
-
rep = sock.read
|
109
|
-
|
110
|
-
body = rep.split("\r\n").last
|
122
|
+
body = request sock, "/stats"
|
111
123
|
|
112
|
-
puts body
|
124
|
+
@stdout.puts body
|
113
125
|
end
|
114
126
|
end
|
115
127
|
end
|
data/lib/puma/server.rb
CHANGED
@@ -52,6 +52,7 @@ module Puma
|
|
52
52
|
@thread_pool = nil
|
53
53
|
|
54
54
|
@persistent_timeout = PERSISTENT_TIMEOUT
|
55
|
+
@persistent_check, @persistent_wakeup = IO.pipe
|
55
56
|
|
56
57
|
@proto_env = {
|
57
58
|
"rack.version".freeze => Rack::VERSION,
|
@@ -91,14 +92,18 @@ module Puma
|
|
91
92
|
end
|
92
93
|
|
93
94
|
# Tell the server to listen on host +host+, port +port+.
|
94
|
-
# If optimize_for_latency is true (the default) then clients connecting
|
95
|
+
# If +optimize_for_latency+ is true (the default) then clients connecting
|
95
96
|
# will be optimized for latency over throughput.
|
96
97
|
#
|
97
|
-
|
98
|
+
# +backlog+ indicates how many unaccepted connections the kernel should
|
99
|
+
# allow to accumulate before returning connection refused.
|
100
|
+
#
|
101
|
+
def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
|
98
102
|
s = TCPServer.new(host, port)
|
99
103
|
if optimize_for_latency
|
100
104
|
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
101
105
|
end
|
106
|
+
s.listen backlog
|
102
107
|
@ios << s
|
103
108
|
end
|
104
109
|
|
@@ -219,9 +224,11 @@ module Puma
|
|
219
224
|
env = @proto_env.dup
|
220
225
|
nparsed = 0
|
221
226
|
else
|
222
|
-
unless IO.select([client], nil, nil, @persistent_timeout)
|
227
|
+
unless ret = IO.select([client, @persistent_check], nil, nil, @persistent_timeout)
|
223
228
|
raise EOFError, "Timed out persistent connection"
|
224
229
|
end
|
230
|
+
|
231
|
+
return if ret.first.include? @persistent_check
|
225
232
|
end
|
226
233
|
else
|
227
234
|
# Parser is not done, queue up more data to read and continue parsing
|
@@ -514,12 +521,14 @@ module Puma
|
|
514
521
|
# off the request queue before finally exiting.
|
515
522
|
#
|
516
523
|
def stop(sync=false)
|
524
|
+
@persistent_wakeup.close
|
517
525
|
@notify << STOP_COMMAND
|
518
526
|
|
519
527
|
@thread.join if @thread && sync
|
520
528
|
end
|
521
529
|
|
522
530
|
def halt(sync=false)
|
531
|
+
@persistent_wakeup.close
|
523
532
|
@notify << HALT_COMMAND
|
524
533
|
|
525
534
|
@thread.join if @thread && sync
|
data/lib/rack/handler/puma.rb
CHANGED
@@ -8,13 +8,13 @@ module Rack
|
|
8
8
|
:Host => '0.0.0.0',
|
9
9
|
:Port => 8080,
|
10
10
|
:Threads => '0:16',
|
11
|
-
:
|
11
|
+
:Verbose => false
|
12
12
|
}
|
13
13
|
|
14
14
|
def self.run(app, options = {})
|
15
15
|
options = DEFAULT_OPTIONS.merge(options)
|
16
16
|
|
17
|
-
|
17
|
+
if options[:Verbose]
|
18
18
|
app = Rack::CommonLogger.new(app, STDOUT)
|
19
19
|
end
|
20
20
|
|
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 = "0.9.
|
5
|
+
s.version = "0.9.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 = "2011-12-
|
9
|
+
s.date = "2011-12-19"
|
10
10
|
s.description = "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.\n\nWhat 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."
|
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/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/
|
15
|
+
s.files = ["COPYING", "Gemfile", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "examples/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/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
16
|
s.rdoc_options = ["--main", "README.md"]
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
s.rubyforge_project = "puma"
|
19
19
|
s.rubygems_version = "1.8.12"
|
20
20
|
s.summary = "Puma is a small library that provides a very fast and concurrent HTTP 1.1 server for Ruby web applications"
|
21
|
-
s.test_files = ["test/test_app_status.rb", "test/test_cli.rb", "test/test_http10.rb", "test/test_http11.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"]
|
21
|
+
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_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
|
22
22
|
|
23
23
|
if s.respond_to? :specification_version then
|
24
24
|
s.specification_version = 3
|
@@ -26,15 +26,18 @@ Gem::Specification.new do |s|
|
|
26
26
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
27
27
|
s.add_runtime_dependency(%q<rack>, ["~> 1.2"])
|
28
28
|
s.add_development_dependency(%q<rake-compiler>, ["~> 0.7.0"])
|
29
|
-
s.add_development_dependency(%q<hoe>, ["~> 2.
|
29
|
+
s.add_development_dependency(%q<hoe>, ["~> 2.12"])
|
30
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.10"])
|
30
31
|
else
|
31
32
|
s.add_dependency(%q<rack>, ["~> 1.2"])
|
32
33
|
s.add_dependency(%q<rake-compiler>, ["~> 0.7.0"])
|
33
|
-
s.add_dependency(%q<hoe>, ["~> 2.
|
34
|
+
s.add_dependency(%q<hoe>, ["~> 2.12"])
|
35
|
+
s.add_dependency(%q<rdoc>, ["~> 3.10"])
|
34
36
|
end
|
35
37
|
else
|
36
38
|
s.add_dependency(%q<rack>, ["~> 1.2"])
|
37
39
|
s.add_dependency(%q<rake-compiler>, ["~> 0.7.0"])
|
38
|
-
s.add_dependency(%q<hoe>, ["~> 2.
|
40
|
+
s.add_dependency(%q<hoe>, ["~> 2.12"])
|
41
|
+
s.add_dependency(%q<rdoc>, ["~> 3.10"])
|
39
42
|
end
|
40
43
|
end
|
data/test/config/app.rb
ADDED
data/test/hello.ru
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
run lambda { |env| [200, {}, ["Hello World"]] }
|
data/test/slow.ru
ADDED
data/test/test_app_status.rb
CHANGED
@@ -24,12 +24,36 @@ class TestAppStatus < Test::Unit::TestCase
|
|
24
24
|
def setup
|
25
25
|
@server = FakeServer.new
|
26
26
|
@app = Puma::App::Status.new(@server, @server)
|
27
|
+
@app.auth_token = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_bad_token
|
31
|
+
@app.auth_token = "abcdef"
|
32
|
+
|
33
|
+
env = { 'PATH_INFO' => "/whatever" }
|
34
|
+
|
35
|
+
status, _, _ = @app.call env
|
36
|
+
|
37
|
+
assert_equal 403, status
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_good_token
|
41
|
+
@app.auth_token = "abcdef"
|
42
|
+
|
43
|
+
env = {
|
44
|
+
'PATH_INFO' => "/whatever",
|
45
|
+
'QUERY_STRING' => "token=abcdef"
|
46
|
+
}
|
47
|
+
|
48
|
+
status, _, _ = @app.call env
|
49
|
+
|
50
|
+
assert_equal 404, status
|
27
51
|
end
|
28
52
|
|
29
53
|
def test_unsupported
|
30
54
|
env = { 'PATH_INFO' => "/not-real" }
|
31
55
|
|
32
|
-
status,
|
56
|
+
status, _, _ = @app.call env
|
33
57
|
|
34
58
|
assert_equal 404, status
|
35
59
|
end
|
@@ -37,7 +61,7 @@ class TestAppStatus < Test::Unit::TestCase
|
|
37
61
|
def test_stop
|
38
62
|
env = { 'PATH_INFO' => "/stop" }
|
39
63
|
|
40
|
-
status,
|
64
|
+
status, _ , body = @app.call env
|
41
65
|
|
42
66
|
assert_equal :stop, @server.status
|
43
67
|
assert_equal 200, status
|
@@ -47,7 +71,7 @@ class TestAppStatus < Test::Unit::TestCase
|
|
47
71
|
def test_halt
|
48
72
|
env = { 'PATH_INFO' => "/halt" }
|
49
73
|
|
50
|
-
status,
|
74
|
+
status, _ , body = @app.call env
|
51
75
|
|
52
76
|
assert_equal :halt, @server.status
|
53
77
|
assert_equal 200, status
|
@@ -60,7 +84,7 @@ class TestAppStatus < Test::Unit::TestCase
|
|
60
84
|
@server.backlog = 1
|
61
85
|
@server.running = 9
|
62
86
|
|
63
|
-
status,
|
87
|
+
status, _ , body = @app.call env
|
64
88
|
|
65
89
|
assert_equal 200, status
|
66
90
|
assert_equal ['{ "backlog": 1, "running": 9 }'], body
|
data/test/test_cli.rb
CHANGED
@@ -34,7 +34,10 @@ class TestCLI < Test::Unit::TestCase
|
|
34
34
|
sin = StringIO.new
|
35
35
|
sout = StringIO.new
|
36
36
|
|
37
|
-
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
|
37
|
+
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
|
38
|
+
"--control", url,
|
39
|
+
"--control-token", "",
|
40
|
+
"test/lobster.ru"], sin, sout
|
38
41
|
cli.parse_options
|
39
42
|
|
40
43
|
t = Thread.new { cli.run }
|
@@ -57,7 +60,10 @@ class TestCLI < Test::Unit::TestCase
|
|
57
60
|
sin = StringIO.new
|
58
61
|
sout = StringIO.new
|
59
62
|
|
60
|
-
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
|
63
|
+
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}",
|
64
|
+
"--control", url,
|
65
|
+
"--control-token", "",
|
66
|
+
"test/lobster.ru"], sin, sout
|
61
67
|
cli.parse_options
|
62
68
|
|
63
69
|
t = Thread.new { cli.run }
|
data/test/test_config.rb
ADDED
@@ -0,0 +1,16 @@
|
|
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(nil)
|
15
|
+
end
|
16
|
+
end
|
data/test/test_http11.rb
CHANGED
@@ -37,14 +37,6 @@ class Http11ParserTest < Test::Unit::TestCase
|
|
37
37
|
assert_equal should_be_good.length, nread
|
38
38
|
assert parser.finished?
|
39
39
|
assert !parser.error?
|
40
|
-
|
41
|
-
nasty_pound_header = "GET / HTTP/1.1\r\nX-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n\tRA==\r\n\t-----END CERTIFICATE-----\r\n\r\n"
|
42
|
-
parser = HttpParser.new
|
43
|
-
req = {}
|
44
|
-
#nread = parser.execute(req, nasty_pound_header, 0)
|
45
|
-
#assert_equal nasty_pound_header.length, nread
|
46
|
-
#assert parser.finished?
|
47
|
-
#assert !parser.error?
|
48
40
|
end
|
49
41
|
|
50
42
|
def test_parse_error
|
@@ -54,8 +46,8 @@ class Http11ParserTest < Test::Unit::TestCase
|
|
54
46
|
|
55
47
|
error = false
|
56
48
|
begin
|
57
|
-
|
58
|
-
rescue
|
49
|
+
parser.execute(req, bad_http, 0)
|
50
|
+
rescue
|
59
51
|
error = true
|
60
52
|
end
|
61
53
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
require 'puma/cli'
|
6
|
+
require 'puma/control_cli'
|
7
|
+
|
8
|
+
class TestIntegration < Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@state_path = "test/test_puma.state"
|
11
|
+
@bind_path = "test/test_server.sock"
|
12
|
+
@control_path = "test/test_control.sock"
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
File.unlink @state_path rescue nil
|
17
|
+
File.unlink @bind_path rescue nil
|
18
|
+
File.unlink @control_path rescue nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_stop_via_pumactl
|
22
|
+
if defined? JRUBY_VERSION
|
23
|
+
assert true
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
sin = StringIO.new
|
28
|
+
sout = StringIO.new
|
29
|
+
|
30
|
+
cli = Puma::CLI.new %W!-q -S #{@state_path} -b unix://#{@bind_path} --control unix://#{@control_path} test/hello.ru!, sin, sout
|
31
|
+
|
32
|
+
t = Thread.new do
|
33
|
+
cli.run
|
34
|
+
end
|
35
|
+
|
36
|
+
sleep 1
|
37
|
+
|
38
|
+
s = UNIXSocket.new @bind_path
|
39
|
+
s << "GET / HTTP/1.0\r\n\r\n"
|
40
|
+
assert_equal "Hello World", s.read.split("\r\n").last
|
41
|
+
|
42
|
+
ccli = Puma::ControlCLI.new %W!-S #{@state_path} stop!, sout
|
43
|
+
|
44
|
+
ccli.run
|
45
|
+
|
46
|
+
assert_kind_of Thread, t.join(1), "server didn't stop"
|
47
|
+
end
|
48
|
+
end
|
data/test/test_ws.rb
CHANGED
@@ -90,7 +90,7 @@ class WebServerTest < Test::Unit::TestCase
|
|
90
90
|
def test_file_streamed_request
|
91
91
|
body = "a" * (Puma::Const::MAX_BODY * 2)
|
92
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)
|
93
|
+
do_test(long, (Puma::Const::CHUNK_SIZE * 2) - 400)
|
94
94
|
end
|
95
95
|
|
96
96
|
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: 63
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 2
|
10
|
+
version: 0.9.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: 2011-12-
|
18
|
+
date: 2011-12-19 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rack
|
@@ -118,7 +118,7 @@ files:
|
|
118
118
|
- lib/puma.rb
|
119
119
|
- lib/puma/app/status.rb
|
120
120
|
- lib/puma/cli.rb
|
121
|
-
- lib/puma/
|
121
|
+
- lib/puma/configuration.rb
|
122
122
|
- lib/puma/const.rb
|
123
123
|
- lib/puma/control_cli.rb
|
124
124
|
- lib/puma/events.rb
|
@@ -130,12 +130,17 @@ files:
|
|
130
130
|
- lib/rack/handler/puma.rb
|
131
131
|
- puma.gemspec
|
132
132
|
- test/ab_rs.rb
|
133
|
+
- test/config/app.rb
|
134
|
+
- test/hello.ru
|
133
135
|
- test/lobster.ru
|
134
136
|
- test/mime.yaml
|
137
|
+
- test/slow.ru
|
135
138
|
- test/test_app_status.rb
|
136
139
|
- test/test_cli.rb
|
140
|
+
- test/test_config.rb
|
137
141
|
- test/test_http10.rb
|
138
142
|
- test/test_http11.rb
|
143
|
+
- test/test_integration.rb
|
139
144
|
- test/test_persistent.rb
|
140
145
|
- test/test_rack_handler.rb
|
141
146
|
- test/test_rack_server.rb
|
@@ -181,8 +186,10 @@ summary: Puma is a small library that provides a very fast and concurrent HTTP 1
|
|
181
186
|
test_files:
|
182
187
|
- test/test_app_status.rb
|
183
188
|
- test/test_cli.rb
|
189
|
+
- test/test_config.rb
|
184
190
|
- test/test_http10.rb
|
185
191
|
- test/test_http11.rb
|
192
|
+
- test/test_integration.rb
|
186
193
|
- test/test_persistent.rb
|
187
194
|
- test/test_rack_handler.rb
|
188
195
|
- test/test_rack_server.rb
|
data/lib/puma/config.rb
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
module Puma
|
2
|
-
class Configuration
|
3
|
-
DefaultTCPHost = "0.0.0.0"
|
4
|
-
DefaultTCPPort = 9292
|
5
|
-
|
6
|
-
def initialize(options)
|
7
|
-
@options = options
|
8
|
-
@options[:binds] ||= []
|
9
|
-
end
|
10
|
-
|
11
|
-
attr_reader :options
|
12
|
-
|
13
|
-
def load
|
14
|
-
if path = @options[:config_file]
|
15
|
-
instance_eval File.read(path), path, 1
|
16
|
-
end
|
17
|
-
|
18
|
-
# Rakeup default option support
|
19
|
-
if host = @options[:Host]
|
20
|
-
port = @options[:Port] || DefaultTCPPort
|
21
|
-
|
22
|
-
@options[:binds] << "tcp://#{host}:#{port}"
|
23
|
-
end
|
24
|
-
|
25
|
-
if @options[:binds].empty?
|
26
|
-
@options[:binds] << "tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.temp_path
|
31
|
-
require 'tmpdir'
|
32
|
-
|
33
|
-
t = (Time.now.to_f * 1000).to_i
|
34
|
-
"#{Dir.tmpdir}/puma-status-#{t}-#{$$}"
|
35
|
-
end
|
36
|
-
|
37
|
-
# Use +obj+ or +block+ as the Rack app. This allows a config file to
|
38
|
-
# be the app itself.
|
39
|
-
#
|
40
|
-
def app(obj=nil, &block)
|
41
|
-
obj ||= block
|
42
|
-
|
43
|
-
raise "Provide either a #call'able or a block" unless obj
|
44
|
-
|
45
|
-
@options[:app] = obj
|
46
|
-
end
|
47
|
-
|
48
|
-
# Start the Puma control rack app on +url+. This app can be communicated
|
49
|
-
# with to control the main server.
|
50
|
-
#
|
51
|
-
def activate_control_app(url="auto")
|
52
|
-
@options[:control_url] = url
|
53
|
-
end
|
54
|
-
|
55
|
-
# Bind the server to +url+. tcp:// and unix:// are the only accepted
|
56
|
-
# protocols.
|
57
|
-
#
|
58
|
-
def bind(url)
|
59
|
-
@options[:binds] << url
|
60
|
-
end
|
61
|
-
|
62
|
-
# Store the pid of the server in the file at +path+.
|
63
|
-
def pidfile(path)
|
64
|
-
@options[:pidfile] = path
|
65
|
-
end
|
66
|
-
|
67
|
-
# Disable request logging.
|
68
|
-
#
|
69
|
-
def quiet
|
70
|
-
@options[:quiet] = true
|
71
|
-
end
|
72
|
-
|
73
|
-
# Load +path+ as a rackup file.
|
74
|
-
#
|
75
|
-
def rackup(path)
|
76
|
-
@options[:rackup] = path.to_s
|
77
|
-
end
|
78
|
-
|
79
|
-
# Configure +min+ to be the minimum number of threads to use to answer
|
80
|
-
# requests and +max+ the maximum.
|
81
|
-
#
|
82
|
-
def threads(min, max)
|
83
|
-
if min > max
|
84
|
-
raise "The minimum number of threads must be less than the max"
|
85
|
-
end
|
86
|
-
|
87
|
-
@options[:min_threads] = min
|
88
|
-
@options[:max_threads] = max
|
89
|
-
end
|
90
|
-
|
91
|
-
# Use +path+ as the file to store the server info state. This is
|
92
|
-
# used by pumactl to query and control the server.
|
93
|
-
#
|
94
|
-
def state_path(path)
|
95
|
-
@options[:state] = path.to_s
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|