yahns 1.14.1 → 1.18.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 +5 -5
- data/.document +2 -0
- data/.gitignore +0 -1
- data/.olddoc.yml +3 -2
- data/Documentation/GNUmakefile +1 -1
- data/Documentation/design_notes.txt +6 -3
- data/Documentation/yahns-rackup.pod +7 -3
- data/Documentation/yahns.pod +1 -1
- data/Documentation/yahns_config.pod +10 -10
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +3 -3
- data/HACKING +13 -13
- data/NEWS +982 -829
- data/README +11 -12
- data/Rakefile +121 -5
- data/examples/https_proxy_pass.conf.rb +36 -0
- data/examples/logrotate.conf +1 -1
- data/examples/proxy_pass.ru +11 -0
- data/extras/autoindex.rb +20 -4
- data/extras/exec_cgi.rb +38 -24
- data/extras/proxy_pass.rb +7 -6
- data/extras/try_gzip_static.rb +4 -1
- data/lib/yahns/acceptor.rb +3 -3
- data/lib/yahns/chunk_body.rb +2 -1
- data/lib/yahns/config.rb +10 -5
- data/lib/yahns/daemon.rb +0 -1
- data/lib/yahns/http_client.rb +28 -18
- data/lib/yahns/http_response.rb +3 -4
- data/lib/yahns/openssl_client.rb +33 -11
- data/lib/yahns/proxy_http_response.rb +3 -1
- data/lib/yahns/proxy_pass.rb +68 -10
- data/lib/yahns/queue_epoll.rb +4 -0
- data/lib/yahns/queue_kqueue.rb +0 -6
- data/lib/yahns/queue_quitter_pipe.rb +4 -1
- data/lib/yahns/rackup_handler.rb +3 -7
- data/lib/yahns/server.rb +47 -27
- data/lib/yahns/server_mp.rb +3 -4
- data/lib/yahns/sigevent_efd.rb +0 -1
- data/lib/yahns/sigevent_pipe.rb +13 -6
- data/lib/yahns/socket_helper.rb +1 -1
- data/lib/yahns/stream_input.rb +3 -2
- data/lib/yahns/tee_input.rb +1 -3
- data/lib/yahns/version.rb +1 -1
- data/lib/yahns/wbuf.rb +10 -3
- data/lib/yahns/worker.rb +8 -0
- data/lib/yahns.rb +12 -7
- data/man/yahns-rackup.1 +17 -17
- data/man/yahns.1 +11 -15
- data/man/yahns_config.5 +31 -31
- data/test/helper.rb +6 -2
- data/test/server_helper.rb +20 -5
- data/test/test_bin.rb +33 -30
- data/test/test_config.rb +2 -2
- data/test/test_extras_exec_cgi.rb +24 -1
- data/test/test_extras_try_gzip_static.rb +1 -1
- data/test/test_mt_accept.rb +0 -2
- data/test/test_proxy_pass.rb +1 -2
- data/test/test_proxy_pass_no_buffering.rb +1 -1
- data/test/test_rack_env.rb +58 -0
- data/test/test_serve_static.rb +0 -1
- data/test/test_server.rb +1 -4
- data/test/test_ssl.rb +2 -0
- data/test/test_unix_socket.rb +1 -3
- data/test/test_wbuf.rb +1 -1
- data/yahns.gemspec +8 -5
- metadata +12 -9
data/man/yahns-rackup.1
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
.\" Automatically generated by Pod::Man
|
1
|
+
.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32)
|
2
2
|
.\"
|
3
3
|
.\" Standard preamble:
|
4
4
|
.\" ========================================================================
|
@@ -46,7 +46,7 @@
|
|
46
46
|
.ie \n(.g .ds Aq \(aq
|
47
47
|
.el .ds Aq '
|
48
48
|
.\"
|
49
|
-
.\" If the F register is
|
49
|
+
.\" If the F register is >0, we'll generate index entries on stderr for
|
50
50
|
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
51
51
|
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
52
52
|
.\" output yourself in some meaningful fashion.
|
@@ -54,20 +54,16 @@
|
|
54
54
|
.\" Avoid warning from groff about undefined register 'F'.
|
55
55
|
.de IX
|
56
56
|
..
|
57
|
-
.nr
|
58
|
-
.if \
|
59
|
-
.
|
60
|
-
.
|
61
|
-
. de IX
|
62
|
-
. tm Index:\\$1\t\\n%\t"\\$2"
|
57
|
+
.if !\nF .nr F 0
|
58
|
+
.if \nF>0 \{\
|
59
|
+
. de IX
|
60
|
+
. tm Index:\\$1\t\\n%\t"\\$2"
|
63
61
|
..
|
64
|
-
.
|
65
|
-
.
|
66
|
-
.
|
67
|
-
. \}
|
62
|
+
. if !\nF==2 \{\
|
63
|
+
. nr % 0
|
64
|
+
. nr F 2
|
68
65
|
. \}
|
69
66
|
.\}
|
70
|
-
.rr rF
|
71
67
|
.\"
|
72
68
|
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
73
69
|
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
@@ -133,7 +129,7 @@
|
|
133
129
|
.\" ========================================================================
|
134
130
|
.\"
|
135
131
|
.IX Title "YAHNS-RACKUP 1"
|
136
|
-
.TH YAHNS-RACKUP 1 "1994-10-02" "yahns 1.
|
132
|
+
.TH YAHNS-RACKUP 1 "1994-10-02" "yahns 1.16.0.24.g39049" "yahns user manual"
|
137
133
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
138
134
|
.\" way too many mistakes in technical documents.
|
139
135
|
.if n .ad l
|
@@ -171,6 +167,10 @@ Listens on a given \s-1ADDRESS. ADDRESS\s0 may be in the form of
|
|
171
167
|
and \s-1PATH\s0 is meant to be a path to a \s-1UNIX\s0 domain socket.
|
172
168
|
Defaults to \*(L"0.0.0.0:9292\*(R" (all addresses on \s-1TCP\s0 port 9292).
|
173
169
|
Multiple addresses may be separated with commas.
|
170
|
+
.Sp
|
171
|
+
For systemd users, a special value of \*(L"inherit\*(R" may be specified
|
172
|
+
to inherit FDs using the \s-1LISTEN_FDS\s0 and \s-1LISTEN_PID\s0 environment
|
173
|
+
variables described in \fIsd_listen_fds\fR\|(3)
|
174
174
|
.IP "\-O stderr_path=PATHNAME" 4
|
175
175
|
.IX Item "-O stderr_path=PATHNAME"
|
176
176
|
Allow redirecting \f(CW$stderr\fR to a given path. Unlike doing this from
|
@@ -268,12 +268,12 @@ See rackup documentation for more details.
|
|
268
268
|
.SH "CONTACT"
|
269
269
|
.IX Header "CONTACT"
|
270
270
|
All feedback welcome via plain-text mail to <mailto:yahns\-public@yhbt.net>
|
271
|
-
No subscription is necessary to
|
272
|
-
|
271
|
+
No subscription is necessary to email us.
|
272
|
+
Mail archives are available at <https://yhbt.net/yahns\-public/>
|
273
273
|
.SH "COPYRIGHT"
|
274
274
|
.IX Header "COPYRIGHT"
|
275
275
|
Copyright (C) 2013\-2016 all contributors <mailto:yahns\-public@yhbt.net>
|
276
|
-
License: \s-1GPL\-3.0+ \s0<
|
276
|
+
License: \s-1GPL\-3.0+ \s0<https://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),
|
data/man/yahns.1
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
.\" Automatically generated by Pod::Man
|
1
|
+
.\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32)
|
2
2
|
.\"
|
3
3
|
.\" Standard preamble:
|
4
4
|
.\" ========================================================================
|
@@ -46,7 +46,7 @@
|
|
46
46
|
.ie \n(.g .ds Aq \(aq
|
47
47
|
.el .ds Aq '
|
48
48
|
.\"
|
49
|
-
.\" If the F register is
|
49
|
+
.\" If the F register is >0, we'll generate index entries on stderr for
|
50
50
|
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
51
51
|
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
52
52
|
.\" output yourself in some meaningful fashion.
|
@@ -54,20 +54,16 @@
|
|
54
54
|
.\" Avoid warning from groff about undefined register 'F'.
|
55
55
|
.de IX
|
56
56
|
..
|
57
|
-
.nr
|
58
|
-
.if \
|
59
|
-
.
|
60
|
-
.
|
61
|
-
. de IX
|
62
|
-
. tm Index:\\$1\t\\n%\t"\\$2"
|
57
|
+
.if !\nF .nr F 0
|
58
|
+
.if \nF>0 \{\
|
59
|
+
. de IX
|
60
|
+
. tm Index:\\$1\t\\n%\t"\\$2"
|
63
61
|
..
|
64
|
-
.
|
65
|
-
.
|
66
|
-
.
|
67
|
-
. \}
|
62
|
+
. if !\nF==2 \{\
|
63
|
+
. nr % 0
|
64
|
+
. nr F 2
|
68
65
|
. \}
|
69
66
|
.\}
|
70
|
-
.rr rF
|
71
67
|
.\"
|
72
68
|
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
73
69
|
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
@@ -133,7 +129,7 @@
|
|
133
129
|
.\" ========================================================================
|
134
130
|
.\"
|
135
131
|
.IX Title "YAHNS 1"
|
136
|
-
.TH YAHNS 1 "1994-10-02" "yahns 1.
|
132
|
+
.TH YAHNS 1 "1994-10-02" "yahns 1.16.0.24.g39049" "yahns user manual"
|
137
133
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
138
134
|
.\" way too many mistakes in technical documents.
|
139
135
|
.if n .ad l
|
@@ -205,7 +201,7 @@ See \fIyahns_config\fR\|(5) for documentation on the configuration file format.
|
|
205
201
|
.SH "CONTACT"
|
206
202
|
.IX Header "CONTACT"
|
207
203
|
All feedback welcome via plain-text mail to <mailto:yahns\-public@yhbt.net>
|
208
|
-
No subscription is necessary to
|
204
|
+
No subscription is necessary to email us.
|
209
205
|
Mail archives are available at <https://yhbt.net/yahns\-public/>
|
210
206
|
.SH "COPYRIGHT"
|
211
207
|
.IX Header "COPYRIGHT"
|
data/man/yahns_config.5
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
.\" Automatically generated by Pod::Man
|
1
|
+
.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35)
|
2
2
|
.\"
|
3
3
|
.\" Standard preamble:
|
4
4
|
.\" ========================================================================
|
@@ -46,7 +46,7 @@
|
|
46
46
|
.ie \n(.g .ds Aq \(aq
|
47
47
|
.el .ds Aq '
|
48
48
|
.\"
|
49
|
-
.\" If the F register is
|
49
|
+
.\" If the F register is >0, we'll generate index entries on stderr for
|
50
50
|
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
51
51
|
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
52
52
|
.\" output yourself in some meaningful fashion.
|
@@ -56,12 +56,12 @@
|
|
56
56
|
..
|
57
57
|
.nr rF 0
|
58
58
|
.if \n(.g .if rF .nr rF 1
|
59
|
-
.if (\n(rF:(\n(.g==0)) \{
|
60
|
-
. if \nF \{
|
59
|
+
.if (\n(rF:(\n(.g==0)) \{\
|
60
|
+
. if \nF \{\
|
61
61
|
. de IX
|
62
62
|
. tm Index:\\$1\t\\n%\t"\\$2"
|
63
63
|
..
|
64
|
-
. if !\nF==2 \{
|
64
|
+
. if !\nF==2 \{\
|
65
65
|
. nr % 0
|
66
66
|
. nr F 2
|
67
67
|
. \}
|
@@ -133,7 +133,7 @@
|
|
133
133
|
.\" ========================================================================
|
134
134
|
.\"
|
135
135
|
.IX Title "YAHNS_CONFIG 5"
|
136
|
-
.TH YAHNS_CONFIG 5 "1994-10-02" "yahns 1.
|
136
|
+
.TH YAHNS_CONFIG 5 "1994-10-02" "yahns 1.17.0.5.g4e5f" "yahns user manual"
|
137
137
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
138
138
|
.\" way too many mistakes in technical documents.
|
139
139
|
.if n .ad l
|
@@ -174,7 +174,7 @@ For Rack \s-1HTTP\s0 applications, see \*(L"\s-1RACK APP ARGUMENTS\*(R"\s0 for m
|
|
174
174
|
information.
|
175
175
|
.IP "before_exec &BLOCK" 4
|
176
176
|
.IX Item "before_exec &BLOCK"
|
177
|
-
This runs &BLOCK before Kernel#exec (\
|
177
|
+
This runs &BLOCK before Kernel#exec (\fBexecve\fR\|(2) wrapper). The command
|
178
178
|
array to be passed to Kernel#exec may be modified within this hook:
|
179
179
|
.Sp
|
180
180
|
.Vb 3
|
@@ -287,7 +287,7 @@ Default: / if daemonized, current working directory if not
|
|
287
287
|
.IP "max_events \s-1INTEGER\s0" 4
|
288
288
|
.IX Item "max_events INTEGER"
|
289
289
|
This controls the number of events a worker thread will fetch at
|
290
|
-
once via \
|
290
|
+
once via \fBepoll_wait\fR\|(2) or \fBkevent\fR\|(2).
|
291
291
|
There is no good reason to change this
|
292
292
|
unless you use very few (e.g. 1) worker_threads. Leaving this at
|
293
293
|
1 will give the fairest load balancing behavior with epoll or kqueue.
|
@@ -332,7 +332,7 @@ Default: false
|
|
332
332
|
This controls the maximum size of a request body before it is
|
333
333
|
buffered to the filesystem (instead of memory). This has no effect
|
334
334
|
if input_buffering is false. This also governs the size of an
|
335
|
-
individual \
|
335
|
+
individual \fBread\fR\|(2) system call when reading a request body.
|
336
336
|
.Sp
|
337
337
|
There is generally no need to change this value and this directive
|
338
338
|
may be removed in the future.
|
@@ -340,7 +340,7 @@ may be removed in the future.
|
|
340
340
|
Default: 8192 bytes (8 kilobytes)
|
341
341
|
.IP "client_header_buffer_size \s-1INTEGER\s0" 4
|
342
342
|
.IX Item "client_header_buffer_size INTEGER"
|
343
|
-
This controls the size of a single \
|
343
|
+
This controls the size of a single \fBread\fR\|(2) syscall for reading
|
344
344
|
client request headers. Increase this as needed if your application
|
345
345
|
uses large cookies or long URLs. Lowering this may reduce \s-1GC\s0 and
|
346
346
|
memory allocator overhead.
|
@@ -463,12 +463,12 @@ this means Unix domain sockets must not be placed in /tmp
|
|
463
463
|
The following \s-1OPTIONS\s0 may be specified (but are generally not needed):
|
464
464
|
.IP "backlog: \s-1INTEGER\s0" 4
|
465
465
|
.IX Item "backlog: INTEGER"
|
466
|
-
This is the backlog of the \
|
466
|
+
This is the backlog of the \fBlisten\fR\|(2) syscall.
|
467
467
|
.Sp
|
468
468
|
Some operating systems allow negative values here to specify the
|
469
469
|
maximum allowable value. In most cases, this number is only
|
470
470
|
recommendation and there are other OS-specific tunables and
|
471
|
-
variables that can affect this number. See the \
|
471
|
+
variables that can affect this number. See the \fBlisten\fR\|(2)
|
472
472
|
syscall documentation of your \s-1OS\s0 for the exact semantics of
|
473
473
|
this.
|
474
474
|
.Sp
|
@@ -495,7 +495,7 @@ Default: Operating-system dependent
|
|
495
495
|
Maximum receive and send buffer sizes (in bytes) of sockets.
|
496
496
|
.Sp
|
497
497
|
These correspond to the \s-1SO_RCVBUF\s0 and \s-1SO_SNDBUF\s0 settings which
|
498
|
-
can be set via the \
|
498
|
+
can be set via the \fBsetsockopt\fR\|(2) syscall. Some kernels
|
499
499
|
(e.g. Linux 2.4+) have intelligent auto-tuning mechanisms and
|
500
500
|
there is no need (and it is sometimes detrimental) to specify them.
|
501
501
|
.Sp
|
@@ -511,8 +511,8 @@ This enables multiple, independently-started yahns instances to
|
|
511
511
|
bind to the same port (as long as all the processes enable this).
|
512
512
|
.Sp
|
513
513
|
This option must be used when yahns first binds the listen socket.
|
514
|
-
It cannot be enabled when a socket is inherited via \s-1SIGUSR2
|
515
|
-
|
514
|
+
It cannot be enabled when a socket is inherited via \s-1SIGUSR2\s0
|
515
|
+
(but it will remain on if inherited), and it cannot be enabled
|
516
516
|
directly via \s-1SIGHUP.\s0
|
517
517
|
.Sp
|
518
518
|
Note: there is a chance of connections being dropped if
|
@@ -529,7 +529,7 @@ To enable \s-1TLS\s0 connections, you must configure this yourself.
|
|
529
529
|
See documentation for OpenSSL::SSL::SSLContext
|
530
530
|
for more information:
|
531
531
|
.Sp
|
532
|
-
<
|
532
|
+
<https://docs.ruby\-lang.org/en/trunk/OpenSSL/SSL/SSLContext.html>
|
533
533
|
.Sp
|
534
534
|
Default: none
|
535
535
|
.Sp
|
@@ -539,22 +539,22 @@ An example which seems to work is:
|
|
539
539
|
\& require \*(Aqopenssl\*(Aq
|
540
540
|
\& ssl_ctx = OpenSSL::SSL::SSLContext.new
|
541
541
|
\& ssl_ctx.cert = OpenSSL::X509::Certificate.new(
|
542
|
-
\&
|
542
|
+
\& File.read(\*(Aq/etc/ssl/certs/example.crt\*(Aq)
|
543
543
|
\& )
|
544
544
|
\& ssl_ctx.extra_chain_cert = [
|
545
545
|
\& OpenSSL::X509::Certificate.new(
|
546
|
-
\&
|
546
|
+
\& File.read(\*(Aq/etc/ssl/certs/chain.crt\*(Aq)
|
547
547
|
\& )
|
548
548
|
\& ]
|
549
549
|
\& ssl_ctx.key = OpenSSL::PKey::RSA.new(
|
550
|
-
\&
|
550
|
+
\& File.read(\*(Aq/etc/ssl/private/example.key\*(Aq)
|
551
551
|
\& )
|
552
552
|
\&
|
553
553
|
\& # use defaults provided by Ruby on top of OpenSSL,
|
554
|
-
\& # but disable client certificate verification as it is rare:
|
554
|
+
\& # but disable client certificate verification as it is rare for servers:
|
555
555
|
\& ssl_ctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
556
556
|
\&
|
557
|
-
\& # Built\-in session cache (only
|
557
|
+
\& # Built\-in session cache (only useful if worker_processes is nil or 1)
|
558
558
|
\& ssl_ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_SERVER
|
559
559
|
\&
|
560
560
|
\& app(:rack, "/path/to/my/app/config.ru") do
|
@@ -676,7 +676,7 @@ here means yahns will enable yahns to use a master/worker process
|
|
676
676
|
model instead of a single process.
|
677
677
|
.Sp
|
678
678
|
If an optional &BLOCK is given, it may be used to configure
|
679
|
-
\&\
|
679
|
+
\&\fBpthread_atfork\fR\|(3)\-style hooks.
|
680
680
|
See \*(L"\s-1WORKER_PROCESSES\-LEVEL DIRECTIVES\*(R"\s0 for details.
|
681
681
|
.Sp
|
682
682
|
Using worker_processes is strongly recommended if your application
|
@@ -692,7 +692,7 @@ Note: all of the atfork_* hooks described here are available inside the
|
|
692
692
|
\&\*(L"app\*(R" blocks, too.
|
693
693
|
.IP "atfork_prepare &BLOCK" 4
|
694
694
|
.IX Item "atfork_prepare &BLOCK"
|
695
|
-
This &BLOCK is executed in the parent before \
|
695
|
+
This &BLOCK is executed in the parent before \fBfork\fR\|(2) operation.
|
696
696
|
This may be useful for app directives which specify \*(L"preload: true\*(R"
|
697
697
|
to disconnect from databases or otherwise close open file descriptors
|
698
698
|
to prevent them from being shared with the children.
|
@@ -700,12 +700,12 @@ to prevent them from being shared with the children.
|
|
700
700
|
Default: none
|
701
701
|
.IP "atfork_parent &BLOCK" 4
|
702
702
|
.IX Item "atfork_parent &BLOCK"
|
703
|
-
This &BLOCK is executed in the parent after the \
|
703
|
+
This &BLOCK is executed in the parent after the \fBfork\fR\|(2) operation.
|
704
704
|
.Sp
|
705
705
|
Default: none
|
706
706
|
.IP "atfork_child &BLOCK" 4
|
707
707
|
.IX Item "atfork_child &BLOCK"
|
708
|
-
This &BLOCK is executed in the child after the \
|
708
|
+
This &BLOCK is executed in the child after the \fBfork\fR\|(2) operation.
|
709
709
|
.Sp
|
710
710
|
This may be useful for app directives which specify \*(L"preload: true\*(R"
|
711
711
|
to reconnect to databases or reopen closed file descriptors which
|
@@ -714,7 +714,7 @@ were closed in the atfork_prepare hook.
|
|
714
714
|
Default: none
|
715
715
|
.SH "RACK APP ARGUMENTS"
|
716
716
|
.IX Header "RACK APP ARGUMENTS"
|
717
|
-
Rack applications take a \s-1PATHNAME\s0 to the \
|
717
|
+
Rack applications take a \s-1PATHNAME\s0 to the \fBrackup\fR\|(1) config file
|
718
718
|
(e.g. \*(L"config.ru\*(R") as its first argument.
|
719
719
|
.PP
|
720
720
|
The only supported keyword argument is:
|
@@ -737,17 +737,17 @@ compatibility.
|
|
737
737
|
See the examples/ directory in the git source tree.
|
738
738
|
.PP
|
739
739
|
.Vb 1
|
740
|
-
\& git clone
|
740
|
+
\& git clone https://yhbt.net/yahns.git
|
741
741
|
.Ve
|
742
742
|
.SH "CONTACT"
|
743
743
|
.IX Header "CONTACT"
|
744
744
|
All feedback welcome via plain-text mail to <mailto:yahns\-public@yhbt.net>
|
745
|
-
No subscription is necessary to
|
746
|
-
|
745
|
+
No subscription is necessary to email us.
|
746
|
+
Mail archives are available at <https://yhbt.net/yahns\-public/>
|
747
747
|
.SH "COPYRIGHT"
|
748
748
|
.IX Header "COPYRIGHT"
|
749
749
|
Copyright (C) 2013\-2016 all contributors <mailto:yahns\-public@yhbt.net>
|
750
|
-
License: \s-1GPL\-3.0
|
750
|
+
License: \s-1GPL\-3.0+\s0 <https://www.gnu.org/licenses/gpl\-3.0.txt>
|
751
751
|
.SH "SEE ALSO"
|
752
752
|
.IX Header "SEE ALSO"
|
753
|
-
\&\
|
753
|
+
\&\fByahns\fR\|(1)
|
data/test/helper.rb
CHANGED
@@ -125,7 +125,7 @@ class IO
|
|
125
125
|
end if ! IO.method_defined?(:nread) && RUBY_PLATFORM =~ /linux/
|
126
126
|
|
127
127
|
def cloexec_pipe
|
128
|
-
IO.pipe
|
128
|
+
IO.pipe
|
129
129
|
end
|
130
130
|
|
131
131
|
def require_exec(cmd)
|
@@ -136,6 +136,10 @@ def require_exec(cmd)
|
|
136
136
|
false
|
137
137
|
end
|
138
138
|
|
139
|
+
def xfork
|
140
|
+
GTL.synchronize { fork { yield } }
|
141
|
+
end
|
142
|
+
|
139
143
|
class DieIfUsed
|
140
144
|
@@n = 0
|
141
145
|
def each
|
@@ -154,7 +158,7 @@ def skip_skb_mem
|
|
154
158
|
[ [ '/proc/sys/net/ipv4/tcp_rmem', "4096 87380 6291456\n" ],
|
155
159
|
[ '/proc/sys/net/ipv4/tcp_wmem', "4096 16384 4194304\n" ]
|
156
160
|
].each do |file, expect|
|
157
|
-
val =
|
161
|
+
val = File.read(file)
|
158
162
|
val == expect or skip "#{file} had: #{val}expected: #{expect}"
|
159
163
|
end
|
160
164
|
end
|
data/test/server_helper.rb
CHANGED
@@ -31,7 +31,7 @@ module ServerHelper
|
|
31
31
|
|
32
32
|
def quit_wait(pid)
|
33
33
|
pid or return
|
34
|
-
err = $!
|
34
|
+
err = $! and warn "Terminating on #{err.inspect} (#{err.class})"
|
35
35
|
Process.kill(:QUIT, pid)
|
36
36
|
_, status = Timeout.timeout(10) { Process.waitpid2(pid) }
|
37
37
|
assert status.success?, status.inspect
|
@@ -52,9 +52,7 @@ module ServerHelper
|
|
52
52
|
# only use for newly bound sockets
|
53
53
|
def get_tcp_client(host, port, tries = 500)
|
54
54
|
begin
|
55
|
-
|
56
|
-
c.close_on_exec = true
|
57
|
-
return c
|
55
|
+
return TCPSocket.new(host, port)
|
58
56
|
rescue Errno::ECONNREFUSED
|
59
57
|
raise if tries < 0
|
60
58
|
tries -= 1
|
@@ -65,16 +63,33 @@ module ServerHelper
|
|
65
63
|
@srv.close if defined?(@srv) && !@srv.closed?
|
66
64
|
@ru.close! if defined?(@ru) && @ru
|
67
65
|
check_err if defined?(@err)
|
66
|
+
Timeout.timeout(30) do
|
67
|
+
Process.kill(:TERM, @tail_pid)
|
68
|
+
Process.waitpid(@tail_pid)
|
69
|
+
end if @tail_pid
|
68
70
|
end
|
69
71
|
|
70
72
|
def server_helper_setup
|
71
73
|
@srv = TCPServer.new(ENV["TEST_HOST"] || "127.0.0.1", 0)
|
72
74
|
@err = tmpfile(%w(srv .err))
|
73
75
|
@ru = nil
|
76
|
+
@tail_pid = nil
|
77
|
+
case tail = ENV['TAIL']
|
78
|
+
when '1'
|
79
|
+
tail = 'tail -f' # POSIX
|
80
|
+
when nil, '0'
|
81
|
+
tail = nil
|
82
|
+
# else : allow users to specify 'tail -F' or 'gtail -F' for GNU
|
83
|
+
end
|
84
|
+
if tail
|
85
|
+
cmd = tail.split(/\s+/)
|
86
|
+
cmd << @err.path
|
87
|
+
@tail_pid = spawn(*cmd)
|
88
|
+
end
|
74
89
|
end
|
75
90
|
|
76
91
|
def mkserver(cfg, srv = @srv)
|
77
|
-
|
92
|
+
xfork do
|
78
93
|
ENV["YAHNS_FD"] = srv.fileno.to_s
|
79
94
|
srv.autoclose = false
|
80
95
|
yield if block_given?
|
data/test/test_bin.rb
CHANGED
@@ -9,40 +9,41 @@ class TestBin < Testcase
|
|
9
9
|
|
10
10
|
def setup
|
11
11
|
server_helper_setup
|
12
|
-
@cmd = %W(ruby -I lib bin/yahns)
|
12
|
+
@cmd = %W(#{RbConfig.ruby} -I lib bin/yahns)
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_listen_fd3
|
16
16
|
return unless RUBY_VERSION.to_f > 2.3 # Fixed in ruby/trunk r51209, actually
|
17
|
-
@srv.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, 0)
|
18
17
|
host, port = @srv.addr[3], @srv.addr[1]
|
19
18
|
|
20
19
|
ru = tmpfile(%w(test_bin_daemon .ru))
|
21
20
|
ru.write("require 'rack/lobster'; run Rack::Lobster.new\n")
|
22
|
-
cmd = %W(ruby -I lib bin/yahns-rackup
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
21
|
+
cmd = %W(#{RbConfig.ruby} -I lib bin/yahns-rackup -E none #{ru.path})
|
22
|
+
[ %w(-O listen=inherit), %W(-p #{port} -o #{host}) ].each do |opt|
|
23
|
+
@srv.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, 0)
|
24
|
+
begin
|
25
|
+
pid = xfork do # emulate a systemd environment
|
26
|
+
env = { 'LISTEN_PID' => $$.to_s, 'LISTEN_FDS' => '1' }
|
27
|
+
cmd.concat(opt)
|
28
|
+
exec env, *cmd, 3 => @srv, err: @err.path
|
29
|
+
end
|
30
|
+
Net::HTTP.start(host, port) do |http|
|
31
|
+
req = Net::HTTP::Get.new("/")
|
32
|
+
res = http.request(req)
|
33
|
+
assert_equal 200, res.code.to_i
|
34
|
+
assert_equal "keep-alive", res["Connection"]
|
35
|
+
end
|
36
|
+
assert @srv.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).bool,
|
37
|
+
'ensure the inheriting process applies TCP socket options'
|
38
|
+
ensure
|
39
|
+
if pid
|
40
|
+
Process.kill(:QUIT, pid)
|
41
|
+
_, status = Process.waitpid2(pid)
|
42
|
+
assert status.success?, status.inspect
|
43
|
+
end
|
44
|
+
end
|
36
45
|
end
|
37
|
-
|
38
|
-
assert_equal 1, @srv.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).int,
|
39
|
-
'ensure the inheriting process applies TCP socket options'
|
40
46
|
ensure
|
41
|
-
if pid
|
42
|
-
Process.kill(:QUIT, pid)
|
43
|
-
_, status = Process.waitpid2(pid)
|
44
|
-
assert status.success?, status.inspect
|
45
|
-
end
|
46
47
|
ru.close! if ru
|
47
48
|
end
|
48
49
|
|
@@ -76,7 +77,7 @@ class TestBin < Testcase
|
|
76
77
|
cfg.puts "end"
|
77
78
|
@cmd.concat(%W(-D -c #{cfg.path}))
|
78
79
|
addr = cloexec_pipe
|
79
|
-
pid =
|
80
|
+
pid = xfork do
|
80
81
|
opts = { close_others: true }
|
81
82
|
addr[0].close
|
82
83
|
if inherit
|
@@ -98,7 +99,10 @@ class TestBin < Testcase
|
|
98
99
|
# Even with a synchronous FD_CLOEXEC, there's a chance of a race
|
99
100
|
# because the server does not bind right away.
|
100
101
|
unless inherit
|
101
|
-
|
102
|
+
begin
|
103
|
+
@srv.shutdown
|
104
|
+
rescue Errno::ENOTCONN
|
105
|
+
end
|
102
106
|
@srv.close
|
103
107
|
end
|
104
108
|
exec(*@cmd)
|
@@ -158,11 +162,10 @@ class TestBin < Testcase
|
|
158
162
|
# need to fork here since tests are MT and the FD can leak out and go to
|
159
163
|
# other processes which fork (but do not exec), causing ETXTBUSY on
|
160
164
|
# Process.spawn
|
161
|
-
pid =
|
162
|
-
ruby = "#!#{`which ruby`}"
|
165
|
+
pid = xfork do
|
163
166
|
File.open(exe, "w") { |y|
|
164
167
|
lines = File.readlines("bin/yahns")
|
165
|
-
lines[0] = ruby
|
168
|
+
lines[0] = "#!#{RbConfig.ruby}\n"
|
166
169
|
y.chmod(0755)
|
167
170
|
y.syswrite(lines.join)
|
168
171
|
}
|
@@ -190,7 +193,7 @@ class TestBin < Testcase
|
|
190
193
|
}
|
191
194
|
cmd = %W(#{exe} -D -c #{cfg.path})
|
192
195
|
cmd << { @srv => @srv, close_others: true }
|
193
|
-
pid =
|
196
|
+
pid = Process.spawn(env, *cmd)
|
194
197
|
res = Net::HTTP.start(host, port) { |h| h.get("/") }
|
195
198
|
assert_equal 200, res.code.to_i
|
196
199
|
orig = res.body
|
data/test/test_config.rb
CHANGED
@@ -13,7 +13,7 @@ class TestConfig < Testcase
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_multi_conf_example
|
16
|
-
pid =
|
16
|
+
pid = xfork do
|
17
17
|
tmpdir = yahns_mktmpdir
|
18
18
|
|
19
19
|
# modify the example config file for testing
|
@@ -37,7 +37,7 @@ class TestConfig < Testcase
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def test_rack_basic_conf_example
|
40
|
-
pid =
|
40
|
+
pid = xfork do
|
41
41
|
tmpdir = yahns_mktmpdir
|
42
42
|
|
43
43
|
# modify the example config file for testing
|
@@ -170,7 +170,7 @@ class TestExtrasExecCGI < Testcase
|
|
170
170
|
assert_match %r{\A\d+\n\z}, body
|
171
171
|
exec_pid = body.to_i
|
172
172
|
poke_until_dead exec_pid
|
173
|
-
assert_raises(EOFError) { c.
|
173
|
+
assert_raises(EOFError) { c.readpartial(666) }
|
174
174
|
else
|
175
175
|
raise "BUG in test, bad rtype"
|
176
176
|
end
|
@@ -179,4 +179,27 @@ class TestExtrasExecCGI < Testcase
|
|
179
179
|
c.close if c
|
180
180
|
quit_wait(pid)
|
181
181
|
end
|
182
|
+
|
183
|
+
def test_rlimit_options
|
184
|
+
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
185
|
+
tout = 1
|
186
|
+
opts = { rlimit_cpu: tout, rlimit_core: 0 }
|
187
|
+
cmd = [ '/bin/sh', '-c', 'while :; do :;done', opts ]
|
188
|
+
pid = mkserver(cfg) do
|
189
|
+
require './extras/exec_cgi'
|
190
|
+
cfg.instance_eval do
|
191
|
+
stack = Rack::ContentLength.new(Rack::Chunked.new(ExecCgi.new(*cmd)))
|
192
|
+
app(:rack, stack) { listen "#{host}:#{port}" }
|
193
|
+
stderr_path err.path
|
194
|
+
worker_processes 1
|
195
|
+
end
|
196
|
+
end
|
197
|
+
c = get_tcp_client(host, port)
|
198
|
+
c.write "GET / HTTP/1.0\r\n\r\n"
|
199
|
+
assert_same c, c.wait(tout + 5)
|
200
|
+
assert_match %r{ 500 Internal Server Error\b}, c.readpartial(4096)
|
201
|
+
c.close
|
202
|
+
ensure
|
203
|
+
quit_wait(pid)
|
204
|
+
end
|
182
205
|
end
|
@@ -52,7 +52,7 @@ class TestExtrasTryGzipStatic < Testcase
|
|
52
52
|
File.symlink "COPYING", "#{tmpdir}/COPYING.relsymlink"
|
53
53
|
gplgz = "#{tmpdir}/COPYING.gz"
|
54
54
|
FileUtils.cp("COPYING", gpl)
|
55
|
-
_, status = Process.waitpid2(
|
55
|
+
_, status = Process.waitpid2(xfork do
|
56
56
|
File.open(gplgz, "w") do |fp|
|
57
57
|
Zlib::GzipWriter.wrap(fp.dup) { |io| io.write(GPL_TEXT) }
|
58
58
|
end
|
data/test/test_mt_accept.rb
CHANGED
@@ -14,7 +14,6 @@ class TestMtAccept < Testcase
|
|
14
14
|
skip "Linux kernel required" unless RUBY_PLATFORM =~ /linux/
|
15
15
|
skip "/proc not mounted" unless File.directory?("/proc")
|
16
16
|
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
17
|
-
opts = { threads: 1 }
|
18
17
|
cfg.instance_eval do
|
19
18
|
GTL.synchronize do
|
20
19
|
app(:rack, Rack::Lobster.new) { listen "#{host}:#{port}", threads: 1 }
|
@@ -29,7 +28,6 @@ class TestMtAccept < Testcase
|
|
29
28
|
quit_wait(pid)
|
30
29
|
|
31
30
|
cfg = Yahns::Config.new
|
32
|
-
opts = { threads: 1 }
|
33
31
|
cfg.instance_eval do
|
34
32
|
GTL.synchronize do
|
35
33
|
app(:rack, Rack::Lobster.new) { listen "#{host}:#{port}", threads: 2 }
|
data/test/test_proxy_pass.rb
CHANGED
@@ -6,6 +6,7 @@ require 'json'
|
|
6
6
|
require 'digest'
|
7
7
|
begin
|
8
8
|
require 'kcar'
|
9
|
+
require 'yahns/proxy_pass'
|
9
10
|
rescue LoadError
|
10
11
|
end
|
11
12
|
|
@@ -188,7 +189,6 @@ class TestProxyPass < Testcase
|
|
188
189
|
pid = mkserver(cfg) do
|
189
190
|
@srv.autoclose = @srv2.autoclose = false
|
190
191
|
ENV["YAHNS_FD"] = "#{@srv.fileno},#{@srv2.fileno}"
|
191
|
-
require 'yahns/proxy_pass'
|
192
192
|
cfg.instance_eval do
|
193
193
|
app(:rack, Yahns::ProxyPass.new("unix:#{unix_path}:/$fullpath")) do
|
194
194
|
listen "#{host}:#{port}"
|
@@ -251,7 +251,6 @@ class TestProxyPass < Testcase
|
|
251
251
|
err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
|
252
252
|
host2, port2 = @srv2.addr[3], @srv2.addr[1]
|
253
253
|
pid = mkserver(cfg) do
|
254
|
-
require 'yahns/proxy_pass'
|
255
254
|
@srv2.close
|
256
255
|
cfg.instance_eval do
|
257
256
|
app(:rack, Yahns::ProxyPass.new("http://#{host2}:#{port2}")) do
|
@@ -4,6 +4,7 @@
|
|
4
4
|
require_relative 'server_helper'
|
5
5
|
begin
|
6
6
|
require 'kcar'
|
7
|
+
require 'yahns/proxy_pass'
|
7
8
|
rescue LoadError
|
8
9
|
end
|
9
10
|
require 'digest/md5'
|
@@ -39,7 +40,6 @@ class TestProxyPassNoBuffering < Testcase
|
|
39
40
|
@srv2 = TCPServer.new(ENV["TEST_HOST"] || "127.0.0.1", 0)
|
40
41
|
server_helper_setup
|
41
42
|
skip "kcar missing yahns/proxy_pass" unless defined?(Kcar)
|
42
|
-
require 'yahns/proxy_pass'
|
43
43
|
@tmpdir = yahns_mktmpdir
|
44
44
|
end
|
45
45
|
|