yahns 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Documentation/.gitignore +5 -0
- data/Documentation/GNUmakefile +50 -0
- data/Documentation/yahns-rackup.txt +152 -0
- data/Documentation/yahns.txt +68 -0
- data/Documentation/yahns_config.txt +563 -0
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +14 -7
- data/HACKING +56 -0
- data/INSTALL +8 -0
- data/README +15 -2
- data/Rakefile +2 -2
- data/bin/yahns +1 -2
- data/bin/yahns-rackup +9 -0
- data/examples/yahns_multi.conf.rb +14 -4
- data/examples/yahns_rack_basic.conf.rb +17 -1
- data/extras/README +16 -0
- data/extras/autoindex.rb +151 -0
- data/extras/exec_cgi.rb +108 -0
- data/extras/proxy_pass.rb +210 -0
- data/extras/try_gzip_static.rb +208 -0
- data/lib/yahns.rb +5 -2
- data/lib/yahns/acceptor.rb +64 -22
- data/lib/yahns/cap_input.rb +2 -2
- data/lib/yahns/{client_expire_portable.rb → client_expire_generic.rb} +12 -11
- data/lib/yahns/{client_expire.rb → client_expire_tcpi.rb} +7 -6
- data/lib/yahns/config.rb +107 -22
- data/lib/yahns/daemon.rb +2 -0
- data/lib/yahns/fdmap.rb +28 -9
- data/lib/yahns/http_client.rb +123 -37
- data/lib/yahns/http_context.rb +21 -3
- data/lib/yahns/http_response.rb +80 -19
- data/lib/yahns/log.rb +23 -4
- data/lib/yahns/queue_epoll.rb +20 -9
- data/lib/yahns/queue_quitter.rb +16 -0
- data/lib/yahns/queue_quitter_pipe.rb +24 -0
- data/lib/yahns/rack.rb +0 -1
- data/lib/yahns/rackup_handler.rb +57 -0
- data/lib/yahns/server.rb +189 -59
- data/lib/yahns/server_mp.rb +43 -35
- data/lib/yahns/sigevent_pipe.rb +1 -0
- data/lib/yahns/socket_helper.rb +37 -11
- data/lib/yahns/stream_file.rb +14 -4
- data/lib/yahns/stream_input.rb +13 -7
- data/lib/yahns/tcp_server.rb +7 -0
- data/lib/yahns/tmpio.rb +10 -3
- data/lib/yahns/unix_server.rb +7 -0
- data/lib/yahns/wbuf.rb +19 -2
- data/lib/yahns/wbuf_common.rb +10 -3
- data/lib/yahns/wbuf_str.rb +24 -0
- data/lib/yahns/worker.rb +5 -26
- data/test/helper.rb +15 -5
- data/test/server_helper.rb +37 -1
- data/test/test_bin.rb +17 -8
- data/test/test_buffer_tmpdir.rb +103 -0
- data/test/test_client_expire.rb +71 -35
- data/test/test_client_max_body_size.rb +5 -13
- data/test/test_config.rb +1 -1
- data/test/test_expect_100.rb +176 -0
- data/test/test_extras_autoindex.rb +53 -0
- data/test/test_extras_exec_cgi.rb +81 -0
- data/test/test_extras_exec_cgi.sh +35 -0
- data/test/test_extras_try_gzip_static.rb +177 -0
- data/test/test_input.rb +128 -0
- data/test/test_mt_accept.rb +48 -0
- data/test/test_output_buffering.rb +90 -63
- data/test/test_rack.rb +1 -1
- data/test/test_rack_hijack.rb +2 -6
- data/test/test_reopen_logs.rb +2 -8
- data/test/test_serve_static.rb +104 -8
- data/test/test_server.rb +448 -73
- data/test/test_stream_file.rb +1 -1
- data/test/test_unix_socket.rb +72 -0
- data/test/test_wbuf.rb +20 -17
- data/yahns.gemspec +3 -0
- metadata +57 -5
data/lib/yahns.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
|
+
$stdout.sync = $stderr.sync = true
|
|
4
|
+
|
|
3
5
|
require 'unicorn' # pulls in raindrops, kgio, fcntl, etc, stringio, and logger
|
|
4
6
|
require 'sleepy_penguin'
|
|
5
7
|
|
|
@@ -48,6 +50,9 @@ module Yahns # :nodoc:
|
|
|
48
50
|
# for client shutdowns/disconnects.
|
|
49
51
|
class ClientShutdown < EOFError # :nodoc:
|
|
50
52
|
end
|
|
53
|
+
|
|
54
|
+
class ClientTimeout < RuntimeError # :nodoc:
|
|
55
|
+
end
|
|
51
56
|
end
|
|
52
57
|
|
|
53
58
|
# FIXME: require lazily
|
|
@@ -56,7 +61,6 @@ require_relative 'yahns/queue_epoll'
|
|
|
56
61
|
require_relative 'yahns/stream_input'
|
|
57
62
|
require_relative 'yahns/tee_input'
|
|
58
63
|
require_relative 'yahns/queue_egg'
|
|
59
|
-
require_relative 'yahns/client_expire'
|
|
60
64
|
require_relative 'yahns/http_response'
|
|
61
65
|
require_relative 'yahns/http_client'
|
|
62
66
|
require_relative 'yahns/http_context'
|
|
@@ -65,7 +69,6 @@ require_relative 'yahns/config'
|
|
|
65
69
|
require_relative 'yahns/tmpio'
|
|
66
70
|
require_relative 'yahns/worker'
|
|
67
71
|
require_relative 'yahns/sigevent'
|
|
68
|
-
require_relative 'yahns/daemon'
|
|
69
72
|
require_relative 'yahns/socket_helper'
|
|
70
73
|
require_relative 'yahns/server'
|
|
71
74
|
require_relative 'yahns/fdmap'
|
data/lib/yahns/acceptor.rb
CHANGED
|
@@ -1,30 +1,72 @@
|
|
|
1
|
+
# -*- encoding: binary -*-
|
|
1
2
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> et. al.
|
|
2
3
|
# License: GPLv3 or later (see COPYING for details)
|
|
4
|
+
require_relative 'client_expire_tcpi'
|
|
5
|
+
require_relative 'client_expire_generic'
|
|
3
6
|
module Yahns::Acceptor # :nodoc:
|
|
4
|
-
def
|
|
5
|
-
|
|
6
|
-
accept_flags = Kgio::SOCK_NONBLOCK | Kgio::SOCK_CLOEXEC
|
|
7
|
-
Thread.current.abort_on_exception = true
|
|
8
|
-
qev_flags = client_class.superclass::QEV_FLAGS
|
|
7
|
+
def __ac_quit_done?
|
|
8
|
+
@thrs.delete_if do |t|
|
|
9
9
|
begin
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
t.join(0.01)
|
|
11
|
+
rescue
|
|
12
|
+
! t.alive?
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
return false if @thrs[0]
|
|
16
|
+
close
|
|
17
|
+
true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# just keep looping this on every acceptor until the associated thread dies
|
|
21
|
+
def ac_quit
|
|
22
|
+
return true unless defined?(@thrs)
|
|
23
|
+
@thrs.each { |t| t[:yahns_quit] = true }
|
|
24
|
+
return true if __ac_quit_done?
|
|
25
|
+
|
|
26
|
+
@thrs.each do
|
|
27
|
+
begin
|
|
28
|
+
# try to connect to kick it out of the blocking accept() syscall
|
|
29
|
+
killer = Kgio::Socket.start(getsockname)
|
|
30
|
+
killer.kgio_write("G") # first byte of "GET / HTTP/1.0\r\n\r\n"
|
|
31
|
+
ensure
|
|
32
|
+
killer.close if killer
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
false # now hope __ac_quit_done? is true next time around
|
|
36
|
+
rescue SystemCallError
|
|
37
|
+
return __ac_quit_done?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def spawn_acceptor(nr, logger, client_class)
|
|
41
|
+
@thrs = nr.times.map do
|
|
42
|
+
Thread.new do
|
|
43
|
+
queue = client_class.queue
|
|
44
|
+
t = Thread.current
|
|
45
|
+
accept_flags = Kgio::SOCK_NONBLOCK | Kgio::SOCK_CLOEXEC
|
|
46
|
+
qev_flags = client_class.superclass::QEV_FLAGS
|
|
47
|
+
begin
|
|
48
|
+
# We want the accept/accept4 syscall to be _blocking_
|
|
49
|
+
# so it can distribute work evenly between processes
|
|
50
|
+
if client = kgio_accept(client_class, accept_flags)
|
|
51
|
+
client.yahns_init
|
|
14
52
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
end while true
|
|
53
|
+
# it is not safe to touch client in this thread after this,
|
|
54
|
+
# a worker thread may grab client right away
|
|
55
|
+
queue.queue_add(client, qev_flags)
|
|
56
|
+
end
|
|
57
|
+
rescue Errno::EMFILE, Errno::ENFILE => e
|
|
58
|
+
logger.error("#{e.message}, consider raising open file limits")
|
|
59
|
+
queue.fdmap.desperate_expire_for(nil, 5)
|
|
60
|
+
sleep 1 # let other threads do some work
|
|
61
|
+
rescue => e
|
|
62
|
+
Yahns::Log.exception(logger, "accept loop", e)
|
|
63
|
+
end until t[:yahns_quit]
|
|
64
|
+
end
|
|
28
65
|
end
|
|
29
66
|
end
|
|
67
|
+
|
|
68
|
+
def expire_mod
|
|
69
|
+
(Yahns::TCPServer === self && Yahns.const_defined?(:ClientExpireTCPI)) ?
|
|
70
|
+
Yahns::ClientExpireTCPI : Yahns::ClientExpireGeneric
|
|
71
|
+
end
|
|
30
72
|
end
|
data/lib/yahns/cap_input.rb
CHANGED
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
|
-
module Yahns::
|
|
3
|
+
module Yahns::ClientExpireGeneric # :nodoc:
|
|
4
4
|
def __timestamp
|
|
5
5
|
Time.now.to_f
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
def yahns_init
|
|
9
|
+
super # Yahns::HttpClient#yahns_init
|
|
10
|
+
@last_io_at = 0
|
|
11
|
+
end
|
|
12
|
+
|
|
8
13
|
def yahns_expire(timeout)
|
|
9
|
-
return 0 if closed?
|
|
14
|
+
return 0 if closed?
|
|
10
15
|
if (__timestamp - @last_io_at) > timeout
|
|
11
16
|
shutdown
|
|
12
17
|
1
|
|
13
18
|
else
|
|
14
19
|
0
|
|
15
20
|
end
|
|
16
|
-
|
|
21
|
+
# shutdown may race with the shutdown in http_response_done
|
|
22
|
+
rescue
|
|
17
23
|
0
|
|
18
24
|
end
|
|
19
25
|
|
|
20
|
-
def
|
|
21
|
-
@last_io_at = __timestamp
|
|
22
|
-
super
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def kgio_write(*args)
|
|
26
|
+
def kgio_trywrite(*args)
|
|
26
27
|
@last_io_at = __timestamp
|
|
27
28
|
super
|
|
28
29
|
end
|
|
29
30
|
|
|
30
|
-
def
|
|
31
|
+
def kgio_tryread(*args)
|
|
31
32
|
@last_io_at = __timestamp
|
|
32
33
|
super
|
|
33
34
|
end
|
|
34
35
|
|
|
35
|
-
def
|
|
36
|
+
def trysendfile(*args)
|
|
36
37
|
@last_io_at = __timestamp
|
|
37
38
|
super
|
|
38
39
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
|
+
require 'raindrops'
|
|
3
4
|
|
|
4
5
|
# included in Yahns::HttpClient
|
|
5
6
|
#
|
|
@@ -7,9 +8,9 @@
|
|
|
7
8
|
# on idle clients
|
|
8
9
|
#
|
|
9
10
|
# we absolutely DO NOT issue IO#close in here, only BasicSocket#shutdown
|
|
10
|
-
module Yahns::
|
|
11
|
+
module Yahns::ClientExpireTCPI # :nodoc:
|
|
11
12
|
def yahns_expire(timeout) # rarely called
|
|
12
|
-
return 0 if closed?
|
|
13
|
+
return 0 if closed?
|
|
13
14
|
|
|
14
15
|
info = Raindrops::TCP_Info.new(self)
|
|
15
16
|
return 0 if info.state != 1 # TCP_ESTABLISHED == 1
|
|
@@ -31,10 +32,10 @@ module Yahns::ClientExpire # :nodoc:
|
|
|
31
32
|
else
|
|
32
33
|
0
|
|
33
34
|
end
|
|
34
|
-
#
|
|
35
|
-
# (since those are the most trusted of local clients)
|
|
36
|
-
# the IO#closed? check is racy
|
|
35
|
+
# shutdown may race with the shutdown in http_response_done
|
|
37
36
|
rescue
|
|
38
37
|
0
|
|
39
38
|
end
|
|
40
|
-
|
|
39
|
+
# FreeBSD has "struct tcp_info", too, but does not support all the fields
|
|
40
|
+
# Linux does as of FreeBSD 9 (haven't checked FreeBSD 10, yet).
|
|
41
|
+
end if RUBY_PLATFORM =~ /linux/
|
data/lib/yahns/config.rb
CHANGED
|
@@ -22,9 +22,10 @@ class Yahns::Config # :nodoc:
|
|
|
22
22
|
return var if @block == nil
|
|
23
23
|
msg = "#{var} must be called outside of #{@block.type}"
|
|
24
24
|
else
|
|
25
|
-
|
|
25
|
+
ctx = Array(ctx)
|
|
26
|
+
return var if @block && ctx.include?(@block.type)
|
|
26
27
|
msg = @block ? "may not be used inside a #{@block.type} block" :
|
|
27
|
-
"must be used with a #{ctx} block"
|
|
28
|
+
"must be used with a #{ctx.join(' or ')} block"
|
|
28
29
|
end
|
|
29
30
|
raise ArgumentError, msg
|
|
30
31
|
end
|
|
@@ -38,7 +39,7 @@ class Yahns::Config # :nodoc:
|
|
|
38
39
|
@config_listeners = {} # name/address -> options
|
|
39
40
|
@app_ctx = []
|
|
40
41
|
@set = Hash.new(:unset)
|
|
41
|
-
@qeggs = {}
|
|
42
|
+
@qeggs = Hash.new { |h,k| h[k] = Yahns::QueueEgg.new }
|
|
42
43
|
@app_instances = {}
|
|
43
44
|
|
|
44
45
|
# set defaults:
|
|
@@ -73,10 +74,44 @@ class Yahns::Config # :nodoc:
|
|
|
73
74
|
end
|
|
74
75
|
end
|
|
75
76
|
|
|
76
|
-
def
|
|
77
|
-
|
|
78
|
-
var =
|
|
77
|
+
def shutdown_timeout(sec)
|
|
78
|
+
var = _check_in_block(nil, :shutdown_timeout)
|
|
79
|
+
@set[var] = _check_num(var, sec, 0)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def worker_processes(nr, &blk)
|
|
83
|
+
var =_check_in_block(nil, :worker_processes)
|
|
79
84
|
@set[var] = _check_int(var, nr, 1)
|
|
85
|
+
if block_given?
|
|
86
|
+
@block = CfgBlock.new(var, nil)
|
|
87
|
+
instance_eval(&blk)
|
|
88
|
+
@block = nil
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
%w(atfork_prepare atfork_parent atfork_child).each do |fn|
|
|
93
|
+
eval(
|
|
94
|
+
%Q(def #{fn}(*args, &blk);) <<
|
|
95
|
+
%Q( _check_in_block([:worker_processes,:app], :#{fn});) <<
|
|
96
|
+
%Q( _add_hook(:#{fn}, block_given? ? blk : args[0]);) <<
|
|
97
|
+
%Q(end)
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def before_exec(&blk)
|
|
102
|
+
var = _check_in_block(nil, :before_exec)
|
|
103
|
+
@set[var] = (block_given? ? blk : args[0])
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def _add_hook(var, my_proc)
|
|
107
|
+
Proc === my_proc or
|
|
108
|
+
raise ArgumentError, "invalid type: #{var}=#{my_proc.inspect}"
|
|
109
|
+
|
|
110
|
+
# this sets:
|
|
111
|
+
# :atfork_prepare, :atfork_parent, :atfork_child
|
|
112
|
+
key = var.to_sym
|
|
113
|
+
@set[key] = [] unless @set.include?(key)
|
|
114
|
+
@set[key] << my_proc
|
|
80
115
|
end
|
|
81
116
|
|
|
82
117
|
# sets the +path+ for the PID file of the yahns master process
|
|
@@ -104,7 +139,7 @@ class Yahns::Config # :nodoc:
|
|
|
104
139
|
# for error checking and cannot be undone by unsetting it in the
|
|
105
140
|
# configuration file and reloading.
|
|
106
141
|
def working_directory(path)
|
|
107
|
-
var = :working_directory
|
|
142
|
+
var = _check_in_block(nil, :working_directory)
|
|
108
143
|
@app_ctx.empty? or
|
|
109
144
|
raise ArgumentError, "#{var} must be declared before any apps"
|
|
110
145
|
|
|
@@ -127,7 +162,7 @@ class Yahns::Config # :nodoc:
|
|
|
127
162
|
# if the Worker#user method is not called in the after_fork hooks
|
|
128
163
|
# +group+ is optional and will not change if unspecified.
|
|
129
164
|
def user(user, group = nil)
|
|
130
|
-
var = :user
|
|
165
|
+
var = _check_in_block(nil, :user)
|
|
131
166
|
@block and raise "#{var} is not valid inside #{@block.type}"
|
|
132
167
|
# raises ArgumentError on invalid user/group
|
|
133
168
|
Etc.getpwnam(user)
|
|
@@ -151,12 +186,17 @@ class Yahns::Config # :nodoc:
|
|
|
151
186
|
address = expand_addr(address)
|
|
152
187
|
String === address or
|
|
153
188
|
raise ArgumentError, "address=#{address.inspect} must be a string"
|
|
154
|
-
[ :umask, :backlog
|
|
189
|
+
[ :umask, :backlog ].each do |key|
|
|
190
|
+
# :backlog may be negative on some OSes
|
|
155
191
|
value = options[key] or next
|
|
156
192
|
Integer === value or
|
|
157
193
|
raise ArgumentError, "#{var}: not an integer: #{key}=#{value.inspect}"
|
|
158
194
|
end
|
|
159
|
-
[ :
|
|
195
|
+
[ :sndbuf, :rcvbuf, :threads ].each do |key|
|
|
196
|
+
value = options[key] and _check_int(key, value, 1)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
[ :ipv6only, :reuseport ].each do |key|
|
|
160
200
|
(value = options[key]).nil? and next
|
|
161
201
|
[ true, false ].include?(value) or
|
|
162
202
|
raise ArgumentError, "#{var}: not boolean: #{key}=#{value.inspect}"
|
|
@@ -197,16 +237,33 @@ class Yahns::Config # :nodoc:
|
|
|
197
237
|
/:/ =~ addr ? "[#{addr}]:#{port}" : "#{addr}:#{port}"
|
|
198
238
|
end
|
|
199
239
|
|
|
200
|
-
def queue(
|
|
240
|
+
def queue(*args, &block)
|
|
201
241
|
var = :queue
|
|
202
|
-
qegg = @qeggs[name] ||= Yahns::QueueEgg.new
|
|
203
242
|
prev_block = @block
|
|
204
|
-
|
|
243
|
+
if prev_block
|
|
244
|
+
_check_in_block(:app, var)
|
|
245
|
+
if block_given?
|
|
246
|
+
args.size == 0 or
|
|
247
|
+
raise ArgumentError,
|
|
248
|
+
"queues defined with a block inside app must not have names"
|
|
249
|
+
name = @block
|
|
250
|
+
else
|
|
251
|
+
name = args[0] or
|
|
252
|
+
raise ArgumentError, "queue must be given a name if no block given"
|
|
253
|
+
end
|
|
254
|
+
else
|
|
255
|
+
name = args[0] || :default
|
|
256
|
+
end
|
|
257
|
+
args.size > 1 and
|
|
258
|
+
raise ArgumentError, "queue only takes one name argument"
|
|
259
|
+
qegg = @qeggs[name]
|
|
205
260
|
if block_given?
|
|
206
261
|
@block = CfgBlock.new(:queue, qegg)
|
|
207
262
|
instance_eval(&block)
|
|
208
263
|
@block = prev_block
|
|
209
264
|
end
|
|
265
|
+
|
|
266
|
+
# associate the queue if we're inside an app
|
|
210
267
|
prev_block.ctx.qegg = qegg if prev_block
|
|
211
268
|
end
|
|
212
269
|
|
|
@@ -226,12 +283,19 @@ class Yahns::Config # :nodoc:
|
|
|
226
283
|
n
|
|
227
284
|
end
|
|
228
285
|
|
|
286
|
+
def _check_num(var, n, min)
|
|
287
|
+
Numeric === n or raise ArgumentError, "not a number: #{var}=#{n.inspect}"
|
|
288
|
+
n >= min or raise ArgumentError, "too low (< #{min}): #{var}=#{n.inspect}"
|
|
289
|
+
n
|
|
290
|
+
end
|
|
291
|
+
|
|
229
292
|
# global
|
|
230
293
|
def client_expire_threshold(val)
|
|
231
294
|
var = _check_in_block(nil, :client_expire_threshold)
|
|
232
295
|
case val
|
|
233
296
|
when Float
|
|
234
|
-
val
|
|
297
|
+
(val > 0 && val <= 1.0) or
|
|
298
|
+
raise ArgumentError, "#{var} must be > 0 and <= 1.0 if a ratio"
|
|
235
299
|
when Integer
|
|
236
300
|
else
|
|
237
301
|
raise ArgumentError, "#{var} must be a float or integer"
|
|
@@ -270,9 +334,7 @@ class Yahns::Config # :nodoc:
|
|
|
270
334
|
end
|
|
271
335
|
|
|
272
336
|
# boolean config directives for app
|
|
273
|
-
%w(check_client_connection
|
|
274
|
-
output_buffering
|
|
275
|
-
persistent_connections).each do |_v|
|
|
337
|
+
%w(check_client_connection persistent_connections).each do |_v|
|
|
276
338
|
eval(
|
|
277
339
|
%Q(def #{_v}(bool);) <<
|
|
278
340
|
%Q( _check_in_block(:app, :#{_v});) <<
|
|
@@ -281,13 +343,27 @@ class Yahns::Config # :nodoc:
|
|
|
281
343
|
)
|
|
282
344
|
end
|
|
283
345
|
|
|
346
|
+
def output_buffering(bool, opts = {})
|
|
347
|
+
var = _check_in_block(:app, :output_buffering)
|
|
348
|
+
@block.ctx.__send__("#{var}=", _check_bool(var, bool))
|
|
349
|
+
tmpdir = opts[:tmpdir] and
|
|
350
|
+
@block.ctx.output_buffer_tmpdir = _check_tmpdir(var, tmpdir)
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def _check_tmpdir(var, path)
|
|
354
|
+
File.directory?(path) or
|
|
355
|
+
raise ArgumentError, "#{var} tmpdir: #{path} is not a directory"
|
|
356
|
+
File.writable?(path) or
|
|
357
|
+
raise ArgumentError, "#{var} tmpdir: #{path} is not writable"
|
|
358
|
+
path
|
|
359
|
+
end
|
|
360
|
+
|
|
284
361
|
# integer config directives for app
|
|
285
362
|
{
|
|
286
363
|
# config name, minimum value
|
|
287
364
|
client_body_buffer_size: 1,
|
|
288
365
|
client_header_buffer_size: 1,
|
|
289
366
|
client_max_header_size: 1,
|
|
290
|
-
client_timeout: 0,
|
|
291
367
|
}.each do |_v,minval|
|
|
292
368
|
eval(
|
|
293
369
|
%Q(def #{_v}(val);) <<
|
|
@@ -297,18 +373,25 @@ class Yahns::Config # :nodoc:
|
|
|
297
373
|
)
|
|
298
374
|
end
|
|
299
375
|
|
|
376
|
+
def client_timeout(val)
|
|
377
|
+
var = _check_in_block(:app, :client_timeout)
|
|
378
|
+
@block.ctx.__send__("#{var}=", _check_num(var, val, 0))
|
|
379
|
+
end
|
|
380
|
+
|
|
300
381
|
def client_max_body_size(val)
|
|
301
382
|
var = _check_in_block(:app, :client_max_body_size)
|
|
302
383
|
val = _check_int(var, val, 0) if val != nil
|
|
303
384
|
@block.ctx.__send__("#{var}=", val)
|
|
304
385
|
end
|
|
305
386
|
|
|
306
|
-
def input_buffering(val)
|
|
387
|
+
def input_buffering(val, opts = {})
|
|
307
388
|
var = _check_in_block(:app, :input_buffering)
|
|
308
389
|
ok = [ :lazy, true, false ]
|
|
309
390
|
ok.include?(val) or
|
|
310
391
|
raise ArgumentError, "`#{var}' must be one of: #{ok.inspect}"
|
|
311
392
|
@block.ctx.__send__("#{var}=", val)
|
|
393
|
+
tmpdir = opts[:tmpdir] and
|
|
394
|
+
@block.ctx.input_buffer_tmpdir = _check_tmpdir(var, tmpdir)
|
|
312
395
|
end
|
|
313
396
|
|
|
314
397
|
# used to configure rack.errors destination
|
|
@@ -335,14 +418,16 @@ class Yahns::Config # :nodoc:
|
|
|
335
418
|
@set[key] = path = "/dev/null"
|
|
336
419
|
end
|
|
337
420
|
File.open(path, 'a') { |fp| io.reopen(fp) } if String === path
|
|
338
|
-
io.
|
|
421
|
+
io.sync = true
|
|
339
422
|
end
|
|
340
423
|
|
|
341
|
-
[ :logger, :pid, :worker_processes
|
|
424
|
+
[ :logger, :pid, :worker_processes, :user, :shutdown_timeout, :before_exec,
|
|
425
|
+
:atfork_prepare, :atfork_parent, :atfork_child
|
|
426
|
+
].each do |var|
|
|
342
427
|
val = @set[var]
|
|
343
428
|
server.__send__("#{var}=", val) if val != :unset
|
|
344
429
|
end
|
|
345
|
-
|
|
430
|
+
|
|
346
431
|
@app_ctx.each { |app| app.logger ||= server.logger }
|
|
347
432
|
end
|
|
348
433
|
end
|