yahns 1.12.5 → 1.13.0
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/Documentation/yahns-rackup.pod +0 -10
- data/Documentation/yahns_config.pod +3 -0
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/NEWS +80 -0
- data/examples/init.sh +34 -9
- data/examples/logrotate.conf +5 -0
- data/examples/yahns.socket +17 -0
- data/examples/yahns@.service +50 -0
- data/examples/yahns_rack_basic.conf.rb +0 -6
- data/extras/autoindex.rb +3 -2
- data/extras/exec_cgi.rb +1 -0
- data/extras/try_gzip_static.rb +19 -5
- data/lib/yahns/chunk_body.rb +27 -0
- data/lib/yahns/fdmap.rb +7 -4
- data/lib/yahns/http_client.rb +39 -10
- data/lib/yahns/http_response.rb +41 -22
- data/lib/yahns/openssl_client.rb +7 -3
- data/lib/yahns/proxy_http_response.rb +132 -159
- data/lib/yahns/proxy_pass.rb +6 -170
- data/lib/yahns/queue_epoll.rb +1 -0
- data/lib/yahns/queue_kqueue.rb +1 -0
- data/lib/yahns/req_res.rb +164 -0
- data/lib/yahns/server.rb +2 -1
- data/lib/yahns/server_mp.rb +1 -1
- data/lib/yahns/version.rb +1 -1
- data/lib/yahns/wbuf.rb +5 -6
- data/lib/yahns/wbuf_common.rb +5 -10
- data/lib/yahns/wbuf_lite.rb +111 -0
- data/man/yahns-rackup.1 +29 -29
- data/man/yahns_config.5 +47 -35
- data/test/helper.rb +12 -0
- data/test/test_auto_chunk.rb +56 -0
- data/test/test_extras_exec_cgi.rb +1 -3
- data/test/test_extras_try_gzip_static.rb +30 -16
- data/test/test_output_buffering.rb +5 -1
- data/test/test_proxy_pass.rb +2 -2
- data/test/test_proxy_pass_no_buffering.rb +170 -0
- data/test/test_reopen_logs.rb +5 -1
- data/test/test_response.rb +42 -0
- data/test/test_server.rb +35 -0
- data/test/test_ssl.rb +0 -6
- data/test/test_tmpio.rb +4 -0
- data/test/test_wbuf.rb +11 -4
- metadata +10 -4
- data/lib/yahns/sendfile_compat.rb +0 -24
@@ -0,0 +1,164 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2013-2016 all contributors <yahns-public@yhbt.net>
|
3
|
+
# License: GPL-3.0+ (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
# frozen_string_literal: true
|
5
|
+
# Only used by Yahns::ProxyPass
|
6
|
+
require 'kcar' # gem install kcar
|
7
|
+
require 'kgio'
|
8
|
+
|
9
|
+
class Yahns::ReqRes < Kgio::Socket # :nodoc:
|
10
|
+
attr_accessor :resbuf
|
11
|
+
attr_accessor :proxy_trailers
|
12
|
+
attr_accessor :alive
|
13
|
+
attr_reader :proxy_pass
|
14
|
+
|
15
|
+
def req_start(c, req, input, chunked, proxy_pass)
|
16
|
+
@hdr = @resbuf = nil
|
17
|
+
@yahns_client = c
|
18
|
+
@rrstate = input ? [ req, input, chunked ] : req
|
19
|
+
@proxy_pass = proxy_pass
|
20
|
+
Thread.current[:yahns_queue].queue_add(self, Yahns::Queue::QEV_WR)
|
21
|
+
end
|
22
|
+
|
23
|
+
def yahns_step # yahns event loop entry point
|
24
|
+
c = @yahns_client
|
25
|
+
case req = @rrstate
|
26
|
+
when Kcar::Parser # reading response...
|
27
|
+
buf = Thread.current[:yahns_rbuf]
|
28
|
+
|
29
|
+
case resbuf = @resbuf # where are we at the response?
|
30
|
+
when nil # common case, catch the response header in a single read
|
31
|
+
|
32
|
+
case rv = kgio_tryread(0x2000, buf)
|
33
|
+
when String
|
34
|
+
if res = req.headers(@hdr = [], rv)
|
35
|
+
return c.proxy_response_start(res, rv, req, self)
|
36
|
+
else # ugh, big headers or tricked response
|
37
|
+
# we must reinitialize the thread-local rbuf if it may
|
38
|
+
# live beyond the current thread
|
39
|
+
buf = Thread.current[:yahns_rbuf] = ''.dup
|
40
|
+
@resbuf = rv
|
41
|
+
end
|
42
|
+
# continue looping in middle "case @resbuf" loop
|
43
|
+
when :wait_readable
|
44
|
+
return rv # spurious wakeup
|
45
|
+
when nil
|
46
|
+
return c.proxy_err_response(502, self, 'upstream EOF (headers)')
|
47
|
+
end # NOT looping here
|
48
|
+
|
49
|
+
when String # continue reading trickled response headers from upstream
|
50
|
+
|
51
|
+
case rv = kgio_tryread(0x2000, buf)
|
52
|
+
when String then res = req.headers(@hdr, resbuf << rv) and break
|
53
|
+
when :wait_readable then return rv
|
54
|
+
when nil
|
55
|
+
return c.proxy_err_response(502, self, 'upstream EOF (big headers)')
|
56
|
+
end while true
|
57
|
+
@resbuf = false
|
58
|
+
|
59
|
+
return c.proxy_response_start(res, resbuf, req, self)
|
60
|
+
|
61
|
+
when Yahns::WbufCommon # streaming/buffering the response body
|
62
|
+
|
63
|
+
return c.proxy_response_finish(req, self)
|
64
|
+
|
65
|
+
end while true # case @resbuf
|
66
|
+
|
67
|
+
when Array # [ (str|vec), rack.input, chunked? ]
|
68
|
+
send_req_body(req) # returns nil or :wait_writable
|
69
|
+
when String # buffered request header
|
70
|
+
send_req_buf(req)
|
71
|
+
end
|
72
|
+
rescue => e
|
73
|
+
# avoid polluting logs with a giant backtrace when the problem isn't
|
74
|
+
# fixable in code.
|
75
|
+
case e
|
76
|
+
when Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EPIPE
|
77
|
+
e.set_backtrace([])
|
78
|
+
end
|
79
|
+
c.proxy_err_response(502, self, e)
|
80
|
+
end
|
81
|
+
|
82
|
+
def send_req_body_chunk(buf)
|
83
|
+
case rv = String === buf ? kgio_trywrite(buf) : kgio_trywritev(buf)
|
84
|
+
when String, Array
|
85
|
+
buf.replace(rv) # retry loop on partial write
|
86
|
+
when :wait_writable, nil
|
87
|
+
# :wait_writable = upstream is reading slowly and making us wait
|
88
|
+
return rv
|
89
|
+
else
|
90
|
+
abort "BUG: #{rv.inspect} from kgio_trywrite*"
|
91
|
+
end while true
|
92
|
+
end
|
93
|
+
|
94
|
+
# returns :wait_readable if complete, :wait_writable if not
|
95
|
+
def send_req_body(req) # @rrstate == [ (str|vec), rack.input, chunked? ]
|
96
|
+
buf, input, chunked = req
|
97
|
+
|
98
|
+
# send the first buffered chunk or vector
|
99
|
+
rv = send_req_body_chunk(buf) and return rv # :wait_writable
|
100
|
+
|
101
|
+
# yay, sent the first chunk, now read the body!
|
102
|
+
rbuf = buf
|
103
|
+
if chunked
|
104
|
+
if String === buf # initial body
|
105
|
+
req[0] = buf = []
|
106
|
+
else
|
107
|
+
# try to reuse the biggest non-frozen buffer we just wrote;
|
108
|
+
rbuf = buf.max_by(&:size)
|
109
|
+
rbuf = ''.dup if rbuf.frozen? # unlikely...
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Note: input (env['rack.input']) is fully-buffered by default so
|
114
|
+
# we should not be waiting on a slow network resource when reading
|
115
|
+
# input. However, some weird configs may disable this on LANs
|
116
|
+
# and we may wait indefinitely on input.read here...
|
117
|
+
while input.read(0x2000, rbuf)
|
118
|
+
if chunked
|
119
|
+
buf[0] = "#{rbuf.size.to_s(16)}\r\n".freeze
|
120
|
+
buf[1] = rbuf
|
121
|
+
buf[2] = "\r\n".freeze
|
122
|
+
end
|
123
|
+
rv = send_req_body_chunk(buf) and return rv # :wait_writable
|
124
|
+
end
|
125
|
+
|
126
|
+
rbuf.clear # all done, clear the big buffer
|
127
|
+
|
128
|
+
# we cannot use respond_to?(:close) here since Rack::Lint::InputWrapper
|
129
|
+
# tries to prevent that (and hijack means all Rack specs go out the door)
|
130
|
+
case input
|
131
|
+
when Yahns::TeeInput, IO
|
132
|
+
input.close
|
133
|
+
end
|
134
|
+
|
135
|
+
# note: we do not send any trailer, they are folded into the header
|
136
|
+
# because this relies on full request buffering
|
137
|
+
# prepare_wait_readable is called by send_req_buf
|
138
|
+
chunked ? send_req_buf("0\r\n\r\n".freeze) : prepare_wait_readable
|
139
|
+
rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ENOTCONN
|
140
|
+
# no more reading off the client socket, just prepare to forward
|
141
|
+
# the rejection response from the upstream (if any)
|
142
|
+
@yahns_client.to_io.shutdown(Socket::SHUT_RD)
|
143
|
+
prepare_wait_readable
|
144
|
+
end
|
145
|
+
|
146
|
+
def prepare_wait_readable
|
147
|
+
@rrstate = Kcar::Parser.new
|
148
|
+
:wait_readable # all done sending the request, wait for response
|
149
|
+
end
|
150
|
+
|
151
|
+
# n.b. buf must be a detached string not shared with
|
152
|
+
# Thread.current[:yahns_rbuf] of any thread
|
153
|
+
def send_req_buf(buf)
|
154
|
+
case rv = kgio_trywrite(buf)
|
155
|
+
when String
|
156
|
+
buf = rv # retry inner loop
|
157
|
+
when :wait_writable
|
158
|
+
@rrstate = buf
|
159
|
+
return :wait_writable
|
160
|
+
when nil
|
161
|
+
return prepare_wait_readable
|
162
|
+
end while true
|
163
|
+
end
|
164
|
+
end # class ReqRes
|
data/lib/yahns/server.rb
CHANGED
@@ -496,7 +496,8 @@ class Yahns::Server # :nodoc:
|
|
496
496
|
def dropping(fdmap)
|
497
497
|
if drop_acceptors[0] || fdmap.size > 0
|
498
498
|
timeout = @shutdown_expire < Yahns.now ? -1 : @shutdown_timeout
|
499
|
-
fdmap.desperate_expire(timeout)
|
499
|
+
n = fdmap.desperate_expire(timeout)
|
500
|
+
$0 = "yahns quitting, #{n} FD(s) remain"
|
500
501
|
true
|
501
502
|
else
|
502
503
|
false
|
data/lib/yahns/server_mp.rb
CHANGED
@@ -159,7 +159,7 @@ module Yahns::ServerMP # :nodoc:
|
|
159
159
|
def mp_sig_handle(watch, alive)
|
160
160
|
# not performance critical
|
161
161
|
watch.delete_if { |io| io.to_io.closed? }
|
162
|
-
if r = IO.select(watch, nil, nil, alive ? nil : 0.
|
162
|
+
if r = IO.select(watch, nil, nil, alive ? nil : 0.1)
|
163
163
|
r[0].each(&:yahns_step)
|
164
164
|
end
|
165
165
|
case @sig_queue.shift
|
data/lib/yahns/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
Yahns::VERSION = '1.
|
1
|
+
Yahns::VERSION = '1.13.0'.freeze # :nodoc:
|
data/lib/yahns/wbuf.rb
CHANGED
@@ -31,15 +31,13 @@ require_relative 'wbuf_common'
|
|
31
31
|
class Yahns::Wbuf # :nodoc:
|
32
32
|
include Yahns::WbufCommon
|
33
33
|
attr_reader :busy
|
34
|
-
attr_reader :wbuf_persist
|
35
34
|
|
36
|
-
def initialize(body, persist
|
35
|
+
def initialize(body, persist)
|
37
36
|
@tmpio = nil
|
38
|
-
@tmpdir = tmpdir
|
39
37
|
@sf_offset = @sf_count = 0
|
40
38
|
@wbuf_persist = persist # whether or not we keep the connection alive
|
41
|
-
@body = body
|
42
|
-
@busy =
|
39
|
+
@body = body # something we call #close on when done writing
|
40
|
+
@busy = false
|
43
41
|
end
|
44
42
|
|
45
43
|
def wbuf_writev(buf)
|
@@ -59,7 +57,8 @@ class Yahns::Wbuf # :nodoc:
|
|
59
57
|
@busy = rv
|
60
58
|
end until @busy
|
61
59
|
|
62
|
-
@tmpio ||= Yahns::TmpIO.new(
|
60
|
+
@tmpio ||= Yahns::TmpIO.new(c.class.output_buffer_tmpdir)
|
61
|
+
# n.b.: we rely on O_APPEND in TmpIO, here
|
63
62
|
@sf_count += String === buf ? @tmpio.write(buf) : wbuf_writev(buf)
|
64
63
|
|
65
64
|
# we spent some time copying to the FS, try to write to
|
data/lib/yahns/wbuf_common.rb
CHANGED
@@ -2,14 +2,6 @@
|
|
2
2
|
# Copyright (C) 2013-2016 all contributors <yahns-public@yhbt.net>
|
3
3
|
# License: GPL-3.0+ (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
4
|
# frozen_string_literal: true
|
5
|
-
begin
|
6
|
-
raise LoadError, "SENDFILE_BROKEN env set" if ENV["SENDFILE_BROKEN"]
|
7
|
-
require 'sendfile'
|
8
|
-
rescue LoadError
|
9
|
-
require_relative 'sendfile_compat'
|
10
|
-
IO.__send__ :include, Yahns::SendfileCompat
|
11
|
-
end
|
12
|
-
|
13
5
|
module Yahns::WbufCommon # :nodoc:
|
14
6
|
# returns true / false for persistent/non-persistent connections
|
15
7
|
# returns :wait_*able when blocked
|
@@ -19,7 +11,10 @@ module Yahns::WbufCommon # :nodoc:
|
|
19
11
|
def wbuf_flush(client)
|
20
12
|
case rv = client.trysendfile(@tmpio, @sf_offset, @sf_count)
|
21
13
|
when Integer
|
22
|
-
|
14
|
+
if (@sf_count -= rv) == 0 # all sent!
|
15
|
+
@sf_offset = 0
|
16
|
+
return wbuf_close(client)
|
17
|
+
end
|
23
18
|
|
24
19
|
@sf_offset += rv # keep going otherwise
|
25
20
|
when :wait_writable, :wait_readable
|
@@ -48,7 +43,7 @@ module Yahns::WbufCommon # :nodoc:
|
|
48
43
|
if @wbuf_persist.respond_to?(:call) # hijack
|
49
44
|
client.response_hijacked(@wbuf_persist) # :ignore
|
50
45
|
else
|
51
|
-
@wbuf_persist # true
|
46
|
+
@wbuf_persist # true, false, :ignore, or Yahns::StreamFile
|
52
47
|
end
|
53
48
|
end
|
54
49
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2016 all contributors <yahns-public@yhbt.net>
|
3
|
+
# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
|
4
|
+
# frozen_string_literal: true
|
5
|
+
require 'stringio'
|
6
|
+
require_relative 'wbuf_common'
|
7
|
+
|
8
|
+
# This is only used for "proxy_buffering: false"
|
9
|
+
class Yahns::WbufLite # :nodoc:
|
10
|
+
include Yahns::WbufCommon
|
11
|
+
attr_reader :busy
|
12
|
+
attr_writer :req_res
|
13
|
+
|
14
|
+
def initialize(req_res)
|
15
|
+
@tmpio = nil
|
16
|
+
@sf_offset = @sf_count = 0
|
17
|
+
@wbuf_persist = :ignore
|
18
|
+
@busy = false
|
19
|
+
@req_res = req_res
|
20
|
+
end
|
21
|
+
|
22
|
+
def wbuf_write(c, buf)
|
23
|
+
buf = buf.join if Array === buf
|
24
|
+
# try to bypass the VFS layer and write directly to the socket
|
25
|
+
# if we're all caught up
|
26
|
+
case rv = c.kgio_trywrite(buf)
|
27
|
+
when String
|
28
|
+
buf = rv # retry in loop
|
29
|
+
when nil
|
30
|
+
return # yay! hopefully we don't have to buffer again
|
31
|
+
when :wait_writable, :wait_readable
|
32
|
+
@busy = rv
|
33
|
+
end until @busy
|
34
|
+
|
35
|
+
@tmpio ||= StringIO.new(''.dup) # relies on encoding: binary above
|
36
|
+
@tmpio.seek(0, 2) # fake O_APPEND behavior
|
37
|
+
@sf_count += @tmpio.write(buf)
|
38
|
+
|
39
|
+
# we spent some time copying to the FS, try to write to
|
40
|
+
# the socket again in case some space opened up...
|
41
|
+
case rv = c.trysendio(@tmpio, @sf_offset, @sf_count)
|
42
|
+
when Integer
|
43
|
+
@sf_count -= rv
|
44
|
+
@sf_offset += rv
|
45
|
+
when :wait_writable, :wait_readable
|
46
|
+
@busy = rv
|
47
|
+
return rv
|
48
|
+
else
|
49
|
+
raise "BUG: #{rv.nil? ? 'EOF' : rv.inspect} on " \
|
50
|
+
"tmpio.size=#{@tmpio.size} " \
|
51
|
+
"sf_offset=#@sf_offset sf_count=#@sf_count"
|
52
|
+
end while @sf_count > 0
|
53
|
+
|
54
|
+
# we're all caught up, try to save some memory if we can help it.
|
55
|
+
wbuf_abort
|
56
|
+
@busy = false
|
57
|
+
nil
|
58
|
+
rescue
|
59
|
+
@req_res = @req_res.close if @req_res
|
60
|
+
raise
|
61
|
+
end
|
62
|
+
|
63
|
+
def wbuf_flush(client)
|
64
|
+
case rv = client.trysendio(@tmpio, @sf_offset, @sf_count)
|
65
|
+
when Integer
|
66
|
+
return wbuf_close(client) if (@sf_count -= rv) == 0 # all sent!
|
67
|
+
@sf_offset += rv # keep going otherwise
|
68
|
+
when :wait_writable, :wait_readable
|
69
|
+
return rv
|
70
|
+
else
|
71
|
+
raise "BUG: #{rv.nil? ? 'EOF' : rv.inspect} on " \
|
72
|
+
"tmpio.size=#{@tmpio.size} " \
|
73
|
+
"sf_offset=#@sf_offset sf_count=#@sf_count"
|
74
|
+
end while @sf_count > 0
|
75
|
+
wbuf_close(client)
|
76
|
+
rescue
|
77
|
+
@wbuf_persist = false # ensure a hijack response is not called
|
78
|
+
@req_res = @req_res.close if @req_res
|
79
|
+
wbuf_close(client)
|
80
|
+
raise
|
81
|
+
end
|
82
|
+
|
83
|
+
# called by Yahns::HttpClient#step_write
|
84
|
+
def wbuf_close(client)
|
85
|
+
wbuf_abort if @tmpio
|
86
|
+
|
87
|
+
# resume the event loop when @blocked is empty
|
88
|
+
# The actual Yahns::ReqRes#yahns_step is actually read/write-event
|
89
|
+
# agnostic, and we should actually watch for writability here since
|
90
|
+
# the req_res socket itself could be completely drained of readable
|
91
|
+
# data and just waiting for another request (which we don't support, yet)
|
92
|
+
if @req_res
|
93
|
+
@busy = false
|
94
|
+
client.hijack_cleanup
|
95
|
+
Thread.current[:yahns_queue].queue_mod(@req_res, Yahns::Queue::QEV_WR)
|
96
|
+
return :ignore
|
97
|
+
end
|
98
|
+
@wbuf_persist
|
99
|
+
rescue
|
100
|
+
@req_res = @req_res.close if @req_res
|
101
|
+
raise
|
102
|
+
end
|
103
|
+
|
104
|
+
def wbuf_abort
|
105
|
+
@sf_offset = @sf_count = 0
|
106
|
+
# we can safely truncate since this is a StringIO, we cannot do this
|
107
|
+
# with a real file because zero-copy with sendfile means truncating
|
108
|
+
# a while could clobber in-flight data
|
109
|
+
@tmpio.truncate(0)
|
110
|
+
end
|
111
|
+
end
|
data/man/yahns-rackup.1
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
.\" Automatically generated by Pod::Man 2.
|
1
|
+
.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28)
|
2
2
|
.\"
|
3
3
|
.\" Standard preamble:
|
4
4
|
.\" ========================================================================
|
@@ -38,6 +38,8 @@
|
|
38
38
|
. ds PI \(*p
|
39
39
|
. ds L" ``
|
40
40
|
. ds R" ''
|
41
|
+
. ds C`
|
42
|
+
. ds C'
|
41
43
|
'br\}
|
42
44
|
.\"
|
43
45
|
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
@@ -48,17 +50,24 @@
|
|
48
50
|
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
49
51
|
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
50
52
|
.\" output yourself in some meaningful fashion.
|
51
|
-
|
52
|
-
.
|
53
|
-
.
|
53
|
+
.\"
|
54
|
+
.\" Avoid warning from groff about undefined register 'F'.
|
55
|
+
.de IX
|
54
56
|
..
|
55
|
-
.
|
56
|
-
.
|
57
|
-
|
58
|
-
.
|
59
|
-
.
|
57
|
+
.nr rF 0
|
58
|
+
.if \n(.g .if rF .nr rF 1
|
59
|
+
.if (\n(rF:(\n(.g==0)) \{
|
60
|
+
. if \nF \{
|
61
|
+
. de IX
|
62
|
+
. tm Index:\\$1\t\\n%\t"\\$2"
|
60
63
|
..
|
64
|
+
. if !\nF==2 \{
|
65
|
+
. nr % 0
|
66
|
+
. nr F 2
|
67
|
+
. \}
|
68
|
+
. \}
|
61
69
|
.\}
|
70
|
+
.rr rF
|
62
71
|
.\"
|
63
72
|
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
64
73
|
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
@@ -124,7 +133,7 @@
|
|
124
133
|
.\" ========================================================================
|
125
134
|
.\"
|
126
135
|
.IX Title "YAHNS-RACKUP 1"
|
127
|
-
.TH YAHNS-RACKUP 1 "1994-10-02" "yahns 1.12.
|
136
|
+
.TH YAHNS-RACKUP 1 "1994-10-02" "yahns 1.12.5.48.g013d" "yahns user manual"
|
128
137
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
129
138
|
.\" way too many mistakes in technical documents.
|
130
139
|
.if n .ad l
|
@@ -140,7 +149,7 @@ A \fIrackup\fR\|(1)\-like command to launch Rack applications using yahns.
|
|
140
149
|
It is expected to start in your application root (\s-1APP_ROOT\s0).
|
141
150
|
.SH "RACKUP FILE"
|
142
151
|
.IX Header "RACKUP FILE"
|
143
|
-
This defaults to \*(L"config.ru\*(R" in \s-1APP_ROOT\s0
|
152
|
+
This defaults to \*(L"config.ru\*(R" in \s-1APP_ROOT. \s0 It should be the same
|
144
153
|
file used by \fIrackup\fR\|(1) and other Rack launchers, it uses the
|
145
154
|
*Rack::Builder* \s-1DSL\s0 documented at:
|
146
155
|
.PP
|
@@ -157,8 +166,8 @@ default timeout. Lower this if you run out of FDs.
|
|
157
166
|
Default: 15 (seconds)
|
158
167
|
.IP "\-O listen=ADDRESS[,ADDRESS...]" 4
|
159
168
|
.IX Item "-O listen=ADDRESS[,ADDRESS...]"
|
160
|
-
Listens on a given \s-1ADDRESS
|
161
|
-
\&\s-1HOST:PORT\s0 or \s-1PATH
|
169
|
+
Listens on a given \s-1ADDRESS. ADDRESS\s0 may be in the form of
|
170
|
+
\&\s-1HOST:PORT\s0 or \s-1PATH, HOST:PORT\s0 is taken to mean a \s-1TCP\s0 socket
|
162
171
|
and \s-1PATH\s0 is meant to be a path to a \s-1UNIX\s0 domain socket.
|
163
172
|
Defaults to \*(L"0.0.0.0:9292\*(R" (all addresses on \s-1TCP\s0 port 9292).
|
164
173
|
Multiple addresses may be separated with commas.
|
@@ -204,11 +213,11 @@ Unless specified via stderr_path and stdout_path, stderr and stdout will
|
|
204
213
|
also be redirected to \*(L"/dev/null\*(R".
|
205
214
|
.IP "\-E, \-\-env \s-1RACK_ENV\s0" 4
|
206
215
|
.IX Item "-E, --env RACK_ENV"
|
207
|
-
Run under the given \s-1RACK_ENV\s0
|
216
|
+
Run under the given \s-1RACK_ENV. \s0 See the \*(L"\s-1RACK ENVIRONMENT\*(R"\s0 section
|
208
217
|
for more details.
|
209
218
|
.IP "\-o, \-\-host \s-1HOST\s0" 4
|
210
219
|
.IX Item "-o, --host HOST"
|
211
|
-
Listen on a \s-1TCP\s0 socket belonging to \s-1HOST
|
220
|
+
Listen on a \s-1TCP\s0 socket belonging to \s-1HOST,\s0 default is
|
212
221
|
\&\*(L"0.0.0.0\*(R" (all addresses).
|
213
222
|
If specified multiple times on the command-line, only the
|
214
223
|
last-specified value takes effect.
|
@@ -216,7 +225,7 @@ This option only exists for compatibility with the \fIrackup\fR\|(1) command,
|
|
216
225
|
use of \*(L"\-l\*(R"/\*(L"\-\-listen\*(R" switch is recommended instead.
|
217
226
|
.IP "\-p, \-\-port \s-1PORT\s0" 4
|
218
227
|
.IX Item "-p, --port PORT"
|
219
|
-
Listen on the specified \s-1TCP
|
228
|
+
Listen on the specified \s-1TCP PORT,\s0 default is 9292.
|
220
229
|
If specified multiple times on the command-line, only the last-specified
|
221
230
|
value takes effect.
|
222
231
|
This option only exists for compatibility with the \fIrackup\fR\|(1) command,
|
@@ -256,24 +265,15 @@ See Rack documentation for a description of the rackup file format.
|
|
256
265
|
The \s-1RACK_ENV\s0 variable is set by the aforementioned \-E switch.
|
257
266
|
If \s-1RACK_ENV\s0 is already set, it will be used unless \-E is used.
|
258
267
|
See rackup documentation for more details.
|
259
|
-
.SH "CAVEATS"
|
260
|
-
.IX Header "CAVEATS"
|
261
|
-
yahns is strict about buggy, non-compliant Rack applications.
|
262
|
-
Some existing servers work fine without \*(L"Content-Length\*(R" or
|
263
|
-
\&\*(L"Transfer-Encoding: chunked\*(R" response headers enforced by Rack::Lint.
|
264
|
-
Forgetting these headers with yahns causes clients to stall as they
|
265
|
-
assume more data is coming. Loading the Rack::ContentLength and/or
|
266
|
-
Rack::Chunked middlewares will set the necessary response headers
|
267
|
-
and fix your app.
|
268
268
|
.SH "CONTACT"
|
269
269
|
.IX Header "CONTACT"
|
270
|
-
All feedback welcome via plain-text mail to mailto:yahns\-public@yhbt.net
|
270
|
+
All feedback welcome via plain-text mail to <mailto:yahns\-public@yhbt.net>
|
271
271
|
No subscription is necessary to post to the mailing list.
|
272
|
-
List archives are available at http://yhbt.net/yahns\-public
|
272
|
+
List archives are available at <http://yhbt.net/yahns\-public/>
|
273
273
|
.SH "COPYRIGHT"
|
274
274
|
.IX Header "COPYRIGHT"
|
275
|
-
Copyright (C) 2013\-2016 all contributors mailto:yahns\-public@yhbt.net
|
276
|
-
License: \s-1GPL\-3
|
275
|
+
Copyright (C) 2013\-2016 all contributors <mailto:yahns\-public@yhbt.net>
|
276
|
+
License: \s-1GPL\-3.0+ \s0<http://www.gnu.org/licenses/gpl\-3.0.txt>
|
277
277
|
.SH "SEE ALSO"
|
278
278
|
.IX Header "SEE ALSO"
|
279
279
|
\&\fIyahns\fR\|(1), \fIyahns_config\fR\|(5),
|