summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKonstantin Pavlov <thresh@nginx.com>2022-09-13 13:17:16 +0400
committerKonstantin Pavlov <thresh@nginx.com>2022-09-13 13:17:16 +0400
commitce964aa30b163e2b3263c5af57c1a6dae7d0cebb (patch)
tree26bf70c1a5991f6471fc4caed8628e068fdc0b7b
parenteba4c3c98fa1bf275d94df8c727f70692ae7eae1 (diff)
parent38bd7e76a134084ab95a4ee3125af1ccd7b35864 (diff)
downloadunit-ce964aa30b163e2b3263c5af57c1a6dae7d0cebb.tar.gz
unit-ce964aa30b163e2b3263c5af57c1a6dae7d0cebb.tar.bz2
Merged with the default branch.1.28.0-1
-rw-r--r--CHANGES39
-rw-r--r--README.md2
-rw-r--r--auto/isolation22
-rw-r--r--auto/sockets7
-rw-r--r--auto/sources3
-rw-r--r--auto/unix15
-rwxr-xr-xconfigure5
-rw-r--r--docs/changes.xml130
-rw-r--r--docs/unitlogo.pngbin29600 -> 0 bytes
-rw-r--r--docs/unitlogo.svg305
-rw-r--r--pkg/deb/Makefile15
-rw-r--r--pkg/deb/Makefile.jsc1371
-rw-r--r--pkg/deb/Makefile.jsc1471
-rw-r--r--pkg/deb/Makefile.jsc1571
-rw-r--r--pkg/deb/Makefile.python46
-rw-r--r--pkg/deb/Makefile.python3446
-rw-r--r--pkg/deb/Makefile.python3546
-rw-r--r--pkg/deb/debian.module/copyright.unit-jsc1033
-rw-r--r--pkg/deb/debian.module/unit.example-jsc10-config15
-rw-r--r--pkg/deb/debian.module/unit.example-jsc13-config15
-rw-r--r--pkg/deb/debian.module/unit.example-jsc14-config15
-rw-r--r--pkg/deb/debian.module/unit.example-jsc15-config15
-rw-r--r--pkg/deb/debian.module/unit.example-jsc9-config15
-rw-r--r--pkg/deb/debian.module/unit.example-python-config16
-rw-r--r--pkg/deb/debian.module/unit.example-python3.4-config16
-rw-r--r--pkg/deb/debian.module/unit.example-python3.5-config16
-rw-r--r--pkg/deb/debian/dirs1
-rw-r--r--pkg/docker/Dockerfile.go1.19 (renamed from pkg/docker/Dockerfile.go1.18)6
-rw-r--r--pkg/docker/Dockerfile.jsc116
-rw-r--r--pkg/docker/Dockerfile.minimal2
-rw-r--r--pkg/docker/Dockerfile.node162
-rw-r--r--pkg/docker/Dockerfile.perl5.36 (renamed from pkg/docker/Dockerfile.perl5.34)6
-rw-r--r--pkg/docker/Dockerfile.php8.12
-rw-r--r--pkg/docker/Dockerfile.python3.102
-rw-r--r--pkg/docker/Dockerfile.ruby3.12
-rw-r--r--pkg/docker/Makefile6
-rw-r--r--pkg/rpm/Makefile78
-rw-r--r--pkg/rpm/Makefile.go11
-rw-r--r--pkg/rpm/Makefile.perl4
-rw-r--r--pkg/rpm/Makefile.php4
-rw-r--r--pkg/rpm/Makefile.python57
-rw-r--r--pkg/rpm/Makefile.python274
-rw-r--r--pkg/rpm/Makefile.python3102
-rw-r--r--pkg/rpm/Makefile.python3457
-rw-r--r--pkg/rpm/Makefile.python3552
-rw-r--r--pkg/rpm/Makefile.python362
-rw-r--r--pkg/rpm/Makefile.python372
-rw-r--r--pkg/rpm/Makefile.python3857
-rw-r--r--pkg/rpm/Makefile.python392
-rw-r--r--pkg/rpm/Makefile.ruby6
-rw-r--r--pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc1032
-rw-r--r--pkg/rpm/rpmbuild/SOURCES/unit.example-python35-config16
-rw-r--r--pkg/rpm/rpmbuild/SOURCES/unit.example-python38-config16
-rw-r--r--pkg/rpm/unit.module.spec.in11
-rw-r--r--pkg/rpm/unit.spec.in13
-rw-r--r--src/nxt_application.c75
-rw-r--r--src/nxt_clone.c4
-rw-r--r--src/nxt_conf.c24
-rw-r--r--src/nxt_conf.h9
-rw-r--r--src/nxt_conf_validation.c150
-rw-r--r--src/nxt_conn.h23
-rw-r--r--src/nxt_conn_accept.c9
-rw-r--r--src/nxt_conn_close.c14
-rw-r--r--src/nxt_controller.c171
-rw-r--r--src/nxt_event_engine.h5
-rw-r--r--src/nxt_h1proto.c15
-rw-r--r--src/nxt_http.h34
-rw-r--r--src/nxt_http_parse.c26
-rw-r--r--src/nxt_http_parse.h2
-rw-r--r--src/nxt_http_request.c317
-rw-r--r--src/nxt_http_return.c7
-rw-r--r--src/nxt_http_route.c162
-rw-r--r--src/nxt_http_route_addr.c12
-rw-r--r--src/nxt_http_route_addr.h1
-rw-r--r--src/nxt_http_static.c26
-rw-r--r--src/nxt_http_variables.c446
-rw-r--r--src/nxt_isolation.c10
-rw-r--r--src/nxt_isolation.h6
-rw-r--r--src/nxt_job_resolve.c132
-rw-r--r--src/nxt_job_resolve.h29
-rw-r--r--src/nxt_main.h1
-rw-r--r--src/nxt_main_process.c4
-rw-r--r--src/nxt_mp.c4
-rw-r--r--src/nxt_nncq.h6
-rw-r--r--src/nxt_nvbcq.h6
-rw-r--r--src/nxt_port.h9
-rw-r--r--src/nxt_port_memory.c131
-rw-r--r--src/nxt_port_memory.h21
-rw-r--r--src/nxt_port_memory_int.h9
-rw-r--r--src/nxt_port_rpc.c1
-rw-r--r--src/nxt_port_socket.c4
-rw-r--r--src/nxt_process.c82
-rw-r--r--src/nxt_process.h4
-rw-r--r--src/nxt_router.c717
-rw-r--r--src/nxt_router.h26
-rw-r--r--src/nxt_router_access_log.c442
-rw-r--r--src/nxt_runtime.c13
-rw-r--r--src/nxt_sockaddr.c423
-rw-r--r--src/nxt_sockaddr.h12
-rw-r--r--src/nxt_status.c105
-rw-r--r--src/nxt_status.h33
-rw-r--r--src/nxt_string.c2
-rw-r--r--src/nxt_string.h2
-rw-r--r--src/nxt_time_parse.c2
-rw-r--r--src/nxt_unit.c38
-rw-r--r--src/nxt_unix.h2
-rw-r--r--src/nxt_var.c418
-rw-r--r--src/nxt_var.h39
-rw-r--r--src/nxt_websocket_accept.c4
-rw-r--r--src/python/nxt_python_asgi.c44
-rw-r--r--src/ruby/nxt_ruby.c52
-rw-r--r--src/ruby/nxt_ruby.h1
-rw-r--r--test/conftest.py5
-rw-r--r--test/python/ctx_iter_atexit/wsgi.py1
-rw-r--r--test/python/forwarded_header/wsgi.py10
-rw-r--r--test/test_access_log.py82
-rw-r--r--test/test_asgi_application.py55
-rw-r--r--test/test_asgi_application_unix_abstract.py23
-rw-r--r--test/test_client_ip.py82
-rw-r--r--test/test_configuration.py10
-rw-r--r--test/test_forwarded_header.py266
-rw-r--r--test/test_go_application.py12
-rw-r--r--test/test_node_application.py11
-rw-r--r--test/test_php_application.py11
-rw-r--r--test/test_proxy.py4
-rw-r--r--test/test_python_application.py44
-rw-r--r--test/test_routing.py14
-rw-r--r--test/test_ruby_application.py13
-rw-r--r--test/test_static_chroot.py126
-rw-r--r--test/test_status.py223
-rw-r--r--test/test_status_tls.py30
-rw-r--r--test/test_tls.py26
-rw-r--r--test/test_tls_sni.py2
-rw-r--r--test/test_unix_abstract.py109
-rw-r--r--test/test_variables.py154
-rw-r--r--test/unit/applications/lang/go.py5
-rw-r--r--test/unit/applications/proto.py14
-rw-r--r--test/unit/check/unix_abstract.py25
-rw-r--r--test/unit/http.py6
-rw-r--r--test/unit/status.py45
-rw-r--r--version4
141 files changed, 4117 insertions, 3172 deletions
diff --git a/CHANGES b/CHANGES
index 98208fa9..29cd3301 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,43 @@
+Changes with Unit 1.28.0 13 Sep 2022
+
+ *) Change: increased the applications' startup timeout.
+
+ *) Change: disallowed abstract Unix domain socket syntax in non-Linux
+ systems.
+
+ *) Feature: basic statistics API.
+
+ *) Feature: customizable access log format.
+
+ *) Feature: more HTTP variables support.
+
+ *) Feature: forwarded header to replace client address and protocol.
+
+ *) Feature: ability to get dynamic variables.
+
+ *) Feature: support for abstract Unix sockets.
+
+ *) Feature: support for Unix sockets in address matching.
+
+ *) Feature: the $dollar variable translates to a literal "$" during
+ variable substitution.
+
+ *) Bugfix: router process could crash if index file didn't contain an
+ extension.
+
+ *) Bugfix: force SCRIPT_NAME in Ruby to always be an empty string.
+
+ *) Bugfix: when isolated PID numbers reach the prototype process host
+ PID, the prototype crashed.
+
+ *) Bugfix: the Ruby application process could crash on SIGTERM.
+
+ *) Bugfix: the Ruby application process could crash on SIGINT.
+
+ *) Bugfix: mutex leak in the C API.
+
+
Changes with Unit 1.27.0 02 Jun 2022
*) Feature: ability to specify a custom index file name when serving
diff --git a/README.md b/README.md
index 2c3b7d1f..039200d6 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
## Universal Web App Server
-![NGINX Unit Logo](docs/unitlogo.png)
+![NGINX Unit Logo](docs/unitlogo.svg)
NGINX Unit is a lightweight and versatile open-source server that has
three core capabilities:
diff --git a/auto/isolation b/auto/isolation
index fd35f8ed..384f7ef1 100644
--- a/auto/isolation
+++ b/auto/isolation
@@ -21,7 +21,7 @@ nxt_feature_test="#include <sys/wait.h>
#include <sys/syscall.h>
int main() {
- return __NR_clone | SIGCHLD;
+ return SYS_clone | SIGCHLD;
}"
. auto/feature
@@ -61,14 +61,30 @@ fi
nxt_feature="Linux pivot_root()"
-nxt_feature_name=NXT_HAVE_PIVOT_ROOT
+nxt_feature_name=NXT_HAVE_LINUX_PIVOT_ROOT
nxt_feature_run=no
nxt_feature_incs=
nxt_feature_libs=
nxt_feature_test="#include <sys/syscall.h>
+ #if !defined(__linux__)
+ # error
+ #endif
int main() {
- return __NR_pivot_root;
+ return SYS_pivot_root;
+ }"
+. auto/feature
+
+
+nxt_feature="<mntent.h>"
+nxt_feature_name=NXT_HAVE_MNTENT_H
+nxt_feature_run=no
+nxt_feature_incs=
+nxt_feature_libs=
+nxt_feature_test="#include <mntent.h>
+
+ int main(void) {
+ return 0;
}"
. auto/feature
diff --git a/auto/sockets b/auto/sockets
index e6ef326d..e344a3db 100644
--- a/auto/sockets
+++ b/auto/sockets
@@ -225,12 +225,6 @@ nxt_feature_test="#include <sys/filio.h>
}"
. auto/feature
-if [ $nxt_found = yes ]; then
- NXT_SYS_FILIO_H="#include <sys/filio.h>"
-else
- NXT_SYS_FILIO_H=
-fi
-
nxt_feature="ioctl(FIONBIO)"
nxt_feature_name=NXT_HAVE_FIONBIO
@@ -239,7 +233,6 @@ nxt_feature_incs=
nxt_feature_libs=
nxt_feature_test="#include <unistd.h>
#include <sys/socket.h>
- $NXT_SYS_FILIO_H
#include <sys/ioctl.h>
int main() {
diff --git a/auto/sources b/auto/sources
index 27a45edc..8548f812 100644
--- a/auto/sources
+++ b/auto/sources
@@ -69,7 +69,6 @@ NXT_LIB_SRCS=" \
src/nxt_event_conn_job_sendfile.c \
src/nxt_conn_proxy.c \
src/nxt_job.c \
- src/nxt_job_resolve.c \
src/nxt_sockaddr.c \
src/nxt_listen_socket.c \
src/nxt_upstream.c \
@@ -84,7 +83,9 @@ NXT_LIB_SRCS=" \
src/nxt_signal_handlers.c \
src/nxt_controller.c \
src/nxt_router.c \
+ src/nxt_router_access_log.c \
src/nxt_h1proto.c \
+ src/nxt_status.c \
src/nxt_http_request.c \
src/nxt_http_response.c \
src/nxt_http_error.c \
diff --git a/auto/unix b/auto/unix
index 7c241650..45c6a139 100644
--- a/auto/unix
+++ b/auto/unix
@@ -178,21 +178,6 @@ if [ $nxt_found = no ]; then
fi
-nxt_feature="posix_spawn()"
-nxt_feature_name=NXT_HAVE_POSIX_SPAWN
-nxt_feature_run=
-nxt_feature_incs=
-nxt_feature_libs=
-nxt_feature_test="#include <spawn.h>
- #include <unistd.h>
-
- int main(int argc, char *argv[]) {
- (void) posix_spawn(NULL, \"\", NULL, NULL, argv, NULL);
- return 0;
- }"
-. auto/feature
-
-
# NetBSD 1.0, OpenBSD 1.0, FreeBSD 2.2 setproctitle().
nxt_feature="setproctitle()"
diff --git a/configure b/configure
index bc21e579..ea86e18e 100755
--- a/configure
+++ b/configure
@@ -48,11 +48,6 @@ NXT_GROUP=
nxt_module=${1:-""}
case $nxt_module in
- --help)
- . auto/help
- exit 0
- ;;
-
""|--*)
;;
diff --git a/docs/changes.xml b/docs/changes.xml
index 1d8a13c2..0674fb54 100644
--- a/docs/changes.xml
+++ b/docs/changes.xml
@@ -14,8 +14,134 @@
unit-ruby
unit-jsc-common unit-jsc8 unit-jsc10 unit-jsc11 unit-jsc13
unit-jsc14 unit-jsc15 unit-jsc16 unit-jsc17 unit-jsc18"
+ ver="1.28.0" rev="1"
+ date="2022-09-13" time="18:00:00 +0300"
+ packager="Nginx Packaging &lt;nginx-packaging@f5.com&gt;">
+
+<change>
+<para>
+NGINX Unit updated to 1.28.0.
+</para>
+</change>
+
+</changes>
+
+
+<changes apply="unit" ver="1.28.0" rev="1"
+ date="2022-09-13" time="18:00:00 +0300"
+ packager="Nginx Packaging &lt;nginx-packaging@f5.com&gt;">
+
+<change type="change">
+<para>
+increased the applications' startup timeout.
+</para>
+</change>
+
+<change type="change">
+<para>
+disallowed abstract Unix domain socket syntax in non-Linux systems.
+</para>
+</change>
+
+<change type="feature">
+<para>
+basic statistics API.
+</para>
+</change>
+
+<change type="feature">
+<para>
+customizable access log format.
+</para>
+</change>
+
+<change type="feature">
+<para>
+more HTTP variables support.
+</para>
+</change>
+
+<change type="feature">
+<para>
+forwarded header to replace client address and protocol.
+</para>
+</change>
+
+<change type="feature">
+<para>
+ability to get dynamic variables.
+</para>
+</change>
+
+<change type="feature">
+<para>
+support for abstract Unix sockets.
+</para>
+</change>
+
+<change type="feature">
+<para>
+support for Unix sockets in address matching.
+</para>
+</change>
+
+<change type="feature">
+<para>
+the $dollar variable translates to a literal "$" during variable substitution.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+router process could crash if index file didn't contain an extension.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+force SCRIPT_NAME in Ruby to always be an empty string.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+when isolated PID numbers reach the prototype process host PID,
+the prototype crashed.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+the Ruby application process could crash on SIGTERM.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+the Ruby application process could crash on SIGINT.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+mutex leak in the C API.
+</para>
+</change>
+
+</changes>
+
+
+<changes apply="unit-php
+ unit-python unit-python2.7
+ unit-python3.4 unit-python3.5 unit-python3.6 unit-python3.7
+ unit-python3.8 unit-python3.9 unit-python3.10
+ unit-go
+ unit-perl
+ unit-ruby
+ unit-jsc-common unit-jsc8 unit-jsc10 unit-jsc11 unit-jsc13
+ unit-jsc14 unit-jsc15 unit-jsc16 unit-jsc17 unit-jsc18"
ver="1.27.0" rev="1"
- date="" time=""
+ date="2022-06-02" time="18:00:00 +0300"
packager="Andrei Belov &lt;defan@nginx.com&gt;">
<change>
@@ -28,7 +154,7 @@ NGINX Unit updated to 1.27.0.
<changes apply="unit" ver="1.27.0" rev="1"
- date="" time=""
+ date="2022-06-02" time="18:00:00 +0300"
packager="Andrei Belov &lt;defan@nginx.com&gt;">
<change type="feature">
diff --git a/docs/unitlogo.png b/docs/unitlogo.png
deleted file mode 100644
index dbd87fd8..00000000
--- a/docs/unitlogo.png
+++ /dev/null
Binary files differ
diff --git a/docs/unitlogo.svg b/docs/unitlogo.svg
new file mode 100644
index 00000000..a8b87b18
--- /dev/null
+++ b/docs/unitlogo.svg
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 1660 332" style="enable-background:new 0 0 1660 332;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#222222;}
+ .st1{fill:#999999;}
+ .st2{fill:#009639;}
+ .st3{fill:#FFFFFF;}
+ .st4{fill:none;stroke:#62C026;stroke-width:6.3479633;stroke-linejoin:round;stroke-miterlimit:10;}
+ .st5{fill:#267423;}
+ .st6{fill:#62C026;}
+ .st7{fill:#E6E6E6;}
+</style>
+<g id="Layer_1">
+ <rect class="st0" width="1660" height="332"/>
+</g>
+<g id="Art">
+ <g>
+ <g>
+ <path class="st1" d="M311.9880066,232.1229248h-9.3733826l-1.7800903,5.5219574h-4.396637l7.7028503-25.7251434h6.3584595
+ l7.6655273,25.7251434h-4.4327698L311.9880066,232.1229248z M303.8868103,227.9802094h6.8302307L307.3013,216.607666
+ L303.8868103,227.9802094z"/>
+ <path class="st1" d="M336.5467834,226.9271088v10.7177734h-4.3232117v-10.7551117
+ c0-2.8331909-1.4900513-4.1775665-3.6696777-4.1775665c-1.9979248,0-3.7431335,1.1974945-3.8514404,3.6323395v11.3003387
+ h-4.2871094v-18.4579773h2.7970581l0.7991943,1.5983276c1.3817139-1.4165802,3.3796387-2.1062012,5.5592957-2.1062012
+ C333.8218994,218.6790314,336.5467834,221.1138611,336.5467834,226.9271088z"/>
+ <path class="st1" d="M364.9918518,211.9197388v25.7251434h-4.2149353l-10.1003418-17.4048615v17.4048615h-4.1775818v-25.7251434
+ h4.1775818l10.1003418,17.5144043v-17.5144043H364.9918518z"/>
+ <path class="st1" d="M384.2813416,221.0765228v-1.1999969c0-2.6887665-2.0339966-4.3219604-5.5953979-4.3219604
+ c-3.5962219,0-5.6315002,1.633194-5.6315002,4.3219604v9.811554c0,2.6887817,2.0352783,4.3219757,5.5953979,4.3219757
+ c3.5975037,0,5.6315002-1.633194,5.6315002-4.3219757v-1.6356659h-5.7771301v-4.1427155h10.2460022v6.0323334
+ c0,4.9767303-3.6696777,8.2107239-10.06427,8.2107239c-6.3945618,0-10.1003418-3.2339935-10.1003418-8.2107239v-10.3194427
+ c0-4.9767303,3.6696777-8.2107391,10.0642395-8.2107391c6.4306946,0,10.1003723,3.2340088,10.1003723,8.2107391v1.4539337
+ H384.2813416z"/>
+ <path class="st1" d="M392.8530884,211.9197388h4.4688416v25.7251434h-4.4688416V211.9197388z"/>
+ <path class="st1" d="M420.0657959,211.9197388v25.7251434h-4.2149048l-10.1016235-17.4048615v17.4048615h-4.1775513v-25.7251434
+ h4.1775513l10.1016235,17.5144043v-17.5144043H420.0657959z"/>
+ <path class="st1" d="M436.3403931,224.8906097l7.8111572,12.7542725h-5.1958313l-5.3763123-8.8306427l-5.4870911,8.8306427
+ h-4.9406433l7.8111572-13.0804138l-7.7389526-12.6447296h5.1958008l5.3775635,8.7559509l5.5219727-8.7559509h5.0140686
+ L436.3403931,224.8906097z"/>
+ <path class="st1" d="M471.3978577,219.1147156v2.5792389c0,4.396637-3.1244507,7.1949615-8.1746521,7.1949615h-5.9949646
+ v8.7559662h-4.4688721v-25.7251434h10.4265137C468.2360535,211.9197388,471.3978577,214.7180634,471.3978577,219.1147156z
+ M466.9290161,219.0051727c0-1.8896179-1.198761-2.9427185-3.4157715-2.9427185h-6.2850037v8.6837616h6.2489319
+ c2.2157288,0,3.4518433-1.0531158,3.4518433-2.9427185V219.0051727z"/>
+ <path class="st1" d="M484.3649902,218.8956299v3.8165741c-0.5439758-0.1468964-1.1265259-0.253952-1.706604-0.253952
+ c-2.2170105,0-4.178833,1.2696991-4.178833,4.0680237v11.1186066h-4.2871094v-18.4579773h2.9066162l0.8352661,1.6705322
+ c1.453949-1.3443909,3.4879456-2.0340118,5.5232239-2.0340118
+ C483.7836914,218.8234253,484.0749512,218.8607635,484.3649902,218.8956299z"/>
+ <path class="st1" d="M485.9994202,230.3055115v-3.7792358c0-4.8323212,2.9066467-7.8472443,8.1385498-7.8472443
+ c5.2680359,0,8.1746521,3.0149231,8.1746521,7.8472443v3.7792358c0,4.8323364-2.9066162,7.8472443-8.1385498,7.8472443
+ C488.9421692,238.1527557,485.9994202,235.1378479,485.9994202,230.3055115z M497.9894104,230.1586151v-3.4879303
+ c0-2.6141052-1.1626587-3.9958344-3.8153381-3.9958344c-2.6514282,0-3.8501892,1.3817291-3.8501892,3.9958344v3.4879303
+ c0,2.6165924,1.198761,3.9983215,3.8140869,3.9983215C496.7906494,234.1569366,497.9894104,232.7752075,497.9894104,230.1586151z
+ "/>
+ <path class="st1" d="M501.3653259,242.0041809h0.7991638c2.7983093,0,3.2340088-1.5634766,3.2340088-3.9236145v-18.8936615
+ h4.3232117v20.0563049c0,5.0140686-2.9788208,6.7568054-6.3572388,6.7568054h-1.9991455V242.0041809z M505.3623962,212.2110291
+ h4.3954163v4.6157227h-4.3954163V212.2110291z"/>
+ <path class="st1" d="M529.0498047,225.6549225v4.0680237h-11.6264648v0.5452118
+ c0,2.9427185,1.3804932,4.2871094,3.8501587,4.2871094c1.8535156,0,3.4157715-0.9435577,3.4157715-2.5070343v-0.2887878
+ h4.3231812c0,3.9958191-3.0883789,6.3933105-7.7389526,6.3933105c-5.2680054,0-8.1746216-3.1966553-8.1746216-8.0289917
+ v-3.5252838c0-4.8323364,2.9066162-7.9194489,8.0663452-7.9194489
+ C525.8880005,218.6790314,529.0498047,221.6217499,529.0498047,225.6549225z M524.6531372,226.4167328v-0.7269592
+ c0-2.2879486-1.1265259-3.4132538-3.4157104-3.4132538c-2.5792847,0-3.7780151,1.4514313-3.8140869,4.140213H524.6531372z"/>
+ <path class="st1" d="M531.9539185,230.3055115v-3.7792358c0-4.8323212,2.9066162-7.8472443,8.0314941-7.8472443
+ c4.7949829,0,7.84729,2.9427185,7.84729,7.5211029v0.4356842h-4.359314v-0.5452271
+ c0-2.215744-1.3082886-3.415741-3.4879761-3.415741c-2.5082397,0-3.7070312,1.3817291-3.7070312,3.9958344v3.4879303
+ c0,2.6165924,1.1987915,3.9983215,3.7070312,3.9983215c2.1435547,0,3.4879761-1.234848,3.4879761-3.415741v-0.5452271h4.359314
+ v0.4356842c0,4.5783844-3.0523071,7.5211029-7.84729,7.5211029
+ C534.8966675,238.1527557,531.9539185,235.1378479,531.9539185,230.3055115z"/>
+ <path class="st1" d="M562.0359497,233.6465607v3.9983215h-2.6153564c-4.3605957,0-6.5762939-2.2530975-6.5762939-6.94104
+ v-7.5211029h-2.4709473v-3.9958344h2.4709473v-5.2680054h4.3231812v5.2680054h4.614502v3.9958344h-4.614502v6.687088
+ c0,2.61409,1.0531006,3.7767334,3.1605835,3.7767334H562.0359497z"/>
+ </g>
+ <g>
+ <g>
+ <g>
+ <g>
+ <g>
+ <path class="st2" d="M121.0398254,200.2646637c0.716362,1.2425537,1.7262878,2.211853,2.8912964,2.8691254
+ l59.147934,34.1488647l0.0018463-0.0018463c1.1539459,0.6794434,2.4962006,1.0690002,3.9307709,1.0690002
+ s2.7786713-0.3895569,3.9307556-1.0690002l59.1497955-34.1488495
+ c1.1650085-0.6572876,2.1712341-1.6247406,2.8894348-2.8672943c0.7182159-1.2425385,1.0523987-2.5995636,1.0394745-3.9381104
+ v-68.2977295l-0.0018463-0.0018463c0.0110779-1.3367157-0.3231049-2.6955795-1.0394745-3.9381256
+ c-0.7182007-1.2425537-1.7281189-2.2100067-2.8912811-2.869133L190.938736,87.0708618v-0.0018463
+ c-1.1520844-0.6794434-2.494339-1.0690079-3.9289093-1.0690079c-1.432724,0-2.7749786,0.3895645-3.9270782,1.0690079
+ v0.0018463l-59.147934,34.1488571c-1.1650085,0.6591263-2.1749344,1.6265793-2.8931427,2.869133
+ c-0.716362,1.2425461-1.0505447,2.6014099-1.0394669,3.9381256l-0.0018463,0.0018463v68.2977295
+ c-0.0129242,1.3385468,0.3212585,2.6955719,1.0376205,3.9381104"/>
+ </g>
+ </g>
+ </g>
+ <path class="st3" d="M168.0723724,188.1761322c0,4.2002869-3.4047394,7.6066895-7.6071014,7.6066895
+ c-4.200531,0-7.6071014-3.4064026-7.6071014-7.6066895l0.0018463,0.0018463l0.0073853-52.2166138
+ c0-4.0451965,3.5746002-7.3906708,8.6373901-7.3906708c3.6244507,0,7.8083496,1.462265,10.3692932,4.6360168
+ l2.2987518,2.7509766l31.7799683,38.0297394v-37.813736h-0.0036774c0-4.2002869,3.4065704-7.6066895,7.6089478-7.6066895
+ c4.200531,0,7.6052551,3.4064026,7.6052551,7.6066895h-0.0018463l-0.0073853,52.2129059
+ c0,4.0452118-3.5764465,7.390686-8.6373901,7.390686c-3.626297,0-7.8083649-1.4604187-10.3692932-4.6360321
+ l-34.0787354-40.7807159v37.8174438L168.0723724,188.1761322z"/>
+ </g>
+ <g>
+ <path class="st1" d="M427.3791809,185.5565643h0.9719543v-2.1648254h0.7688599
+ c0.5082397,0,0.8728333,0.0495453,1.0799255,0.1803284c0.3398132,0.1991425,0.5132141,0.6261597,0.5132141,1.2592621v0.4438629
+ l0.0217896,0.165451c0.0119019,0.0366669,0.0119019,0.0515289,0.0148621,0.0693665
+ c0.0049438,0.0267487,0.0069275,0.034668,0.0217896,0.0465546h0.9006042l-0.0326843-0.0614319
+ c-0.0267639-0.0416107-0.041626-0.1357269-0.0435791-0.2813721c-0.0128784-0.1555481-0.0128784-0.2883148-0.0128784-0.4111633
+ v-0.4101868c0-0.2754211-0.1030579-0.5568085-0.3012085-0.8580017c-0.2041016-0.2902985-0.525116-0.462677-0.9590759-0.5389709
+ c0.3428345-0.0574646,0.6123047-0.1486206,0.7995605-0.2595825c0.3675842-0.231842,0.5369873-0.6083374,0.5369873-1.0898438
+ c0-0.6925507-0.2734375-1.1661224-0.8500671-1.3979645c-0.3180237-0.1307831-0.8164062-0.1971741-1.506958-0.1971741h-1.9230957
+ V185.5565643z M430.1434326,182.5882263c-0.1951599,0.0842133-0.5053101,0.1228638-0.924408,0.1228638h-0.8678894v-2.0043182
+ h0.8283081c0.5369873,0,0.9263611,0.0762787,1.1680908,0.2149963c0.2466736,0.1377106,0.3656006,0.4042358,0.3656006,0.8035126
+ C430.7131348,182.1513062,430.5278625,182.4306946,430.1434326,182.5882263 M432.9661255,179.279068
+ c-0.9887695-0.9759064-2.1717529-1.4593964-3.5697327-1.4593964c-1.3682556,0-2.5621033,0.48349-3.5281067,1.4593964
+ c-0.9887695,0.9788818-1.4673157,2.1628418-1.4673157,3.552887c0,1.3880615,0.4735718,2.5769806,1.4494629,3.5509033
+ c0.9689636,0.9887848,2.1648254,1.4792175,3.5459595,1.4792175c1.3979797,0,2.5809631-0.4904327,3.5697327-1.4792175
+ c0.9689636-0.9788666,1.4692993-2.1727448,1.4692993-3.5509033
+ C434.4354248,181.4320068,433.9350891,180.2579498,432.9661255,179.279068 M432.4559021,179.77742
+ c0.8460999,0.8263092,1.2602234,1.8567047,1.2602234,3.0545349c0,1.1859589-0.4141235,2.2242737-1.2602234,3.069397
+ c-0.833252,0.841156-1.85672,1.2731323-3.0595093,1.2731323c-1.1938782,0-2.2113647-0.4319763-3.055542-1.2731323
+ c-0.8282776-0.8451233-1.254303-1.8834381-1.254303-3.069397c0-1.1978302,0.4260254-2.2282257,1.254303-3.0545349
+ c0.8560486-0.8599701,1.8695984-1.2820435,3.055542-1.2820435
+ C430.5942078,178.4953766,431.6127319,178.91745,432.4559021,179.77742"/>
+ <g>
+ <path class="st3" d="M296.4403381,172.4392395v-36.1351318h8.9604187v35.6251984
+ c0,5.3908844,3.5699158,8.6692505,10.7825317,8.6692505s10.7825317-3.2783661,10.7825317-8.6692505v-35.6251984h8.9604492
+ v36.1351318c0,10.0534668-7.2126465,16.4645996-19.6701965,16.4645996
+ C303.7257385,188.9038391,296.4403381,182.4927063,296.4403381,172.4392395z"/>
+ <path class="st3" d="M375.7033691,166.3924561v21.4915314l-8.6700134-0.0000153v-21.5643158
+ c0-5.6824341-2.9868164-8.378067-7.3582153-8.378067c-4.0066528,0-7.5037842,2.404068-7.722168,7.2850342v22.6573486
+ h-8.5964661v-37.0090485h5.6096497l1.6029663,3.2052002c2.7684326-2.8412323,6.775116-4.2254333,11.1465149-4.2254333
+ C370.2393188,149.8546906,375.7033691,154.7360229,375.7033691,166.3924561z"/>
+ <path class="st3" d="M383.7144775,136.887207h8.8876343v9.2519836h-8.8876343V136.887207z M383.8600464,150.8749237h8.669281
+ v37.0090485h-8.669281V150.8749237z"/>
+ <path class="st3" d="M420.5768127,179.8702393v8.0137329h-5.2456665c-8.7420654,0-13.1862488-4.516983-13.1862488-13.9149323
+ v-15.0803833h-4.9537659v-8.0137329h4.9537659v-10.5637665h8.6692505v10.5637665h9.2523499v8.0137329h-9.2523499v13.4049988
+ c0,5.2453003,2.1132812,7.5765839,6.3383484,7.5765839H420.5768127z"/>
+ </g>
+ </g>
+ </g>
+ </g>
+</g>
+<g id="artwork">
+ <g>
+ <g>
+ <ellipse class="st3" cx="1438.1523438" cy="40.3328018" rx="4.3671799" ry="4.6571636"/>
+ </g>
+ <g>
+ <path class="st4" d="M1449.3671875,185.17453c0,0,42.8554688,17.7458191,55.9665527-38.7562561"/>
+ <g>
+ <path class="st2" d="M1515.2062988,150.6308441c-0.2004395,0.6022034-0.7965088,1.0005188-1.4407959,0.8917542
+ l-18.2456055-3.0800781c-0.6442871-0.1087646-1.0772705-0.6807861-1.0688477-1.3153992l-0.0385742-0.0065002
+ c0,0,0.0134277-0.078949,0.0321045-0.1901245c0.0522461-0.3088837-0.0175781,0.1047668,0.1364746-0.8079987
+ c0.4699707-2.7843781,1.265625-7.4972229,1.4852295-8.7984619c0.8564453-5.0735321,4.4857178-8.9770355,9.0693359-10.4446106
+ l-1.2091064,7.1621399c-1.1503906,1.0960236-1.9852295,2.5393066-2.2700195,4.2261658
+ c-0.041748,0.2472992-0.8549805,5.2803802-0.8549805,5.2803802l9.5836182,1.6178284
+ c0,0,0.8430176-4.7857513,0.9511719-5.4262543c0.25-1.4815674,0.0388184-2.928299-0.5042725-4.2173157l1.258667-7.4558563
+ c3.6591797,2.9155731,5.6691895,7.6758728,4.8352051,12.6167603c-0.2275391,1.3476562-1.0369873,6.1426239-1.5119629,8.9560699
+ c-0.1540527,0.9130707-0.0842285,0.4994202-0.1363525,0.8079834c-0.0187988,0.111496-0.0321045,0.1901398-0.0321045,0.1901398
+ L1515.2062988,150.6308441z"/>
+ </g>
+ </g>
+ <g>
+ <path class="st4" d="M1454.5784912,196.9434509c0,0,3.9665527,46.2144318,60.1638184,31.8529053"/>
+ <g>
+ <path class="st2" d="M1515.5456543,239.5000458c-0.6268311,0.0991974-1.2548828-0.2467041-1.4547119-0.8687744
+ l-5.6619873-17.616272c-0.1999512-0.6220703,0.1086426-1.2696533,0.6759033-1.5542603l-0.0119629-0.0372009
+ c0,0,0.0762939-0.0245056,0.1835938-0.0590057c0.2982178-0.0958405-0.1010742,0.0325165,0.7801514-0.2507324
+ c2.6883545-0.8640442,7.2386475-2.3265228,8.4949951-2.7303162c4.8984375-1.5744019,10.0341797-0.1486511,13.4465332,3.2453918
+ l-6.9150391,2.2225342c-1.5025635-0.516983-3.1680908-0.5939789-4.7967529-0.0705261
+ c-0.2387695,0.0767517-5.081543,1.6708984-5.081543,1.6708984l2.973999,9.2530365c0,0,4.6368408-1.453949,5.255249-1.65271
+ c1.4304199-0.4597626,2.6176758-1.3130341,3.512085-2.3884583l7.1987305-2.3136749
+ c-0.904541,4.5904236-4.2058105,8.5656891-8.9763184,10.0989227c-1.3011475,0.4181976-5.9306641,1.9061737-8.6470947,2.7792206
+ c-0.8815918,0.2833405-0.4821777,0.1549835-0.7801514,0.2507324c-0.107666,0.0346069-0.1835938,0.0590057-0.1835938,0.0590057
+ L1515.5456543,239.5000458z"/>
+ </g>
+ </g>
+ <g>
+ <path class="st4" d="M1315.6970215,243.2423553c0,0-21.9627686-40.8551483,32.9356689-59.5780487"/>
+ <g>
+ <path class="st2" d="M1306.9082031,248.4536285c-0.2102051-0.5988464,0.017334-1.278717,0.5932617-1.5871277
+ l16.3127441-8.7341766c0.5760498-0.3084259,1.2685547-0.1211395,1.6503906,0.385788l0.0345459-0.0184479
+ c0,0,0.0377197,0.0706024,0.0909424,0.1699982c0.1478271,0.2761536-0.0501709-0.0936737,0.3868408,0.7223969
+ c1.3328857,2.4893951,3.5888672,6.7029724,4.211792,7.8663483c2.4287109,4.5360565,1.9486084,9.8443756-0.7773438,13.8108063
+ l-3.4284668-6.4033813c0.2387695-1.5709229,0.0152588-3.2232208-0.7922363-4.7313843
+ c-0.1184082-0.2210999-2.5563965-4.6987-2.5563965-4.6987l-8.5683594,4.5876617c0,0,2.2631836,4.3002167,2.5697021,4.872879
+ c0.7092285,1.3246155,1.7619629,2.3392639,2.9805908,3.0260315l3.5690918,6.6659851
+ c-4.6782227-0.0653381-9.1818848-2.5988159-11.5471191-7.0162964c-0.6450195-1.2048645-2.9404297-5.4918671-4.2872314-8.0072479
+ c-0.4370117-0.8163452-0.2390137-0.4465179-0.3867188-0.7223969c-0.0534668-0.0996704-0.0910645-0.1699829-0.0910645-0.1699829
+ L1306.9082031,248.4536285z"/>
+ </g>
+ </g>
+ <g>
+ <g>
+ <ellipse class="st5" cx="1464.5943604" cy="188.810318" rx="7.7738867" ry="9.5948353"/>
+ </g>
+ </g>
+ <g>
+ <g>
+ <ellipse class="st5" cx="1462.7558594" cy="218.225769" rx="7.7738867" ry="9.5948353"/>
+ </g>
+ </g>
+ <g>
+ <g>
+ <ellipse class="st5" cx="1339.057251" cy="188.810318" rx="7.7738867" ry="9.5948353"/>
+ </g>
+ </g>
+ <path class="st6" d="M1456.8769531,228.1189728c0-24.7052765-24.6368408-44.7328644-55.027832-44.7328644
+ c-30.3911133,0-55.0279541,20.0275879-55.0279541,44.7328644s24.6368408,44.7328339,55.0279541,44.7328339
+ c0.0229492,0,0.0457764-0.0006714,0.0687256-0.0007019c0.0229492,0.0000305,0.0457764,0.0007019,0.0687256,0.0007019
+ c0,0-0.0037842-0.0012512-0.0040283-0.0013428C1432.3120117,272.7917786,1456.8769531,252.7880096,1456.8769531,228.1189728z"/>
+ <g>
+ <path class="st5" d="M1401.848999,257.1278992c30.8840332,0,56.3187256-7.3460541,59.763916-20.650116
+ c0.1726074-0.4505463,0.2983398-0.9141541,0.3278809-1.3972931l5.4649658-86.9454346
+ c0.197998-3.2748413-4.7550049-8.4608002-9.0810547-8.6103821l-48.4742432,2.5349731
+ c-4.3260498-0.1495819-11.4047852-0.1500549-15.730835-0.0010834l-48.7462158-2.5328064
+ c-4.3260498,0.1490479-9.2781982,5.3344574-9.0810547,8.6092987l5.4658203,86.9454346
+ c0.0286865,0.4833679,0.1552734,0.9471436,0.3277588,1.3978424"/>
+ </g>
+ <g>
+ <path class="st2" d="M1401.848877,141.9467468c-2.8059082,0.000946-5.6011963,0.0380554-7.7299805,0.1113739
+ l-48.7453613-2.5328827c-4.3260498,0.1490021-9.2788086,5.334549-9.0811768,8.609436l5.4648438,86.9454651
+ c0.0291748,0.4832611,0.1561279,0.9470215,0.3283691,1.3975525
+ c3.4455566,13.3038635,28.8806152,20.6496277,59.7635498,20.6496277"/>
+ </g>
+ <g>
+ <path class="st6" d="M1461.5471191,118.1488495c-3.6014404-24.8404541-28.9459229-44.0927124-59.6981201-44.0927124
+ c-30.7520752,0-56.0966797,19.2522583-59.697998,44.0927124l-0.4554443,22.3807983
+ c0,0,22.9992676,10.3432465,60.1534424,10.3432465c37.1542969,0,60.1535645-10.3432465,60.1535645-10.3432465
+ L1461.5471191,118.1488495z"/>
+ </g>
+ <g>
+ <g>
+ <path class="st3" d="M1365.4659424,124.1972198c0.1817627,0.3151855,0.4379883,0.561058,0.7335205,0.7277908l15.00354,8.6623001
+ l0.0003662-0.000473c0.2927246,0.172348,0.6333008,0.2711639,0.9971924,0.2711639s0.704834-0.0988159,0.9970703-0.2711639
+ l15.0040283-8.6623001c0.2954102-0.1667252,0.5506592-0.4121323,0.7329102-0.7273178
+ c0.1821289-0.3151932,0.2669678-0.6594162,0.2636719-0.9989624v-17.3245926l-0.0004883-0.000473
+ c0.0028076-0.3390732-0.0819092-0.6837616-0.2636719-0.9989548c-0.1821289-0.3151855-0.4383545-0.5605927-0.7333984-0.7277908
+ l-15.0040283-8.6623001v-0.0004654c-0.2922363-0.172348-0.6326904-0.2711639-0.996582-0.2711639
+ c-0.3634033,0-0.7039795,0.0988159-0.9962158,0.2711639v0.0004654l-15.00354,8.6623001
+ c-0.2955322,0.1671982-0.5516357,0.4126053-0.7338867,0.7277908c-0.1816406,0.3151932-0.2664795,0.6598816-0.2636719,0.9989548
+ l-0.0004883,0.000473v17.3245926c-0.0031738,0.3395462,0.081543,0.6837692,0.2633057,0.9989624"/>
+ </g>
+ </g>
+ <circle cx="1382.2003174" cy="114.5352554" r="7.8991222"/>
+ <circle class="st3" cx="1384.4804688" cy="112.5474625" r="2.2802224"/>
+ <g>
+ <g>
+ <path class="st3" d="M1405.2994385,124.1972198c0.1816406,0.3151855,0.4378662,0.561058,0.7333984,0.7277908l15.00354,8.6623001
+ l0.0004883-0.000473c0.2927246,0.172348,0.6331787,0.2711639,0.9970703,0.2711639s0.704834-0.0988159,0.9970703-0.2711639
+ l15.0040283-8.6623001c0.2955322-0.1667252,0.5507812-0.4121323,0.7329102-0.7273178
+ c0.182251-0.3151932,0.2669678-0.6594162,0.2636719-0.9989624v-17.3245926l-0.0004883-0.000473
+ c0.0028076-0.3390732-0.0819092-0.6837616-0.2636719-0.9989548c-0.1821289-0.3151855-0.4383545-0.5605927-0.7333984-0.7277908
+ l-15.0040283-8.6623001v-0.0004654c-0.2922363-0.172348-0.6326904-0.2711639-0.996582-0.2711639
+ c-0.3634033,0-0.7038574,0.0988159-0.9960938,0.2711639v0.0004654l-15.00354,8.6623001
+ c-0.2955322,0.1671982-0.5517578,0.4126053-0.7338867,0.7277908c-0.1817627,0.3151932-0.2664795,0.6598816-0.2636719,0.9989548
+ l-0.0004883,0.000473v17.3245926c-0.0032959,0.3395462,0.0814209,0.6837692,0.2631836,0.9989624"/>
+ </g>
+ </g>
+ <circle cx="1422.0336914" cy="114.5352554" r="7.8991222"/>
+ <circle class="st3" cx="1423.0882568" cy="112.5474625" r="2.2802224"/>
+ <g>
+ <g>
+ <path class="st2" d="M1391.7996826,123.6621552C1391.7996826,123.6621552,1391.7996826,123.90728,1391.7996826,123.6621552
+ L1391.7996826,123.6621552z M1378.9281006,123.6621552L1378.9281006,123.6621552L1378.9281006,123.6621552z
+ M1391.3400879,122.4365921L1391.3400879,122.4365921L1391.3400879,122.4365921z"/>
+ </g>
+ <g>
+ <path class="st2" d="M1420.9908447,134.6922913L1420.9908447,134.6922913L1420.9908447,134.6922913z M1427.1968994,123.6621552
+ C1427.1968994,123.6621552,1427.1968994,123.90728,1427.1968994,123.6621552L1427.1968994,123.6621552z
+ M1414.3251953,123.6621552L1414.3251953,123.6621552L1414.3251953,123.6621552z M1426.5073242,122.4365921
+ L1426.5073242,122.4365921L1426.5073242,122.4365921z M1420.9908447,119.7403412L1420.9908447,119.7403412
+ L1420.9908447,119.7403412z"/>
+ </g>
+ <g>
+ <path class="st7" d="M1330.199585,137.1434174c0,35.296402,32.4090576,63.9747467,72.1733398,63.9747467
+ s72.1733398-28.6783142,72.1733398-63.9747314c0,0-10.5732422,50.0032501-72.1733398,51.4739227
+ c0,0-51.2568359,2.6962585-70.7943115-46.3265381L1330.199585,137.1434174z"/>
+ </g>
+ <g>
+ <path class="st3" d="M1402.1430664,190.0880432c-40.9135742,0-74.4719238-29.1685638-74.4719238-64.9551926
+ s33.3284912-64.9552002,74.4719238-64.9552002s74.2419434,29.16856,74.2419434,64.9552002
+ C1476.6148682,160.9194794,1443.286499,190.0880432,1402.1430664,190.0880432z M1402.1430664,62.6287918
+ c-39.7642822,0-72.1733398,27.9429855-72.1733398,62.5040588s32.4090576,62.5040512,72.1733398,62.5040512
+ s71.9434814-27.9429932,71.9434814-62.5040512S1441.9073486,62.6287918,1402.1430664,62.6287918z"/>
+ </g>
+ <g>
+ <rect x="1437.0030518" y="39.955864" class="st3" width="2.2985139" height="29.4136715"/>
+ </g>
+ </g>
+ <path d="M1421.5812988,147.3400879c2.2796631,0,3.9838867,2.0716553,3.5738525,4.3141785
+ c-2.0300293,11.1029358-11.7537842,19.5184631-23.4431152,19.5184631s-21.4130859-8.4155273-23.4431152-19.5184631
+ c-0.4100342-2.2425232,1.2941895-4.3141785,3.5738525-4.3141785H1421.5812988z"/>
+ <g>
+ <path class="st6" d="M1391.913208,233.8167572c0.0942383,0.1883545,0.2825928,0.2825317,0.4709473,0.4708862l8.8527832,5.0856323
+ l0,0c0.376709,0.1883545,0.8475342,0.1883545,1.2242432,0l8.8527832-5.0856323
+ c0.1883545-0.0941772,0.2825928-0.2825317,0.4709473-0.4708862c0.0941162-0.1883545,0.1883545-0.3767242,0.1883545-0.5650787
+ v-10.2654419l0,0c0-0.1883545-0.0942383-0.376709-0.1883545-0.5650635
+ c-0.0942383-0.1883545-0.2825928-0.282547-0.4709473-0.4709015l-8.8527832-5.0856323l0,0
+ c-0.376709-0.1883545-0.8475342-0.1883545-1.2242432,0l0,0l-8.8527832,5.0856323
+ c-0.1883545,0.0941772-0.376709,0.282547-0.4709473,0.4709015c-0.0941162,0.1883545-0.1883545,0.376709-0.1883545,0.5650635l0,0
+ v10.2654419C1391.7248535,233.440033,1391.8190918,233.6283875,1391.913208,233.8167572"/>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/pkg/deb/Makefile b/pkg/deb/Makefile
index 52813e37..c4f085f8 100644
--- a/pkg/deb/Makefile
+++ b/pkg/deb/Makefile
@@ -49,21 +49,6 @@ include Makefile.jsc17
include Makefile.jsc18
endif
-# Ubuntu 21.04
-ifeq ($(CODENAME),hirsute)
-include Makefile.php
-include Makefile.python27
-include Makefile.python39
-include Makefile.go
-include Makefile.perl
-include Makefile.ruby
-include Makefile.jsc-common
-include Makefile.jsc11
-include Makefile.jsc15
-include Makefile.jsc16
-include Makefile.jsc17
-endif
-
# Ubuntu 20.04
ifeq ($(CODENAME),focal)
include Makefile.php
diff --git a/pkg/deb/Makefile.jsc13 b/pkg/deb/Makefile.jsc13
deleted file mode 100644
index d22944dc..00000000
--- a/pkg/deb/Makefile.jsc13
+++ /dev/null
@@ -1,71 +0,0 @@
-MODULES+= jsc13
-MODULE_SUFFIX_jsc13= jsc13
-
-MODULE_SUMMARY_jsc13= Java 13 module for NGINX Unit
-
-MODULE_VERSION_jsc13= $(VERSION)
-MODULE_RELEASE_jsc13= 1
-
-MODULE_CONFARGS_jsc13= java --module=java13 --home=/usr/lib/jvm/java-13-openjdk-$$\(DEB_HOST_ARCH\) --jars=/usr/share/unit-jsc-common/
-MODULE_MAKEARGS_jsc13= java13
-MODULE_INSTARGS_jsc13= java13-install
-
-MODULE_SOURCES_jsc13= unit.example-jsc-app \
- unit.example-jsc13-config
-
-BUILD_DEPENDS_jsc13= openjdk-13-jdk-headless openjdk-13-jre-headless
-BUILD_DEPENDS+= $(BUILD_DEPENDS_jsc13)
-
-MODULE_BUILD_DEPENDS_jsc13=,openjdk-13-jdk-headless
-MODULE_DEPENDS_jsc13=,openjdk-13-jre-headless,unit-jsc-common (= $(MODULE_VERSION_jsc_common)-$(MODULE_RELEASE_jsc_common)~$(CODENAME))
-
-define MODULE_PREINSTALL_jsc13
- mkdir -p debian/unit-jsc13/usr/share/doc/unit-jsc13/examples/jsc-app
- install -m 644 -p debian/unit.example-jsc-app debian/unit-jsc13/usr/share/doc/unit-jsc13/examples/jsc-app/index.jsp
- install -m 644 -p debian/unit.example-jsc13-config debian/unit-jsc13/usr/share/doc/unit-jsc13/examples/unit.config
- install -m 644 -p src/java/README.JSR-340 debian/unit-jsc13/usr/share/doc/unit-jsc13/
-endef
-export MODULE_PREINSTALL_jsc13
-
-define MODULE_POSTINSTALL_jsc13
- cd $$\(BUILDDIR_unit\) \&\& \
- DESTDIR=$$\(INSTALLDIR\) make java-shared-uninstall
-endef
-export MODULE_POSTINSTALL_jsc13
-
-define MODULE_POST_jsc13
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_jsc13) has been installed.
-
-To check out the sample app, run these commands:
-
- sudo service unit restart
- cd /usr/share/doc/unit-$(MODULE_SUFFIX_jsc13)/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/control.unit.sock http://localhost/config
- curl http://localhost:8800/
-
-Online documentation is available at https://unit.nginx.org
-
-NOTICE:
-
-This version of Unit code is made available in support of the open source
-development process. This is an intermediate build made available for
-testing purposes only. This Unit code is untested and presumed incompatible
-with the JSR 340 Java Servlet 3.1 specification. You should not deploy or
-write to this code. You should instead deploy and write production
-applications on pre-built binaries that have been tested and certified
-to meet the JSR-340 compatibility requirements such as certified binaries
-published for the JSR-340 reference implementation available at
-https://javaee.github.io/glassfish/.
-
-Redistribution of any Intermediate Build must retain this notice.
-
-Oracle and Java are registered trademarks of Oracle and/or its affiliates.
-Other names may be trademarks of their respective owners.
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_jsc13
diff --git a/pkg/deb/Makefile.jsc14 b/pkg/deb/Makefile.jsc14
deleted file mode 100644
index 9b53a385..00000000
--- a/pkg/deb/Makefile.jsc14
+++ /dev/null
@@ -1,71 +0,0 @@
-MODULES+= jsc14
-MODULE_SUFFIX_jsc14= jsc14
-
-MODULE_SUMMARY_jsc14= Java 14 module for NGINX Unit
-
-MODULE_VERSION_jsc14= $(VERSION)
-MODULE_RELEASE_jsc14= 1
-
-MODULE_CONFARGS_jsc14= java --module=java14 --home=/usr/lib/jvm/java-14-openjdk-$$\(DEB_HOST_ARCH\) --jars=/usr/share/unit-jsc-common/
-MODULE_MAKEARGS_jsc14= java14
-MODULE_INSTARGS_jsc14= java14-install
-
-MODULE_SOURCES_jsc14= unit.example-jsc-app \
- unit.example-jsc14-config
-
-BUILD_DEPENDS_jsc14= openjdk-14-jdk-headless openjdk-14-jre-headless
-BUILD_DEPENDS+= $(BUILD_DEPENDS_jsc14)
-
-MODULE_BUILD_DEPENDS_jsc14=,openjdk-14-jdk-headless
-MODULE_DEPENDS_jsc14=,openjdk-14-jre-headless,unit-jsc-common (= $(MODULE_VERSION_jsc_common)-$(MODULE_RELEASE_jsc_common)~$(CODENAME))
-
-define MODULE_PREINSTALL_jsc14
- mkdir -p debian/unit-jsc14/usr/share/doc/unit-jsc14/examples/jsc-app
- install -m 644 -p debian/unit.example-jsc-app debian/unit-jsc14/usr/share/doc/unit-jsc14/examples/jsc-app/index.jsp
- install -m 644 -p debian/unit.example-jsc14-config debian/unit-jsc14/usr/share/doc/unit-jsc14/examples/unit.config
- install -m 644 -p src/java/README.JSR-340 debian/unit-jsc14/usr/share/doc/unit-jsc14/
-endef
-export MODULE_PREINSTALL_jsc14
-
-define MODULE_POSTINSTALL_jsc14
- cd $$\(BUILDDIR_unit\) \&\& \
- DESTDIR=$$\(INSTALLDIR\) make java-shared-uninstall
-endef
-export MODULE_POSTINSTALL_jsc14
-
-define MODULE_POST_jsc14
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_jsc14) has been installed.
-
-To check out the sample app, run these commands:
-
- sudo service unit restart
- cd /usr/share/doc/unit-$(MODULE_SUFFIX_jsc14)/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/control.unit.sock http://localhost/config
- curl http://localhost:8800/
-
-Online documentation is available at https://unit.nginx.org
-
-NOTICE:
-
-This version of Unit code is made available in support of the open source
-development process. This is an intermediate build made available for
-testing purposes only. This Unit code is untested and presumed incompatible
-with the JSR 340 Java Servlet 3.1 specification. You should not deploy or
-write to this code. You should instead deploy and write production
-applications on pre-built binaries that have been tested and certified
-to meet the JSR-340 compatibility requirements such as certified binaries
-published for the JSR-340 reference implementation available at
-https://javaee.github.io/glassfish/.
-
-Redistribution of any Intermediate Build must retain this notice.
-
-Oracle and Java are registered trademarks of Oracle and/or its affiliates.
-Other names may be trademarks of their respective owners.
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_jsc14
diff --git a/pkg/deb/Makefile.jsc15 b/pkg/deb/Makefile.jsc15
deleted file mode 100644
index 10b5505b..00000000
--- a/pkg/deb/Makefile.jsc15
+++ /dev/null
@@ -1,71 +0,0 @@
-MODULES+= jsc15
-MODULE_SUFFIX_jsc15= jsc15
-
-MODULE_SUMMARY_jsc15= Java 15 module for NGINX Unit
-
-MODULE_VERSION_jsc15= $(VERSION)
-MODULE_RELEASE_jsc15= 1
-
-MODULE_CONFARGS_jsc15= java --module=java15 --home=/usr/lib/jvm/java-15-openjdk-$$\(DEB_HOST_ARCH\) --jars=/usr/share/unit-jsc-common/
-MODULE_MAKEARGS_jsc15= java15
-MODULE_INSTARGS_jsc15= java15-install
-
-MODULE_SOURCES_jsc15= unit.example-jsc-app \
- unit.example-jsc15-config
-
-BUILD_DEPENDS_jsc15= openjdk-15-jdk-headless openjdk-15-jre-headless
-BUILD_DEPENDS+= $(BUILD_DEPENDS_jsc15)
-
-MODULE_BUILD_DEPENDS_jsc15=,openjdk-15-jdk-headless
-MODULE_DEPENDS_jsc15=,openjdk-15-jre-headless,unit-jsc-common (= $(MODULE_VERSION_jsc_common)-$(MODULE_RELEASE_jsc_common)~$(CODENAME))
-
-define MODULE_PREINSTALL_jsc15
- mkdir -p debian/unit-jsc15/usr/share/doc/unit-jsc15/examples/jsc-app
- install -m 644 -p debian/unit.example-jsc-app debian/unit-jsc15/usr/share/doc/unit-jsc15/examples/jsc-app/index.jsp
- install -m 644 -p debian/unit.example-jsc15-config debian/unit-jsc15/usr/share/doc/unit-jsc15/examples/unit.config
- install -m 644 -p src/java/README.JSR-340 debian/unit-jsc15/usr/share/doc/unit-jsc15/
-endef
-export MODULE_PREINSTALL_jsc15
-
-define MODULE_POSTINSTALL_jsc15
- cd $$\(BUILDDIR_unit\) \&\& \
- DESTDIR=$$\(INSTALLDIR\) make java-shared-uninstall
-endef
-export MODULE_POSTINSTALL_jsc15
-
-define MODULE_POST_jsc15
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_jsc15) has been installed.
-
-To check out the sample app, run these commands:
-
- sudo service unit restart
- cd /usr/share/doc/unit-$(MODULE_SUFFIX_jsc15)/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/control.unit.sock http://localhost/config
- curl http://localhost:8800/
-
-Online documentation is available at https://unit.nginx.org
-
-NOTICE:
-
-This version of Unit code is made available in support of the open source
-development process. This is an intermediate build made available for
-testing purposes only. This Unit code is untested and presumed incompatible
-with the JSR 340 Java Servlet 3.1 specification. You should not deploy or
-write to this code. You should instead deploy and write production
-applications on pre-built binaries that have been tested and certified
-to meet the JSR-340 compatibility requirements such as certified binaries
-published for the JSR-340 reference implementation available at
-https://javaee.github.io/glassfish/.
-
-Redistribution of any Intermediate Build must retain this notice.
-
-Oracle and Java are registered trademarks of Oracle and/or its affiliates.
-Other names may be trademarks of their respective owners.
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_jsc15
diff --git a/pkg/deb/Makefile.python b/pkg/deb/Makefile.python
deleted file mode 100644
index 9bf02bac..00000000
--- a/pkg/deb/Makefile.python
+++ /dev/null
@@ -1,46 +0,0 @@
-MODULES+= python
-MODULE_SUFFIX_python= python
-
-MODULE_SUMMARY_python= Python module for NGINX Unit
-
-MODULE_VERSION_python= $(VERSION)
-MODULE_RELEASE_python= 1
-
-MODULE_CONFARGS_python= python
-MODULE_MAKEARGS_python= python
-MODULE_INSTARGS_python= python-install
-
-MODULE_SOURCES_python= unit.example-python-app \
- unit.example-python-config
-
-BUILD_DEPENDS_python= python-dev
-BUILD_DEPENDS+= $(BUILD_DEPENDS_python)
-
-MODULE_BUILD_DEPENDS_python=,python-dev
-
-define MODULE_PREINSTALL_python
- mkdir -p debian/unit-python/usr/share/doc/unit-python/examples/python-app
- install -m 644 -p debian/unit.example-python-app debian/unit-python/usr/share/doc/unit-python/examples/python-app/wsgi.py
- install -m 644 -p debian/unit.example-python-config debian/unit-python/usr/share/doc/unit-python/examples/unit.config
-endef
-export MODULE_PREINSTALL_python
-
-define MODULE_POST_python
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_python) has been installed.
-
-To check out the sample app, run these commands:
-
- sudo service unit restart
- cd /usr/share/doc/unit-$(MODULE_SUFFIX_python)/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/control.unit.sock http://localhost/config
- curl http://localhost:8400/
-
-Online documentation is available at https://unit.nginx.org
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_python
diff --git a/pkg/deb/Makefile.python34 b/pkg/deb/Makefile.python34
deleted file mode 100644
index 03c496bd..00000000
--- a/pkg/deb/Makefile.python34
+++ /dev/null
@@ -1,46 +0,0 @@
-MODULES+= python34
-MODULE_SUFFIX_python34= python3.4
-
-MODULE_SUMMARY_python34= Python 3.4 module for NGINX Unit
-
-MODULE_VERSION_python34= $(VERSION)
-MODULE_RELEASE_python34= 1
-
-MODULE_CONFARGS_python34= python --config=python3.4-config
-MODULE_MAKEARGS_python34= python3.4
-MODULE_INSTARGS_python34= python3.4-install
-
-MODULE_SOURCES_python34= unit.example-python-app \
- unit.example-python3.4-config
-
-BUILD_DEPENDS_python34= python3.4-dev
-BUILD_DEPENDS+= $(BUILD_DEPENDS_python34)
-
-MODULE_BUILD_DEPENDS_python34=,python3.4-dev
-
-define MODULE_PREINSTALL_python34
- mkdir -p debian/unit-python3.4/usr/share/doc/unit-python3.4/examples/python-app
- install -m 644 -p debian/unit.example-python-app debian/unit-python3.4/usr/share/doc/unit-python3.4/examples/python-app/wsgi.py
- install -m 644 -p debian/unit.example-python3.4-config debian/unit-python3.4/usr/share/doc/unit-python3.4/examples/unit.config
-endef
-export MODULE_PREINSTALL_python34
-
-define MODULE_POST_python34
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_python34) has been installed.
-
-To check out the sample app, run these commands:
-
- sudo service unit restart
- cd /usr/share/doc/unit-$(MODULE_SUFFIX_python34)/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/control.unit.sock http://localhost/config
- curl http://localhost:8400/
-
-Online documentation is available at https://unit.nginx.org
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_python34
diff --git a/pkg/deb/Makefile.python35 b/pkg/deb/Makefile.python35
deleted file mode 100644
index 514a4bf6..00000000
--- a/pkg/deb/Makefile.python35
+++ /dev/null
@@ -1,46 +0,0 @@
-MODULES+= python35
-MODULE_SUFFIX_python35= python3.5
-
-MODULE_SUMMARY_python35= Python 3.5 module for NGINX Unit
-
-MODULE_VERSION_python35= $(VERSION)
-MODULE_RELEASE_python35= 1
-
-MODULE_CONFARGS_python35= python --config=python3.5-config
-MODULE_MAKEARGS_python35= python3.5
-MODULE_INSTARGS_python35= python3.5-install
-
-MODULE_SOURCES_python35= unit.example-python-app \
- unit.example-python3.5-config
-
-BUILD_DEPENDS_python35= python3.5-dev
-BUILD_DEPENDS+= $(BUILD_DEPENDS_python35)
-
-MODULE_BUILD_DEPENDS_python35=,python3.5-dev
-
-define MODULE_PREINSTALL_python35
- mkdir -p debian/unit-python3.5/usr/share/doc/unit-python3.5/examples/python-app
- install -m 644 -p debian/unit.example-python-app debian/unit-python3.5/usr/share/doc/unit-python3.5/examples/python-app/wsgi.py
- install -m 644 -p debian/unit.example-python3.5-config debian/unit-python3.5/usr/share/doc/unit-python3.5/examples/unit.config
-endef
-export MODULE_PREINSTALL_python35
-
-define MODULE_POST_python35
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_python35) has been installed.
-
-To check out the sample app, run these commands:
-
- sudo service unit restart
- cd /usr/share/doc/unit-$(MODULE_SUFFIX_python35)/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/control.unit.sock http://localhost/config
- curl http://localhost:8400/
-
-Online documentation is available at https://unit.nginx.org
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_python35
diff --git a/pkg/deb/debian.module/copyright.unit-jsc10 b/pkg/deb/debian.module/copyright.unit-jsc10
deleted file mode 100644
index 42dbd3b9..00000000
--- a/pkg/deb/debian.module/copyright.unit-jsc10
+++ /dev/null
@@ -1,33 +0,0 @@
-
- NGINX Unit.
-
- Copyright 2017-2022 NGINX, Inc.
- Copyright 2017-2022 Valentin V. Bartenev
- Copyright 2017-2022 Max Romanov
- Copyright 2017-2022 Andrei Zeliankou
- Copyright 2018-2022 Konstantin Pavlov
- Copyright 2021-2022 Zhidao Hong
- Copyright 2021-2022 Oisín Canty
- Copyright 2017-2021 Igor Sysoev
- Copyright 2017-2021 Andrei Belov
- Copyright 2019-2021 Tiago Natel de Moura
- Copyright 2019-2020 Axel Duch
- Copyright 2018-2019 Alexander Borisov
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
- /usr/share/common-licenses/Apache-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The unit-jsc10 package provides Java servlet container module
- for NGINX Unit.
-
- Java is a registered trademark of Oracle and/or its affiliates.
diff --git a/pkg/deb/debian.module/unit.example-jsc10-config b/pkg/deb/debian.module/unit.example-jsc10-config
deleted file mode 100644
index 969491e5..00000000
--- a/pkg/deb/debian.module/unit.example-jsc10-config
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "applications": {
- "example_java10": {
- "processes": 1,
- "type": "java 10",
- "webapp": "/usr/share/doc/unit-jsc10/examples/jsc-app"
- }
- },
-
- "listeners": {
- "*:8800": {
- "pass": "applications/example_java10"
- }
- }
-}
diff --git a/pkg/deb/debian.module/unit.example-jsc13-config b/pkg/deb/debian.module/unit.example-jsc13-config
deleted file mode 100644
index ac0b1db6..00000000
--- a/pkg/deb/debian.module/unit.example-jsc13-config
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "applications": {
- "example_java13": {
- "processes": 1,
- "type": "java 13",
- "webapp": "/usr/share/doc/unit-jsc13/examples/jsc-app"
- }
- },
-
- "listeners": {
- "*:8800": {
- "pass": "applications/example_java13"
- }
- }
-}
diff --git a/pkg/deb/debian.module/unit.example-jsc14-config b/pkg/deb/debian.module/unit.example-jsc14-config
deleted file mode 100644
index 76109835..00000000
--- a/pkg/deb/debian.module/unit.example-jsc14-config
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "applications": {
- "example_java14": {
- "processes": 1,
- "type": "java 14",
- "webapp": "/usr/share/doc/unit-jsc14/examples/jsc-app"
- }
- },
-
- "listeners": {
- "*:8800": {
- "pass": "applications/example_java14"
- }
- }
-}
diff --git a/pkg/deb/debian.module/unit.example-jsc15-config b/pkg/deb/debian.module/unit.example-jsc15-config
deleted file mode 100644
index 9f9aec15..00000000
--- a/pkg/deb/debian.module/unit.example-jsc15-config
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "applications": {
- "example_java15": {
- "processes": 1,
- "type": "java 15",
- "webapp": "/usr/share/doc/unit-jsc15/examples/jsc-app"
- }
- },
-
- "listeners": {
- "*:8800": {
- "pass": "applications/example_java15"
- }
- }
-}
diff --git a/pkg/deb/debian.module/unit.example-jsc9-config b/pkg/deb/debian.module/unit.example-jsc9-config
deleted file mode 100644
index a8faa268..00000000
--- a/pkg/deb/debian.module/unit.example-jsc9-config
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "applications": {
- "example_java9": {
- "processes": 1,
- "type": "java 9",
- "webapp": "/usr/share/doc/unit-jsc9/examples/jsc-app"
- }
- },
-
- "listeners": {
- "*:8800": {
- "pass": "applications/example_java9"
- }
- }
-}
diff --git a/pkg/deb/debian.module/unit.example-python-config b/pkg/deb/debian.module/unit.example-python-config
deleted file mode 100644
index b3d3a2e5..00000000
--- a/pkg/deb/debian.module/unit.example-python-config
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "applications": {
- "example_python": {
- "type": "python",
- "processes": 2,
- "path": "/usr/share/doc/unit-python/examples/python-app",
- "module": "wsgi"
- }
- },
-
- "listeners": {
- "*:8400": {
- "pass": "applications/example_python"
- }
- }
-}
diff --git a/pkg/deb/debian.module/unit.example-python3.4-config b/pkg/deb/debian.module/unit.example-python3.4-config
deleted file mode 100644
index e6d90acf..00000000
--- a/pkg/deb/debian.module/unit.example-python3.4-config
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "applications": {
- "example_python": {
- "type": "python 3.4",
- "processes": 2,
- "path": "/usr/share/doc/unit-python3.4/examples/python-app",
- "module": "wsgi"
- }
- },
-
- "listeners": {
- "*:8400": {
- "pass": "applications/example_python"
- }
- }
-}
diff --git a/pkg/deb/debian.module/unit.example-python3.5-config b/pkg/deb/debian.module/unit.example-python3.5-config
deleted file mode 100644
index 480327ec..00000000
--- a/pkg/deb/debian.module/unit.example-python3.5-config
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "applications": {
- "example_python": {
- "type": "python 3.5",
- "processes": 2,
- "path": "/usr/share/doc/unit-python3.5/examples/python-app",
- "module": "wsgi"
- }
- },
-
- "listeners": {
- "*:8400": {
- "pass": "applications/example_python"
- }
- }
-}
diff --git a/pkg/deb/debian/dirs b/pkg/deb/debian/dirs
index fdcb4340..4a6618c8 100644
--- a/pkg/deb/debian/dirs
+++ b/pkg/deb/debian/dirs
@@ -1,4 +1,3 @@
usr/sbin
-etc/unit
usr/lib/unit
var/lib/unit
diff --git a/pkg/docker/Dockerfile.go1.18 b/pkg/docker/Dockerfile.go1.19
index 9162d8cf..1625b64f 100644
--- a/pkg/docker/Dockerfile.go1.18
+++ b/pkg/docker/Dockerfile.go1.19
@@ -1,4 +1,4 @@
-FROM golang:1.18 as BUILDER
+FROM golang:1.19 as BUILDER
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
@@ -8,7 +8,7 @@ RUN set -ex \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
- && hg up 1.27.0 \
+ && hg up 1.28.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
@@ -40,7 +40,7 @@ RUN set -ex \
&& make -j $NCPU go-install-src libunit-install \
&& ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt
-FROM golang:1.18
+FROM golang:1.19
COPY docker-entrypoint.sh /usr/local/bin/
COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd
COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug
diff --git a/pkg/docker/Dockerfile.jsc11 b/pkg/docker/Dockerfile.jsc11
index 69fc72ad..fe344d0e 100644
--- a/pkg/docker/Dockerfile.jsc11
+++ b/pkg/docker/Dockerfile.jsc11
@@ -1,4 +1,4 @@
-FROM openjdk:11-jdk as BUILDER
+FROM eclipse-temurin:11-jdk as BUILDER
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
@@ -8,7 +8,7 @@ RUN set -ex \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
- && hg up 1.27.0 \
+ && hg up 1.28.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
@@ -40,7 +40,7 @@ RUN set -ex \
&& make -j $NCPU java-shared-install java-install \
&& ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt
-FROM openjdk:11-jdk
+FROM eclipse-temurin:11-jdk
COPY docker-entrypoint.sh /usr/local/bin/
COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd
COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug
diff --git a/pkg/docker/Dockerfile.minimal b/pkg/docker/Dockerfile.minimal
index 730e1893..c57379f7 100644
--- a/pkg/docker/Dockerfile.minimal
+++ b/pkg/docker/Dockerfile.minimal
@@ -8,7 +8,7 @@ RUN set -ex \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
- && hg up 1.27.0 \
+ && hg up 1.28.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
diff --git a/pkg/docker/Dockerfile.node16 b/pkg/docker/Dockerfile.node16
index 246105d8..d341e43f 100644
--- a/pkg/docker/Dockerfile.node16
+++ b/pkg/docker/Dockerfile.node16
@@ -8,7 +8,7 @@ RUN set -ex \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
- && hg up 1.27.0 \
+ && hg up 1.28.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
diff --git a/pkg/docker/Dockerfile.perl5.34 b/pkg/docker/Dockerfile.perl5.36
index db87d209..d0b8006f 100644
--- a/pkg/docker/Dockerfile.perl5.34
+++ b/pkg/docker/Dockerfile.perl5.36
@@ -1,4 +1,4 @@
-FROM perl:5.34 as BUILDER
+FROM perl:5.36 as BUILDER
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
@@ -8,7 +8,7 @@ RUN set -ex \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
- && hg up 1.27.0 \
+ && hg up 1.28.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
@@ -40,7 +40,7 @@ RUN set -ex \
&& make -j $NCPU perl-install \
&& ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt
-FROM perl:5.34
+FROM perl:5.36
COPY docker-entrypoint.sh /usr/local/bin/
COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd
COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug
diff --git a/pkg/docker/Dockerfile.php8.1 b/pkg/docker/Dockerfile.php8.1
index 5c18a9bc..c63e708e 100644
--- a/pkg/docker/Dockerfile.php8.1
+++ b/pkg/docker/Dockerfile.php8.1
@@ -8,7 +8,7 @@ RUN set -ex \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
- && hg up 1.27.0 \
+ && hg up 1.28.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
diff --git a/pkg/docker/Dockerfile.python3.10 b/pkg/docker/Dockerfile.python3.10
index 09e7f42a..6502f8a8 100644
--- a/pkg/docker/Dockerfile.python3.10
+++ b/pkg/docker/Dockerfile.python3.10
@@ -8,7 +8,7 @@ RUN set -ex \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
- && hg up 1.27.0 \
+ && hg up 1.28.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
diff --git a/pkg/docker/Dockerfile.ruby3.1 b/pkg/docker/Dockerfile.ruby3.1
index 0baedc32..f365bc96 100644
--- a/pkg/docker/Dockerfile.ruby3.1
+++ b/pkg/docker/Dockerfile.ruby3.1
@@ -8,7 +8,7 @@ RUN set -ex \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& hg clone https://hg.nginx.org/unit \
&& cd unit \
- && hg up 1.27.0 \
+ && hg up 1.28.0 \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
diff --git a/pkg/docker/Makefile b/pkg/docker/Makefile
index 5c48f925..03723d1d 100644
--- a/pkg/docker/Makefile
+++ b/pkg/docker/Makefile
@@ -18,7 +18,7 @@ INSTALL_minimal ?= version
define COPY_minimal
endef
-VERSION_go ?= 1.18
+VERSION_go ?= 1.19
CONTAINER_go ?= golang:$(VERSION_go)
CONFIGURE_go ?= go --go-path=$$GOPATH
INSTALL_go ?= go-install-src libunit-install
@@ -29,7 +29,7 @@ COPY --from=BUILDER /go/src/ /go/src/
endef
VERSION_jsc ?= 11
-CONTAINER_jsc ?= openjdk:$(VERSION_jsc)-jdk
+CONTAINER_jsc ?= eclipse-temurin:$(VERSION_jsc)-jdk
CONFIGURE_jsc ?= java --jars=/usr/share/unit-jsc-common/
INSTALL_jsc ?= java-shared-install java-install
COPY_jsc = COPY --from=BUILDER /usr/share/unit-jsc-common/ /usr/share/unit-jsc-common/
@@ -44,7 +44,7 @@ COPY --from=BUILDER /usr/include/nxt_* /usr/include/\n\$
COPY --from=BUILDER /usr/local/lib/node_modules/unit-http/ /usr/local/lib/node_modules/unit-http/
endef
-VERSION_perl ?= 5.34
+VERSION_perl ?= 5.36
CONTAINER_perl ?= perl:$(VERSION_perl)
CONFIGURE_perl ?= perl
INSTALL_perl ?= perl-install
diff --git a/pkg/rpm/Makefile b/pkg/rpm/Makefile
index a360b36e..bbe44fe5 100644
--- a/pkg/rpm/Makefile
+++ b/pkg/rpm/Makefile
@@ -10,25 +10,15 @@ RELEASE ?= $(DEFAULT_RELEASE)
PACKAGE_VENDOR = NGINX Packaging <nginx-packaging@f5.com>
-ifeq ($(shell test `rpm --eval '0%{?rhel} -eq 6 -a 0%{?amzn} -eq 0'`; echo $$?), 0)
-OSVER = centos6
-else ifeq ($(shell test `rpm --eval '0%{?rhel} -eq 7 -a 0%{?amzn} -eq 0'`; echo $$?), 0)
+ifeq ($(shell test `rpm --eval '0%{?rhel} -eq 7 -a 0%{?amzn} -eq 0'`; echo $$?), 0)
OSVER = centos7
else ifeq ($(shell rpm --eval "%{?rhel}"), 8)
OSVER = centos8
else ifeq ($(shell rpm --eval "%{?rhel}"), 9)
OSVER = centos9
-else ifeq ($(shell rpm --eval "%{?amzn}"), 1)
-OSVER = amazonlinux1
else ifeq ($(shell rpm --eval "%{?amzn}"), 2)
OSVER = amazonlinux2
-else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1315 -a 0%{?suse_version} -lt 1330 -a 0%{?is_opensuse} -eq 1'`; echo $$?), 0)
-OSVER = opensuse-leap
-else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1330 -a 0%{?is_opensuse} -eq 1'`; echo $$?), 0)
-OSVER = opensuse-tumbleweed
-else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1315 -a 0%{?is_opensuse} -eq 0'`; echo $$?), 0)
-OSVER = sles
-else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 26'`; echo $$?),0)
+else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 35'`; echo $$?),0)
OSVER = fedora
endif
@@ -38,32 +28,16 @@ ifeq ($(OSVER), centos7)
BUILD_DEPENDS_unit += which
endif
-ifeq ($(OSVER), amazonlinux1)
-BUILD_DEPENDS_unit += system-rpm-config
-endif
-
-ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed sles))
-BUILD_DEPENDS_unit += libxml2-tools libxslt1 libopenssl-devel
-else
ifneq (,$(findstring $(OSVER),amazonlinux2))
BUILD_DEPENDS_unit += libxml2 libxslt openssl11-devel
else
BUILD_DEPENDS_unit += libxml2 libxslt openssl-devel
endif
-endif
BUILD_DEPENDS = $(BUILD_DEPENDS_unit)
MODULES=
-ifeq ($(OSVER), centos6)
-include Makefile.php
-include Makefile.python
-include Makefile.go
-include Makefile.jsc-common
-include Makefile.jsc8
-endif
-
ifeq ($(OSVER), centos7)
include Makefile.php
include Makefile.python27
@@ -96,18 +70,6 @@ include Makefile.jsc8
include Makefile.jsc11
endif
-ifeq ($(OSVER), amazonlinux1)
-include Makefile.php
-include Makefile.python27
-include Makefile.python34
-include Makefile.python35
-include Makefile.python36
-include Makefile.go
-include Makefile.perl
-include Makefile.jsc-common
-include Makefile.jsc8
-endif
-
ifeq ($(OSVER), amazonlinux2)
include Makefile.php
include Makefile.python27
@@ -118,45 +80,9 @@ include Makefile.jsc-common
include Makefile.jsc8
endif
-ifeq ($(OSVER), opensuse-leap)
-include Makefile.python27
-include Makefile.python34
-include Makefile.go
-include Makefile.perl
-include Makefile.ruby
-endif
-
-ifeq ($(OSVER), opensuse-tumbleweed)
-include Makefile.php
-include Makefile.python27
-include Makefile.python36
-include Makefile.go
-include Makefile.perl
-include Makefile.ruby
-endif
-
-ifeq ($(OSVER), sles)
-include Makefile.python27
-include Makefile.python34
-include Makefile.perl
-endif
-
ifeq ($(OSVER), fedora)
include Makefile.php
-ifeq ($(shell test `rpm --eval '0%{?fedora} -lt 32'`; echo $$?),0)
-include Makefile.python27
-endif
-ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 35'`; echo $$?),0)
include Makefile.python310
-else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 33'`; echo $$?),0)
-include Makefile.python39
-else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 32'`; echo $$?),0)
-include Makefile.python38
-else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 29'`; echo $$?),0)
-include Makefile.python37
-else
-include Makefile.python36
-endif
include Makefile.go
include Makefile.perl
include Makefile.ruby
diff --git a/pkg/rpm/Makefile.go b/pkg/rpm/Makefile.go
index a1421bee..aacbe2b9 100644
--- a/pkg/rpm/Makefile.go
+++ b/pkg/rpm/Makefile.go
@@ -15,28 +15,17 @@ MODULE_SOURCES_go= unit.example-go-app \
ifeq ($(OSVER), centos6)
BUILD_DEPENDS_go= epel-release golang
-else ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed))
-BUILD_DEPENDS_go= go1.9
else
BUILD_DEPENDS_go= golang
endif
BUILD_DEPENDS+= $(BUILD_DEPENDS_go)
-ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed))
define MODULE_DEFINITIONS_go
BuildArch: noarch
Requires: unit-devel == $(VERSION)-$(RELEASE)%{?dist}.ngx
BuildRequires: $(BUILD_DEPENDS_go)
-%define gopath /usr/share/go/contrib
endef
-else
-define MODULE_DEFINITIONS_go
-BuildArch: noarch
-Requires: unit-devel == $(VERSION)-$(RELEASE)%{?dist}.ngx
-BuildRequires: $(BUILD_DEPENDS_go)
-endef
-endif
export MODULE_DEFINITIONS_go
define MODULE_PREINSTALL_go
diff --git a/pkg/rpm/Makefile.perl b/pkg/rpm/Makefile.perl
index f59b7353..92440cfa 100644
--- a/pkg/rpm/Makefile.perl
+++ b/pkg/rpm/Makefile.perl
@@ -13,11 +13,7 @@ MODULE_INSTARGS_perl= perl-install
MODULE_SOURCES_perl= unit.example-perl-app \
unit.example-perl-config
-ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed sles))
-BUILD_DEPENDS_perl= perl
-else
BUILD_DEPENDS_perl= perl-devel perl-libs perl-ExtUtils-Embed
-endif
BUILD_DEPENDS+= $(BUILD_DEPENDS_perl)
diff --git a/pkg/rpm/Makefile.php b/pkg/rpm/Makefile.php
index 8f39efc0..0f5a10e5 100644
--- a/pkg/rpm/Makefile.php
+++ b/pkg/rpm/Makefile.php
@@ -13,11 +13,7 @@ MODULE_INSTARGS_php= php-install
MODULE_SOURCES_php= unit.example-php-app \
unit.example-php-config
-ifeq ($(OSVER), opensuse-tumbleweed)
-BUILD_DEPENDS_php= php7-devel php7-embed
-else
BUILD_DEPENDS_php= php-devel php-embedded
-endif
BUILD_DEPENDS+= $(BUILD_DEPENDS_php)
diff --git a/pkg/rpm/Makefile.python b/pkg/rpm/Makefile.python
deleted file mode 100644
index 334d62c1..00000000
--- a/pkg/rpm/Makefile.python
+++ /dev/null
@@ -1,57 +0,0 @@
-MODULES+= python
-MODULE_SUFFIX_python= python
-
-MODULE_SUMMARY_python= Python module for NGINX Unit
-
-MODULE_VERSION_python= $(VERSION)
-MODULE_RELEASE_python= 1
-
-MODULE_CONFARGS_python= python
-MODULE_MAKEARGS_python= python
-MODULE_INSTARGS_python= python-install
-
-MODULE_SOURCES_python= unit.example-python-app \
- unit.example-python-config
-
-ifeq ($(shell rpm --eval "%{?amzn}"), 1)
-BUILD_DEPENDS_python= python26-devel
-else
-BUILD_DEPENDS_python= python-devel
-endif
-
-BUILD_DEPENDS+= $(BUILD_DEPENDS_python)
-
-define MODULE_PREINSTALL_python
-%{__mkdir} -p %{buildroot}%{_datadir}/doc/unit-python/examples/python-app
-%{__install} -m 644 -p %{SOURCE100} \
- %{buildroot}%{_datadir}/doc/unit-python/examples/python-app/wsgi.py
-%{__install} -m 644 -p %{SOURCE101} \
- %{buildroot}%{_datadir}/doc/unit-python/examples/unit.config
-endef
-export MODULE_PREINSTALL_python
-
-define MODULE_FILES_python
-%{_libdir}/unit/modules/*
-%{_libdir}/unit/debug-modules/*
-endef
-export MODULE_FILES_python
-
-define MODULE_POST_python
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_python) has been installed.
-
-To check the sample app, run these commands:
-
- sudo service unit start
- cd /usr/share/doc/%{name}/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/unit/control.sock http://localhost/config
- curl http://localhost:8400/
-
-Online documentation is available at https://unit.nginx.org
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_python
diff --git a/pkg/rpm/Makefile.python27 b/pkg/rpm/Makefile.python27
index 079a8512..3de5f634 100644
--- a/pkg/rpm/Makefile.python27
+++ b/pkg/rpm/Makefile.python27
@@ -13,9 +13,7 @@ MODULE_INSTARGS_python27= python2.7-install
MODULE_SOURCES_python27= unit.example-python-app \
unit.example-python27-config
-ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed sles))
-BUILD_DEPENDS_python27= python-devel
-else ifneq (,$(findstring $(OSVER),fedora centos8))
+ifneq (,$(findstring $(OSVER),fedora centos8))
BUILD_DEPENDS_python27= python2-devel
else ifneq (,$(findstring $(OSVER),centos7 amazonlinux2))
BUILD_DEPENDS_python27= python-devel
diff --git a/pkg/rpm/Makefile.python310 b/pkg/rpm/Makefile.python310
index 82bc311a..50731475 100644
--- a/pkg/rpm/Makefile.python310
+++ b/pkg/rpm/Makefile.python310
@@ -13,7 +13,7 @@ MODULE_INSTARGS_python310= python3.10-install
MODULE_SOURCES_python310= unit.example-python-app \
unit.example-python310-config
-ifneq (,$(findstring $(OSVER),opensuse-tumbleweed sles fedora amazonlinux2))
+ifneq (,$(findstring $(OSVER),fedora amazonlinux2))
BUILD_DEPENDS_python310= python3-devel
else
BUILD_DEPENDS_python310= python310-devel
diff --git a/pkg/rpm/Makefile.python34 b/pkg/rpm/Makefile.python34
deleted file mode 100644
index 83c0bdb6..00000000
--- a/pkg/rpm/Makefile.python34
+++ /dev/null
@@ -1,57 +0,0 @@
-MODULES+= python34
-MODULE_SUFFIX_python34= python3.4
-
-MODULE_SUMMARY_python34= Python 3.4 module for NGINX Unit
-
-MODULE_VERSION_python34= $(VERSION)
-MODULE_RELEASE_python34= 1
-
-MODULE_CONFARGS_python34= python --config=python3.4-config
-MODULE_MAKEARGS_python34= python3.4
-MODULE_INSTARGS_python34= python3.4-install
-
-MODULE_SOURCES_python34= unit.example-python-app \
- unit.example-python34-config
-
-ifneq (,$(findstring $(OSVER),opensuse-leap sles))
-BUILD_DEPENDS_python34= python3-devel
-else
-BUILD_DEPENDS_python34= python34-devel
-endif
-
-BUILD_DEPENDS+= $(BUILD_DEPENDS_python34)
-
-define MODULE_PREINSTALL_python34
-%{__mkdir} -p %{buildroot}%{_datadir}/doc/unit-python34/examples/python-app
-%{__install} -m 644 -p %{SOURCE100} \
- %{buildroot}%{_datadir}/doc/unit-python34/examples/python-app/wsgi.py
-%{__install} -m 644 -p %{SOURCE101} \
- %{buildroot}%{_datadir}/doc/unit-python34/examples/unit.config
-endef
-export MODULE_PREINSTALL_python34
-
-define MODULE_FILES_python34
-%{_libdir}/unit/modules/*
-%{_libdir}/unit/debug-modules/*
-endef
-export MODULE_FILES_python34
-
-define MODULE_POST_python34
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_python34) has been installed.
-
-To check the sample app, run these commands:
-
- sudo service unit start
- cd /usr/share/doc/%{name}/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/unit/control.sock http://localhost/config
- curl http://localhost:8400/
-
-Online documentation is available at https://unit.nginx.org
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_python34
diff --git a/pkg/rpm/Makefile.python35 b/pkg/rpm/Makefile.python35
deleted file mode 100644
index 6f866771..00000000
--- a/pkg/rpm/Makefile.python35
+++ /dev/null
@@ -1,52 +0,0 @@
-MODULES+= python35
-MODULE_SUFFIX_python35= python3.5
-
-MODULE_SUMMARY_python35= Python 3.5 module for NGINX Unit
-
-MODULE_VERSION_python35= $(VERSION)
-MODULE_RELEASE_python35= 1
-
-MODULE_CONFARGS_python35= python --config=python3.5-config
-MODULE_MAKEARGS_python35= python3.5
-MODULE_INSTARGS_python35= python3.5-install
-
-MODULE_SOURCES_python35= unit.example-python-app \
- unit.example-python35-config
-
-BUILD_DEPENDS_python35= python35-devel
-BUILD_DEPENDS+= $(BUILD_DEPENDS_python35)
-
-define MODULE_PREINSTALL_python35
-%{__mkdir} -p %{buildroot}%{_datadir}/doc/unit-python35/examples/python-app
-%{__install} -m 644 -p %{SOURCE100} \
- %{buildroot}%{_datadir}/doc/unit-python35/examples/python-app/wsgi.py
-%{__install} -m 644 -p %{SOURCE101} \
- %{buildroot}%{_datadir}/doc/unit-python35/examples/unit.config
-endef
-export MODULE_PREINSTALL_python35
-
-define MODULE_FILES_python35
-%{_libdir}/unit/modules/*
-%{_libdir}/unit/debug-modules/*
-endef
-export MODULE_FILES_python35
-
-define MODULE_POST_python35
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_python35) has been installed.
-
-To check the sample app, run these commands:
-
- sudo service unit start
- cd /usr/share/doc/%{name}/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/unit/control.sock http://localhost/config
- curl http://localhost:8400/
-
-Online documentation is available at https://unit.nginx.org
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_python35
diff --git a/pkg/rpm/Makefile.python36 b/pkg/rpm/Makefile.python36
index 827d2253..c1fc8b6c 100644
--- a/pkg/rpm/Makefile.python36
+++ b/pkg/rpm/Makefile.python36
@@ -13,7 +13,7 @@ MODULE_INSTARGS_python36= python3.6-install
MODULE_SOURCES_python36= unit.example-python-app \
unit.example-python36-config
-ifneq (,$(findstring $(OSVER),opensuse-tumbleweed sles fedora centos7))
+ifneq (,$(findstring $(OSVER),fedora centos7))
BUILD_DEPENDS_python36= python3-devel
else
BUILD_DEPENDS_python36= python36-devel
diff --git a/pkg/rpm/Makefile.python37 b/pkg/rpm/Makefile.python37
index 563d4539..c0604fd9 100644
--- a/pkg/rpm/Makefile.python37
+++ b/pkg/rpm/Makefile.python37
@@ -13,7 +13,7 @@ MODULE_INSTARGS_python37= python3.7-install
MODULE_SOURCES_python37= unit.example-python-app \
unit.example-python37-config
-ifneq (,$(findstring $(OSVER),opensuse-tumbleweed sles fedora amazonlinux2))
+ifneq (,$(findstring $(OSVER),fedora amazonlinux2))
BUILD_DEPENDS_python37= python3-devel
else
BUILD_DEPENDS_python37= python37-devel
diff --git a/pkg/rpm/Makefile.python38 b/pkg/rpm/Makefile.python38
deleted file mode 100644
index ffcca07f..00000000
--- a/pkg/rpm/Makefile.python38
+++ /dev/null
@@ -1,57 +0,0 @@
-MODULES+= python38
-MODULE_SUFFIX_python38= python3.8
-
-MODULE_SUMMARY_python38= Python 3.8 module for NGINX Unit
-
-MODULE_VERSION_python38= $(VERSION)
-MODULE_RELEASE_python38= 1
-
-MODULE_CONFARGS_python38= python --config=python3.8-config
-MODULE_MAKEARGS_python38= python3.8
-MODULE_INSTARGS_python38= python3.8-install
-
-MODULE_SOURCES_python38= unit.example-python-app \
- unit.example-python38-config
-
-ifneq (,$(findstring $(OSVER),opensuse-tumbleweed sles fedora amazonlinux2))
-BUILD_DEPENDS_python38= python3-devel
-else
-BUILD_DEPENDS_python38= python38-devel
-endif
-
-BUILD_DEPENDS+= $(BUILD_DEPENDS_python38)
-
-define MODULE_PREINSTALL_python38
-%{__mkdir} -p %{buildroot}%{_datadir}/doc/unit-python38/examples/python-app
-%{__install} -m 644 -p %{SOURCE100} \
- %{buildroot}%{_datadir}/doc/unit-python38/examples/python-app/wsgi.py
-%{__install} -m 644 -p %{SOURCE101} \
- %{buildroot}%{_datadir}/doc/unit-python38/examples/unit.config
-endef
-export MODULE_PREINSTALL_python38
-
-define MODULE_FILES_python38
-%{_libdir}/unit/modules/*
-%{_libdir}/unit/debug-modules/*
-endef
-export MODULE_FILES_python38
-
-define MODULE_POST_python38
-cat <<BANNER
-----------------------------------------------------------------------
-
-The $(MODULE_SUMMARY_python38) has been installed.
-
-To check the sample app, run these commands:
-
- sudo service unit start
- cd /usr/share/doc/%{name}/examples
- sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/unit/control.sock http://localhost/config
- curl http://localhost:8400/
-
-Online documentation is available at https://unit.nginx.org
-
-----------------------------------------------------------------------
-BANNER
-endef
-export MODULE_POST_python38
diff --git a/pkg/rpm/Makefile.python39 b/pkg/rpm/Makefile.python39
index 3f791111..5d7c2327 100644
--- a/pkg/rpm/Makefile.python39
+++ b/pkg/rpm/Makefile.python39
@@ -13,7 +13,7 @@ MODULE_INSTARGS_python39= python3.9-install
MODULE_SOURCES_python39= unit.example-python-app \
unit.example-python39-config
-ifneq (,$(findstring $(OSVER),opensuse-tumbleweed sles fedora amazonlinux2 centos9))
+ifneq (,$(findstring $(OSVER),fedora amazonlinux2 centos9))
BUILD_DEPENDS_python39= python3-devel
else
BUILD_DEPENDS_python39= python39-devel
diff --git a/pkg/rpm/Makefile.ruby b/pkg/rpm/Makefile.ruby
index 51c2949d..7fddc145 100644
--- a/pkg/rpm/Makefile.ruby
+++ b/pkg/rpm/Makefile.ruby
@@ -13,13 +13,7 @@ MODULE_INSTARGS_ruby= ruby-install
MODULE_SOURCES_ruby= unit.example-ruby-app \
unit.example-ruby-config
-ifeq ($(OSVER), opensuse-leap)
-RACK_PACKAGE= ruby2.1-rubygem-rack
-else ifeq ($(OSVER), opensuse-tumbleweed)
-RACK_PACKAGE= ruby2.5-rubygem-rack
-else
RACK_PACKAGE= rubygem-rack
-endif
BUILD_DEPENDS_ruby= ruby-devel $(RACK_PACKAGE)
BUILD_DEPENDS+= $(BUILD_DEPENDS_ruby)
diff --git a/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10 b/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10
deleted file mode 100644
index c7860e4b..00000000
--- a/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10
+++ /dev/null
@@ -1,32 +0,0 @@
-
- NGINX Unit.
-
- Copyright 2017-2022 NGINX, Inc.
- Copyright 2017-2022 Valentin V. Bartenev
- Copyright 2017-2022 Max Romanov
- Copyright 2017-2022 Andrei Zeliankou
- Copyright 2018-2022 Konstantin Pavlov
- Copyright 2021-2022 Zhidao Hong
- Copyright 2021-2022 Oisín Canty
- Copyright 2017-2021 Igor Sysoev
- Copyright 2017-2021 Andrei Belov
- Copyright 2019-2021 Tiago Natel de Moura
- Copyright 2019-2020 Axel Duch
- Copyright 2018-2019 Alexander Borisov
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- The unit-jsc10 package provides Java servlet container module
- for NGINX Unit.
-
- Java is a registered trademark of Oracle and/or its affiliates.
diff --git a/pkg/rpm/rpmbuild/SOURCES/unit.example-python35-config b/pkg/rpm/rpmbuild/SOURCES/unit.example-python35-config
deleted file mode 100644
index f9923a49..00000000
--- a/pkg/rpm/rpmbuild/SOURCES/unit.example-python35-config
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "applications": {
- "example_python": {
- "type": "python 3.5",
- "processes": 2,
- "path": "/usr/share/doc/unit-python35/examples/python-app",
- "module": "wsgi"
- }
- },
-
- "listeners": {
- "*:8400": {
- "pass": "applications/example_python"
- }
- }
-}
diff --git a/pkg/rpm/rpmbuild/SOURCES/unit.example-python38-config b/pkg/rpm/rpmbuild/SOURCES/unit.example-python38-config
deleted file mode 100644
index c98d1a52..00000000
--- a/pkg/rpm/rpmbuild/SOURCES/unit.example-python38-config
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "applications": {
- "example_python": {
- "type": "python 3.8",
- "processes": 2,
- "path": "/usr/share/doc/unit-python38/examples/python-app",
- "module": "wsgi"
- }
- },
-
- "listeners": {
- "*:8400": {
- "pass": "applications/example_python"
- }
- }
-}
diff --git a/pkg/rpm/unit.module.spec.in b/pkg/rpm/unit.module.spec.in
index 9b0f6221..88a1c33e 100644
--- a/pkg/rpm/unit.module.spec.in
+++ b/pkg/rpm/unit.module.spec.in
@@ -16,10 +16,6 @@ BuildRequires: openssl-devel
%endif
%endif
-%if 0%{?suse_version} >= 1315
-BuildRequires: libopenssl-devel
-%endif
-
%define unit_version %%UNIT_VERSION%%
%define unit_release %%UNIT_RELEASE%%%{?dist}.ngx
@@ -54,10 +50,6 @@ directly in the cloud / container environments and fully control your app
dynamically via an API.
This package contains %%SUMMARY%%.
-%if 0%{?suse_version}
-%debug_package
-%endif
-
%if (0%{?fedora}) || (0%{?rhel} >= 8)
%define _debugsource_template %{nil}
%endif
@@ -106,9 +98,6 @@ DESTDIR=%{buildroot} make %%MODULE_INSTARGS%%
cd %{bdir}
grep -v 'usr/src' debugfiles.list > debugfiles.list.new && mv debugfiles.list.new debugfiles.list
cat /dev/null > debugsources.list
-%if 0%{?suse_version} >= 1500
-cat /dev/null > debugsourcefiles.list
-%endif
%clean
%{__rm} -rf %{buildroot}
diff --git a/pkg/rpm/unit.spec.in b/pkg/rpm/unit.spec.in
index 4cbc7358..01c08bb8 100644
--- a/pkg/rpm/unit.spec.in
+++ b/pkg/rpm/unit.spec.in
@@ -17,10 +17,6 @@ BuildRequires: openssl-devel
%endif
%endif
-%if 0%{?suse_version} >= 1315
-BuildRequires: libopenssl-devel
-%endif
-
%define CC_OPT %{optflags} -fPIC
%define LD_OPT -Wl,-z,relro -Wl,-z,now -pie
@@ -59,10 +55,6 @@ in and out of the application. Take this application server and proxy
directly in the cloud / container environments and fully control your app
dynamically via an API.
-%if 0%{?suse_version}
-%debug_package
-%endif
-
%if (0%{?fedora}) || (0%{?rhel} >= 8)
%define _debugsource_template %{nil}
%endif
@@ -115,7 +107,6 @@ DESTDIR=%{buildroot} make unitd-install libunit-install manpage-install
%{__mkdir} -p %{buildroot}%{_sysconfdir}/logrotate.d
%{__install} -m 644 -p %{SOURCE4} \
%{buildroot}%{_sysconfdir}/logrotate.d/unit
-%{__mkdir} -p %{buildroot}%{_sysconfdir}/unit
%{__mkdir} -p %{buildroot}%{_datadir}/doc/unit/examples
%{__install} -m 644 -p %{SOURCE3} \
%{buildroot}%{_datadir}/doc/unit/examples/example.config
@@ -143,9 +134,6 @@ cd %{bdir} && make tests && ./build/tests
cd %{bdir}
grep -v 'usr/src' debugfiles.list > debugfiles.list.new && mv debugfiles.list.new debugfiles.list
cat /dev/null > debugsources.list
-%if 0%{?suse_version} >= 1500
-cat /dev/null > debugsourcefiles.list
-%endif
%clean
%{__rm} -rf %{buildroot}
@@ -203,7 +191,6 @@ BANNER
%defattr(-,root,root,-)
%attr(0755,root,root) %{_sbindir}/unitd
%attr(0755,root,root) %{_sbindir}/unitd-debug
-%dir %{_sysconfdir}/unit
%{_unitdir}/unit.service
%{_unitdir}/unit-debug.service
%dir %attr(0755,root,root) %ghost %{_localstatedir}/run/unit
diff --git a/src/nxt_application.c b/src/nxt_application.c
index 594574b1..556f1ffb 100644
--- a/src/nxt_application.c
+++ b/src/nxt_application.c
@@ -23,6 +23,13 @@
#endif
+#ifdef WCOREDUMP
+#define NXT_WCOREDUMP(s) WCOREDUMP(s)
+#else
+#define NXT_WCOREDUMP(s) 0
+#endif
+
+
typedef struct {
nxt_app_type_t type;
nxt_str_t version;
@@ -636,6 +643,8 @@ nxt_proto_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
process->data.app = nxt_app_conf;
process->stream = msg->port_msg.stream;
+ init->siblings = &nxt_proto_children;
+
ret = nxt_process_start(task, process);
if (nxt_slow_path(ret == NXT_ERROR)) {
nxt_process_use(task, process, -1);
@@ -711,15 +720,19 @@ nxt_proto_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
nxt_debug(task, "app process %PI (aka %PI) is created", isolated_pid,
pid);
- nxt_runtime_process_remove(task->thread->runtime, process);
-
process->pid = pid;
- nxt_runtime_process_add(task, process);
-
} else {
nxt_debug(task, "app process %PI is created", isolated_pid);
}
+
+ if (!process->registered) {
+ nxt_assert(!nxt_queue_is_empty(&process->ports));
+
+ nxt_runtime_process_add(task, process);
+
+ nxt_port_use(task, nxt_process_port_first(process), -1);
+ }
}
@@ -753,7 +766,11 @@ nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data)
int status;
nxt_err_t err;
nxt_pid_t pid;
+ nxt_port_t *port;
nxt_process_t *process;
+ nxt_runtime_t *rt;
+
+ rt = task->thread->runtime;
nxt_debug(task, "proto sigchld handler signo:%d (%s)",
(int) (uintptr_t) obj, data);
@@ -783,32 +800,58 @@ nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data)
return;
}
+ process = nxt_proto_process_remove(task, pid);
+
if (WTERMSIG(status)) {
-#ifdef WCOREDUMP
- nxt_alert(task, "app process (isolated %PI) exited on signal %d%s",
- pid, WTERMSIG(status),
- WCOREDUMP(status) ? " (core dumped)" : "");
-#else
- nxt_alert(task, "app process (isolated %PI) exited on signal %d",
- pid, WTERMSIG(status));
-#endif
+ if (rt->is_pid_isolated) {
+ nxt_alert(task, "app process %PI (isolated %PI) "
+ "exited on signal %d%s",
+ process != NULL ? process->pid : 0,
+ pid, WTERMSIG(status),
+ NXT_WCOREDUMP(status) ? " (core dumped)" : "");
+
+ } else {
+ nxt_alert(task, "app process %PI exited on signal %d%s",
+ pid, WTERMSIG(status),
+ NXT_WCOREDUMP(status) ? " (core dumped)" : "");
+ }
} else {
- nxt_trace(task, "app process (isolated %PI) exited with code %d",
- pid, WEXITSTATUS(status));
+ if (rt->is_pid_isolated) {
+ nxt_trace(task, "app process %PI (isolated %PI) "
+ "exited with code %d",
+ process != NULL ? process->pid : 0,
+ pid, WEXITSTATUS(status));
+
+ } else {
+ nxt_trace(task, "app process %PI exited with code %d",
+ pid, WEXITSTATUS(status));
+ }
}
- process = nxt_proto_process_remove(task, pid);
if (process == NULL) {
continue;
}
+ if (process->registered) {
+ port = NULL;
+
+ } else {
+ nxt_assert(!nxt_queue_is_empty(&process->ports));
+
+ port = nxt_process_port_first(process);
+ }
+
if (process->state != NXT_PROCESS_STATE_CREATING) {
nxt_port_remove_notify_others(task, process);
}
nxt_process_close_ports(task, process);
+ if (port != NULL) {
+ nxt_port_use(task, port, -1);
+ }
+
if (nxt_proto_exiting && nxt_queue_is_empty(&nxt_proto_children)) {
nxt_process_quit(task, 0);
return;
@@ -1122,7 +1165,7 @@ nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process)
break;
default:
- nxt_debug(task, "process (isolated %PI) failed to add",
+ nxt_alert(task, "process (isolated %PI) failed to add",
process->isolated_pid);
break;
}
diff --git a/src/nxt_clone.c b/src/nxt_clone.c
index aa952a54..a9b39ac1 100644
--- a/src/nxt_clone.c
+++ b/src/nxt_clone.c
@@ -14,9 +14,9 @@ pid_t
nxt_clone(nxt_int_t flags)
{
#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
- return syscall(__NR_clone, NULL, flags);
+ return syscall(SYS_clone, NULL, flags);
#else
- return syscall(__NR_clone, flags, NULL);
+ return syscall(SYS_clone, flags, NULL);
#endif
}
diff --git a/src/nxt_conf.c b/src/nxt_conf.c
index 79e776a0..c6312f3d 100644
--- a/src/nxt_conf.c
+++ b/src/nxt_conf.c
@@ -102,7 +102,7 @@ typedef struct {
static nxt_int_t nxt_conf_path_next_token(nxt_conf_path_parse_t *parse,
nxt_str_t *token);
-static u_char *nxt_conf_json_skip_space(u_char *start, u_char *end);
+static u_char *nxt_conf_json_skip_space(u_char *start, const u_char *end);
static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value,
u_char *start, u_char *end, nxt_conf_json_error_t *error);
static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value,
@@ -266,7 +266,7 @@ nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count)
void
nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name,
- nxt_conf_value_t *value, uint32_t index)
+ const nxt_conf_value_t *value, uint32_t index)
{
nxt_conf_object_member_t *member;
@@ -278,6 +278,20 @@ nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name,
}
+nxt_int_t
+nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, nxt_str_t *name,
+ nxt_conf_value_t *value, uint32_t index)
+{
+ nxt_conf_object_member_t *member;
+
+ member = &object->u.object->members[index];
+
+ member->value = *value;
+
+ return nxt_conf_set_string_dup(&member->name, mp, name);
+}
+
+
void
nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name,
nxt_str_t *value, uint32_t index)
@@ -367,7 +381,7 @@ nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count)
void
nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index,
- nxt_conf_value_t *value)
+ const nxt_conf_value_t *value)
{
array->u.array->elements[index] = *value;
}
@@ -1271,7 +1285,7 @@ nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end,
static u_char *
-nxt_conf_json_skip_space(u_char *start, u_char *end)
+nxt_conf_json_skip_space(u_char *start, const u_char *end)
{
u_char *p, ch;
@@ -2605,7 +2619,7 @@ nxt_conf_json_escape(u_char *dst, u_char *src, size_t size)
void
-nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line,
+nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line,
nxt_uint_t *column)
{
u_char *p;
diff --git a/src/nxt_conf.h b/src/nxt_conf.h
index cfbc5991..c8a276c0 100644
--- a/src/nxt_conf.h
+++ b/src/nxt_conf.h
@@ -72,6 +72,7 @@ typedef struct {
nxt_mp_t *pool;
nxt_str_t error;
void *ctx;
+ nxt_array_t *var_fields; /* of nxt_var_field_t */
nxt_mp_t *conf_pool;
nxt_uint_t ver;
} nxt_conf_validation_t;
@@ -109,7 +110,7 @@ size_t nxt_conf_json_length(nxt_conf_value_t *value,
nxt_conf_json_pretty_t *pretty);
u_char *nxt_conf_json_print(u_char *p, nxt_conf_value_t *value,
nxt_conf_json_pretty_t *pretty);
-void nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line,
+void nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line,
nxt_uint_t *column);
nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt);
@@ -125,7 +126,9 @@ NXT_EXPORT uint8_t nxt_conf_get_boolean(nxt_conf_value_t *value);
NXT_EXPORT nxt_uint_t nxt_conf_object_members_count(nxt_conf_value_t *value);
nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count);
void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name,
- nxt_conf_value_t *value, uint32_t index);
+ const nxt_conf_value_t *value, uint32_t index);
+nxt_int_t nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp,
+ nxt_str_t *name, nxt_conf_value_t *value, uint32_t index);
void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name,
nxt_str_t *value, uint32_t index);
nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp,
@@ -137,7 +140,7 @@ void nxt_conf_set_member_null(nxt_conf_value_t *object, nxt_str_t *name,
nxt_conf_value_t *nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count);
void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index,
- nxt_conf_value_t *value);
+ const nxt_conf_value_t *value);
nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp,
nxt_uint_t index, nxt_str_t *value);
NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count(nxt_conf_value_t *value);
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c
index ee7ebe44..fe6c22e5 100644
--- a/src/nxt_conf_validation.c
+++ b/src/nxt_conf_validation.c
@@ -166,6 +166,8 @@ static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value);
static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
+static nxt_int_t nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt,
+ nxt_conf_value_t *value, void *data);
static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
nxt_str_t *name, nxt_conf_value_t *value);
static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
@@ -200,6 +202,8 @@ static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt,
nxt_str_t *name, nxt_conf_value_t *value);
static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
+static nxt_int_t nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt,
+ nxt_conf_value_t *value, void *data);
static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
@@ -220,6 +224,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[];
+static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[];
#if (NXT_TLS)
static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[];
@@ -238,6 +243,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[];
#if (NXT_HAVE_ISOLATION_ROOTFS)
static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[];
#endif
+static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[];
static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
@@ -267,7 +273,8 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
.u.object = nxt_conf_vldt_upstream,
}, {
.name = nxt_string("access_log"),
- .type = NXT_CONF_VLDT_STRING,
+ .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_OBJECT,
+ .validator = nxt_conf_vldt_access_log,
},
NXT_CONF_VLDT_END
@@ -366,6 +373,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
.type = NXT_CONF_VLDT_STRING,
.validator = nxt_conf_vldt_app_name,
}, {
+ .name = nxt_string("forwarded"),
+ .type = NXT_CONF_VLDT_OBJECT,
+ .validator = nxt_conf_vldt_forwarded,
+ }, {
.name = nxt_string("client_ip"),
.type = NXT_CONF_VLDT_OBJECT,
.validator = nxt_conf_vldt_object,
@@ -385,6 +396,27 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
};
+static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[] = {
+ {
+ .name = nxt_string("client_ip"),
+ .type = NXT_CONF_VLDT_STRING,
+ }, {
+ .name = nxt_string("protocol"),
+ .type = NXT_CONF_VLDT_STRING,
+ }, {
+ .name = nxt_string("source"),
+ .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
+ .validator = nxt_conf_vldt_match_addrs,
+ .flags = NXT_CONF_VLDT_REQUIRED
+ }, {
+ .name = nxt_string("recursive"),
+ .type = NXT_CONF_VLDT_BOOLEAN,
+ },
+
+ NXT_CONF_VLDT_END
+};
+
+
static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[] = {
{
.name = nxt_string("source"),
@@ -1177,11 +1209,29 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = {
};
+static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[] = {
+ {
+ .name = nxt_string("path"),
+ .type = NXT_CONF_VLDT_STRING,
+ }, {
+ .name = nxt_string("format"),
+ .type = NXT_CONF_VLDT_STRING,
+ },
+
+ NXT_CONF_VLDT_END
+};
+
+
nxt_int_t
nxt_conf_validate(nxt_conf_validation_t *vldt)
{
nxt_int_t ret;
+ vldt->var_fields = nxt_array_create(vldt->pool, 4, sizeof(nxt_var_field_t));
+ if (nxt_slow_path(vldt->var_fields == NULL)) {
+ return NXT_ERROR;
+ }
+
ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT);
if (ret != NXT_OK) {
return ret;
@@ -1314,7 +1364,7 @@ nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name,
{
u_char error[NXT_MAX_ERROR_STR];
- if (nxt_var_test(value, error) != NXT_OK) {
+ if (nxt_var_test(value, vldt->var_fields, error) != NXT_OK) {
return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.",
error, name);
}
@@ -1430,9 +1480,14 @@ nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name,
nxt_conf_value_t *value)
{
nxt_int_t ret;
+ nxt_str_t str;
nxt_sockaddr_t *sa;
- sa = nxt_sockaddr_parse(vldt->pool, name);
+ if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) {
+ return NXT_ERROR;
+ }
+
+ sa = nxt_sockaddr_parse(vldt->pool, &str);
if (nxt_slow_path(sa == NULL)) {
return nxt_conf_vldt_error(vldt,
"The listener address \"%V\" is invalid.",
@@ -2124,6 +2179,11 @@ nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
"IPv6 with your configuration.");
+ case NXT_ADDR_PATTERN_NO_UNIX_ERROR:
+ return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
+ "UNIX domain sockets with your "
+ "configuration.");
+
default:
return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown "
"format.");
@@ -2318,6 +2378,28 @@ error:
static nxt_int_t
+nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
+ void *data)
+{
+ nxt_conf_value_t *client_ip, *protocol;
+
+ static nxt_str_t client_ip_str = nxt_string("client_ip");
+ static nxt_str_t protocol_str = nxt_string("protocol");
+
+ client_ip = nxt_conf_get_object_member(value, &client_ip_str, NULL);
+ protocol = nxt_conf_get_object_member(value, &protocol_str, NULL);
+
+ if (client_ip == NULL && protocol == NULL) {
+ return nxt_conf_vldt_error(vldt, "The \"forwarded\" object must have "
+ "either \"client_ip\" or \"protocol\" "
+ "option set.");
+ }
+
+ return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_forwarded_members);
+}
+
+
+static nxt_int_t
nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
nxt_conf_value_t *value)
{
@@ -3030,3 +3112,65 @@ nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
return NXT_OK;
}
+
+
+typedef struct {
+ nxt_str_t path;
+ nxt_str_t format;
+} nxt_conf_vldt_access_log_conf_t;
+
+
+static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = {
+ {
+ nxt_string("path"),
+ NXT_CONF_MAP_STR,
+ offsetof(nxt_conf_vldt_access_log_conf_t, path),
+ },
+
+ {
+ nxt_string("format"),
+ NXT_CONF_MAP_STR,
+ offsetof(nxt_conf_vldt_access_log_conf_t, format),
+ },
+};
+
+
+static nxt_int_t
+nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
+ void *data)
+{
+ nxt_int_t ret;
+ nxt_conf_vldt_access_log_conf_t conf;
+
+ static nxt_str_t format_str = nxt_string("format");
+
+ if (nxt_conf_type(value) == NXT_CONF_STRING) {
+ return NXT_OK;
+ }
+
+ ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_access_log_members);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+
+ nxt_memzero(&conf, sizeof(nxt_conf_vldt_access_log_conf_t));
+
+ ret = nxt_conf_map_object(vldt->pool, value,
+ nxt_conf_vldt_access_log_map,
+ nxt_nitems(nxt_conf_vldt_access_log_map),
+ &conf);
+ if (ret != NXT_OK) {
+ return ret;
+ }
+
+ if (conf.path.length == 0) {
+ return nxt_conf_vldt_error(vldt,
+ "The \"path\" string must not be empty.");
+ }
+
+ if (nxt_is_var(&conf.format)) {
+ return nxt_conf_vldt_var(vldt, &format_str, &conf.format);
+ }
+
+ return NXT_OK;
+}
diff --git a/src/nxt_conn.h b/src/nxt_conn.h
index a443601f..8a703e9a 100644
--- a/src/nxt_conn.h
+++ b/src/nxt_conn.h
@@ -160,6 +160,7 @@ struct nxt_conn_s {
uint8_t block_read; /* 1 bit */
uint8_t block_write; /* 1 bit */
uint8_t delayed; /* 1 bit */
+ uint8_t idle; /* 1 bit */
#define NXT_CONN_SENDFILE_OFF 0
#define NXT_CONN_SENDFILE_ON 1
@@ -294,6 +295,28 @@ NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task,
} while (0)
+#define nxt_conn_idle(engine, c) \
+ do { \
+ nxt_event_engine_t *e = engine; \
+ \
+ nxt_queue_insert_head(&e->idle_connections, &c->link); \
+ \
+ c->idle = 1; \
+ e->idle_conns_cnt++; \
+ } while (0)
+
+
+#define nxt_conn_active(engine, c) \
+ do { \
+ nxt_event_engine_t *e = engine; \
+ \
+ nxt_queue_remove(&c->link); \
+ \
+ c->idle = 0; \
+ e->idle_conns_cnt--; \
+ } while (0)
+
+
extern nxt_conn_io_t nxt_unix_conn_io;
diff --git a/src/nxt_conn_accept.c b/src/nxt_conn_accept.c
index 77c44c58..720c7b64 100644
--- a/src/nxt_conn_accept.c
+++ b/src/nxt_conn_accept.c
@@ -187,7 +187,8 @@ nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data)
void
nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c)
{
- nxt_conn_t *next;
+ nxt_conn_t *next;
+ nxt_event_engine_t *engine;
nxt_sockaddr_text(c->remote);
@@ -195,7 +196,11 @@ nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c)
(size_t) c->remote->address_length,
nxt_sockaddr_address(c->remote));
- nxt_queue_insert_head(&task->thread->engine->idle_connections, &c->link);
+ engine = task->thread->engine;
+
+ engine->accepted_conns_cnt++;
+
+ nxt_conn_idle(engine, c);
c->listen = lev;
lev->count++;
diff --git a/src/nxt_conn_close.c b/src/nxt_conn_close.c
index 7c130309..92bd8d1b 100644
--- a/src/nxt_conn_close.c
+++ b/src/nxt_conn_close.c
@@ -119,6 +119,8 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data)
nxt_socket_close(task, c->socket.fd);
c->socket.fd = -1;
+ engine->closed_conns_cnt++;
+
if (timers_pending == 0) {
nxt_work_queue_add(&engine->fast_work_queue,
c->write_state->ready_handler,
@@ -137,8 +139,9 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data)
static void
nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data)
{
- nxt_conn_t *c;
- nxt_timer_t *timer;
+ nxt_conn_t *c;
+ nxt_timer_t *timer;
+ nxt_event_engine_t *engine;
timer = obj;
@@ -146,13 +149,16 @@ nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "conn close timer handler fd:%d", c->socket.fd);
+ engine = task->thread->engine;
+
if (c->socket.fd != -1) {
nxt_socket_close(task, c->socket.fd);
c->socket.fd = -1;
+
+ engine->closed_conns_cnt++;
}
- nxt_work_queue_add(&task->thread->engine->fast_work_queue,
- c->write_state->ready_handler,
+ nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler,
task, c, c->socket.data);
}
diff --git a/src/nxt_controller.c b/src/nxt_controller.c
index 7510d6f0..09168821 100644
--- a/src/nxt_controller.c
+++ b/src/nxt_controller.c
@@ -9,6 +9,7 @@
#include <nxt_runtime.h>
#include <nxt_main_process.h>
#include <nxt_conf.h>
+#include <nxt_status.h>
#include <nxt_cert.h>
@@ -85,6 +86,12 @@ static void nxt_controller_process_request(nxt_task_t *task,
static void nxt_controller_process_config(nxt_task_t *task,
nxt_controller_request_t *req, nxt_str_t *path);
static nxt_bool_t nxt_controller_check_postpone_request(nxt_task_t *task);
+static void nxt_controller_process_status(nxt_task_t *task,
+ nxt_controller_request_t *req);
+static void nxt_controller_status_handler(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+static void nxt_controller_status_response(nxt_task_t *task,
+ nxt_controller_request_t *req, nxt_str_t *path);
#if (NXT_TLS)
static void nxt_controller_process_cert(nxt_task_t *task,
nxt_controller_request_t *req, nxt_str_t *path);
@@ -120,6 +127,7 @@ static nxt_uint_t nxt_controller_router_ready;
static nxt_controller_conf_t nxt_controller_conf;
static nxt_queue_t nxt_controller_waiting_requests;
static nxt_bool_t nxt_controller_waiting_init_conf;
+static nxt_conf_value_t *nxt_controller_status;
static const nxt_event_conn_state_t nxt_controller_conn_read_state;
@@ -725,7 +733,7 @@ static const nxt_event_conn_state_t nxt_controller_conn_read_state
.timer_handler = nxt_controller_conn_read_timeout,
.timer_value = nxt_controller_conn_timeout_value,
- .timer_data = 60 * 1000,
+ .timer_data = 300 * 1000,
};
@@ -1035,6 +1043,7 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
static nxt_str_t certificates = nxt_string("certificates");
#endif
static nxt_str_t config = nxt_string("config");
+ static nxt_str_t status = nxt_string("status");
c = req->conn;
path = req->parser.path;
@@ -1058,6 +1067,32 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
return;
}
+ nxt_memzero(&resp, sizeof(nxt_controller_response_t));
+
+ if (nxt_str_start(&path, "/status", 7)
+ && (path.length == 7 || path.start[7] == '/'))
+ {
+ if (!nxt_str_eq(&req->parser.method, "GET", 3)) {
+ goto invalid_method;
+ }
+
+ if (nxt_controller_status == NULL) {
+ nxt_controller_process_status(task, req);
+ return;
+ }
+
+ if (path.length == 7) {
+ path.length = 1;
+
+ } else {
+ path.length -= 7;
+ path.start += 7;
+ }
+
+ nxt_controller_status_response(task, req, &path);
+ return;
+ }
+
#if (NXT_TLS)
if (nxt_str_start(&path, "/certificates", 13)
@@ -1085,15 +1120,18 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
return;
}
- nxt_memzero(&resp, sizeof(nxt_controller_response_t));
-
if (path.length == 1 && path.start[0] == '/') {
if (!nxt_str_eq(&req->parser.method, "GET", 3)) {
goto invalid_method;
}
- count = 1;
+ if (nxt_controller_status == NULL) {
+ nxt_controller_process_status(task, req);
+ return;
+ }
+
+ count = 2;
#if (NXT_TLS)
count++;
#endif
@@ -1114,7 +1152,8 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req)
nxt_conf_set_member(value, &certificates, certs, i++);
#endif
- nxt_conf_set_member(value, &config, nxt_controller_conf.root, i);
+ nxt_conf_set_member(value, &config, nxt_controller_conf.root, i++);
+ nxt_conf_set_member(value, &status, nxt_controller_status, i);
resp.status = 200;
resp.conf = value;
@@ -1451,6 +1490,128 @@ nxt_controller_check_postpone_request(nxt_task_t *task)
}
+static void
+nxt_controller_process_status(nxt_task_t *task, nxt_controller_request_t *req)
+{
+ uint32_t stream;
+ nxt_int_t rc;
+ nxt_port_t *router_port, *controller_port;
+ nxt_runtime_t *rt;
+ nxt_controller_response_t resp;
+
+ if (nxt_controller_check_postpone_request(task)) {
+ nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link);
+ return;
+ }
+
+ rt = task->thread->runtime;
+
+ router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
+
+ nxt_assert(router_port != NULL);
+ nxt_assert(nxt_controller_router_ready);
+
+ controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER];
+
+ stream = nxt_port_rpc_register_handler(task, controller_port,
+ nxt_controller_status_handler,
+ nxt_controller_status_handler,
+ router_port->pid, req);
+ if (nxt_slow_path(stream == 0)) {
+ goto fail;
+ }
+
+ rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_STATUS,
+ -1, stream, controller_port->id, NULL);
+
+ if (nxt_slow_path(rc != NXT_OK)) {
+ nxt_port_rpc_cancel(task, controller_port, stream);
+
+ goto fail;
+ }
+
+ nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link);
+ return;
+
+fail:
+
+ nxt_memzero(&resp, sizeof(nxt_controller_response_t));
+
+ resp.status = 500;
+ resp.title = (u_char *) "Failed to get status.";
+ resp.offset = -1;
+
+ nxt_controller_response(task, req, &resp);
+ return;
+}
+
+
+static void
+nxt_controller_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_conf_value_t *status;
+ nxt_controller_request_t *req;
+ nxt_controller_response_t resp;
+
+ nxt_debug(task, "controller status handler");
+
+ req = data;
+
+ if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) {
+ status = nxt_status_get((nxt_status_report_t *) msg->buf->mem.pos,
+ req->conn->mem_pool);
+ } else {
+ status = NULL;
+ }
+
+ if (status == NULL) {
+ nxt_queue_remove(&req->link);
+
+ nxt_memzero(&resp, sizeof(nxt_controller_response_t));
+
+ resp.status = 500;
+ resp.title = (u_char *) "Failed to get status.";
+ resp.offset = -1;
+
+ nxt_controller_response(task, req, &resp);
+ }
+
+ nxt_controller_status = status;
+
+ nxt_controller_flush_requests(task);
+
+ nxt_controller_status = NULL;
+}
+
+
+static void
+nxt_controller_status_response(nxt_task_t *task, nxt_controller_request_t *req,
+ nxt_str_t *path)
+{
+ nxt_conf_value_t *status;
+ nxt_controller_response_t resp;
+
+ status = nxt_conf_get_path(nxt_controller_status, path);
+
+ nxt_memzero(&resp, sizeof(nxt_controller_response_t));
+
+ if (status == NULL) {
+ resp.status = 404;
+ resp.title = (u_char *) "Invalid path.";
+ resp.offset = -1;
+
+ nxt_controller_response(task, req, &resp);
+ return;
+ }
+
+ resp.status = 200;
+ resp.conf = status;
+
+ nxt_controller_response(task, req, &resp);
+}
+
+
#if (NXT_TLS)
static void
diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h
index 91cfc0aa..291ea749 100644
--- a/src/nxt_event_engine.h
+++ b/src/nxt_event_engine.h
@@ -483,6 +483,11 @@ struct nxt_event_engine_s {
nxt_queue_t idle_connections;
nxt_array_t *mem_cache;
+ nxt_atomic_uint_t accepted_conns_cnt;
+ nxt_atomic_uint_t idle_conns_cnt;
+ nxt_atomic_uint_t closed_conns_cnt;
+ nxt_atomic_uint_t requests_cnt;
+
nxt_queue_link_t link;
// STUB: router link
nxt_queue_link_t link0;
diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c
index d3340774..852b4866 100644
--- a/src/nxt_h1proto.c
+++ b/src/nxt_h1proto.c
@@ -478,7 +478,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "h1p conn request init");
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
r = nxt_http_request_create(task);
@@ -490,7 +490,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data)
r->remote = c->remote;
#if (NXT_TLS)
- r->tls = c->u.tls;
+ r->tls = (c->u.tls != NULL);
#endif
r->task = c->task;
@@ -1739,7 +1739,7 @@ nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "h1p conn close");
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
nxt_h1p_shutdown(task, c);
}
@@ -1754,7 +1754,7 @@ nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "h1p conn error");
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
nxt_h1p_shutdown(task, c);
}
@@ -1801,7 +1801,8 @@ nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c)
c->sent = 0;
engine = task->thread->engine;
- nxt_queue_insert_head(&engine->idle_connections, &c->link);
+
+ nxt_conn_idle(engine, c);
if (in == NULL) {
c->read_state = &nxt_h1p_keepalive_state;
@@ -1855,7 +1856,7 @@ nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data)
nxt_debug(task, "h1p idle close");
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
nxt_h1p_idle_response(task, c);
}
@@ -1874,7 +1875,7 @@ nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data)
c = nxt_read_timer_conn(timer);
c->block_read = 1;
- nxt_queue_remove(&c->link);
+ nxt_conn_active(task->thread->engine, c);
nxt_h1p_idle_response(task, c);
}
diff --git a/src/nxt_http.h b/src/nxt_http.h
index d299fdd4..c2e85840 100644
--- a/src/nxt_http.h
+++ b/src/nxt_http.h
@@ -162,7 +162,6 @@ struct nxt_http_request_s {
nxt_sockaddr_t *remote;
nxt_sockaddr_t *local;
- void *tls;
nxt_task_t task;
nxt_timer_t timer;
@@ -190,6 +189,7 @@ struct nxt_http_request_s {
uint8_t pass_count; /* 8 bits */
uint8_t app_target;
nxt_http_protocol_t protocol:8; /* 2 bits */
+ uint8_t tls; /* 1 bit */
uint8_t logged; /* 1 bit */
uint8_t header_sent; /* 1 bit */
uint8_t inconsistent; /* 1 bit */
@@ -207,6 +207,13 @@ typedef struct {
} nxt_http_name_value_t;
+typedef enum {
+ NXT_HTTP_URI_ENCODING_NONE = 0,
+ NXT_HTTP_URI_ENCODING,
+ NXT_HTTP_URI_ENCODING_PLUS
+} nxt_http_uri_encoding_t;
+
+
typedef struct nxt_http_route_s nxt_http_route_t;
typedef struct nxt_http_route_rule_s nxt_http_route_rule_t;
typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t;
@@ -266,10 +273,16 @@ typedef struct {
} nxt_http_proto_table_t;
-struct nxt_http_client_ip_s {
- nxt_http_route_addr_rule_t *source;
+typedef struct {
nxt_str_t *header;
uint32_t header_hash;
+} nxt_http_forward_header_t;
+
+
+struct nxt_http_forward_s {
+ nxt_http_forward_header_t client_ip;
+ nxt_http_forward_header_t protocol;
+ nxt_http_route_addr_rule_t *source;
uint8_t recursive; /* 1 bit */
};
@@ -324,6 +337,12 @@ nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field,
nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r);
nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r);
+int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name,
+ nxt_bool_t case_sensitive, uint8_t encoding);
+int64_t nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name);
+int64_t nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name);
+int64_t nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name);
+
nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf);
nxt_http_action_t *nxt_http_action_create(nxt_task_t *task,
@@ -353,15 +372,16 @@ nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf,
nxt_upstream_t ***upstream_joint);
-nxt_int_t nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action,
- nxt_http_action_conf_t *acf);
+nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf,
+ nxt_http_action_t *action, nxt_http_action_conf_t *acf);
nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_http_action_t *action, nxt_http_action_conf_t *acf);
nxt_int_t nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash);
nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
- nxt_str_t *exten, nxt_str_t *type);
-nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten);
+ const nxt_str_t *exten, nxt_str_t *type);
+nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash,
+ const nxt_str_t *exten);
nxt_http_action_t *nxt_http_application_handler(nxt_task_t *task,
nxt_http_request_t *r, nxt_http_action_t *action);
diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c
index 1ab6cc90..1bb4291f 100644
--- a/src/nxt_http_parse.c
+++ b/src/nxt_http_parse.c
@@ -8,16 +8,16 @@
static nxt_int_t nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
static nxt_int_t nxt_http_parse_field_name(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
static nxt_int_t nxt_http_parse_field_value(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
-static u_char *nxt_http_lookup_field_end(u_char *p, u_char *end);
+ u_char **pos, const u_char *end);
+static u_char *nxt_http_lookup_field_end(u_char *p, const u_char *end);
static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
static nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp);
@@ -62,7 +62,7 @@ static const uint8_t nxt_http_target_chars[256] nxt_aligned(64) = {
nxt_inline nxt_http_target_traps_e
-nxt_http_parse_target(u_char **pos, u_char *end)
+nxt_http_parse_target(u_char **pos, const u_char *end)
{
u_char *p;
nxt_uint_t trap;
@@ -158,7 +158,7 @@ nxt_http_parse_fields(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b)
static nxt_int_t
nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p, ch, *after_slash, *args;
nxt_int_t rc;
@@ -479,7 +479,7 @@ space_after_target:
static nxt_int_t
nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p, ch;
@@ -517,7 +517,7 @@ nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos,
static nxt_int_t
nxt_http_parse_field_name(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p, c;
size_t len;
@@ -624,7 +624,7 @@ name_end:
static nxt_int_t
nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p, *start, ch;
size_t len;
@@ -704,7 +704,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
static u_char *
-nxt_http_lookup_field_end(u_char *p, u_char *end)
+nxt_http_lookup_field_end(u_char *p, const u_char *end)
{
while (nxt_fast_path(end - p >= 16)) {
@@ -771,7 +771,7 @@ nxt_http_lookup_field_end(u_char *p, u_char *end)
static nxt_int_t
nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos,
- u_char *end)
+ const u_char *end)
{
u_char *p;
nxt_http_field_t *field;
diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h
index 3cd9bd15..2b714464 100644
--- a/src/nxt_http_parse.h
+++ b/src/nxt_http_parse.h
@@ -35,7 +35,7 @@ typedef union {
struct nxt_http_request_parse_s {
nxt_int_t (*handler)(nxt_http_request_parse_t *rp,
- u_char **pos, u_char *end);
+ u_char **pos, const u_char *end);
nxt_str_t method;
diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c
index 04a6f7f3..943ad82d 100644
--- a/src/nxt_http_request.c
+++ b/src/nxt_http_request.c
@@ -10,10 +10,14 @@
static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp);
static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data);
-static nxt_int_t nxt_http_request_client_ip(nxt_task_t *task,
- nxt_http_request_t *r);
+static nxt_int_t nxt_http_request_forward(nxt_task_t *task,
+ nxt_http_request_t *r, nxt_http_forward_t *forward);
+static void nxt_http_request_forward_client_ip(nxt_http_request_t *r,
+ nxt_http_forward_t *forward, nxt_array_t *fields);
static nxt_sockaddr_t *nxt_http_request_client_ip_sockaddr(
nxt_http_request_t *r, u_char *start, size_t len);
+static void nxt_http_request_forward_protocol(nxt_http_request_t *r,
+ nxt_http_field_t *field);
static void nxt_http_request_ready(nxt_task_t *task, void *obj, void *data);
static void nxt_http_request_proto_info(nxt_task_t *task,
nxt_http_request_t *r);
@@ -26,11 +30,11 @@ static u_char *nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now,
static nxt_http_name_value_t *nxt_http_argument(nxt_array_t *array,
u_char *name, size_t name_length, uint32_t hash, u_char *start,
- u_char *end);
+ const u_char *end);
static nxt_int_t nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start,
- u_char *end);
+ const u_char *end);
static nxt_http_name_value_t *nxt_http_cookie(nxt_array_t *array, u_char *name,
- size_t name_length, u_char *start, u_char *end);
+ size_t name_length, u_char *start, const u_char *end);
#define NXT_HTTP_COOKIE_HASH \
@@ -274,6 +278,8 @@ nxt_http_request_create(nxt_task_t *task)
r->resp.content_length_n = -1;
r->state = &nxt_http_request_init_state;
+ task->thread->engine->requests_cnt++;
+
return r;
fail:
@@ -296,74 +302,125 @@ static void
nxt_http_request_start(nxt_task_t *task, void *obj, void *data)
{
nxt_int_t ret;
+ nxt_socket_conf_t *skcf;
nxt_http_request_t *r;
r = obj;
r->state = &nxt_http_request_body_state;
- ret = nxt_http_request_client_ip(task, r);
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
+ skcf = r->conf->socket_conf;
+
+ if (skcf->forwarded != NULL) {
+ ret = nxt_http_request_forward(task, r, skcf->forwarded);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
+ }
+
+ if (skcf->client_ip != NULL) {
+ ret = nxt_http_request_forward(task, r, skcf->client_ip);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
}
nxt_http_request_read_body(task, r);
+
+ return;
+
+fail:
+ nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
}
static nxt_int_t
-nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r)
+nxt_http_request_forward(nxt_task_t *task, nxt_http_request_t *r,
+ nxt_http_forward_t *forward)
{
- u_char *start, *p;
- nxt_int_t ret, i, len;
- nxt_str_t *header;
- nxt_array_t *fields_arr; /* of nxt_http_field_t * */
- nxt_sockaddr_t *sa, *prev_sa;
- nxt_http_field_t *f, **fields;
- nxt_http_client_ip_t *client_ip;
+ nxt_int_t ret;
+ nxt_array_t *client_ip_fields;
+ nxt_http_field_t *f, **fields, *protocol_field;
+ nxt_http_forward_header_t *client_ip, *protocol;
- client_ip = r->conf->socket_conf->client_ip;
-
- if (client_ip == NULL) {
- return NXT_OK;
- }
-
- ret = nxt_http_route_addr_rule(r, client_ip->source, r->remote);
+ ret = nxt_http_route_addr_rule(r, forward->source, r->remote);
if (ret <= 0) {
return NXT_OK;
}
- header = client_ip->header;
+ client_ip = &forward->client_ip;
+ protocol = &forward->protocol;
+
+ if (client_ip->header != NULL) {
+ client_ip_fields = nxt_array_create(r->mem_pool, 1,
+ sizeof(nxt_http_field_t *));
+ if (nxt_slow_path(client_ip_fields == NULL)) {
+ return NXT_ERROR;
+ }
- fields_arr = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_field_t *));
- if (nxt_slow_path(fields_arr == NULL)) {
- return NXT_ERROR;
+ } else {
+ client_ip_fields = NULL;
}
+ protocol_field = NULL;
+
nxt_list_each(f, r->fields) {
- if (f->hash == client_ip->header_hash
- && f->name_length == client_ip->header->length
+ if (client_ip_fields != NULL
+ && f->hash == client_ip->header_hash
&& f->value_length > 0
- && nxt_memcasecmp(f->name, header->start, header->length) == 0)
+ && f->name_length == client_ip->header->length
+ && nxt_memcasecmp(f->name, client_ip->header->start,
+ client_ip->header->length) == 0)
{
- fields = nxt_array_add(fields_arr);
+ fields = nxt_array_add(client_ip_fields);
if (nxt_slow_path(fields == NULL)) {
return NXT_ERROR;
}
*fields = f;
}
+
+ if (protocol->header != NULL
+ && protocol_field == NULL
+ && f->hash == protocol->header_hash
+ && f->value_length > 0
+ && f->name_length == protocol->header->length
+ && nxt_memcasecmp(f->name, protocol->header->start,
+ protocol->header->length) == 0)
+ {
+ protocol_field = f;
+ }
} nxt_list_loop;
+ if (client_ip_fields != NULL) {
+ nxt_http_request_forward_client_ip(r, forward, client_ip_fields);
+ }
+
+ if (protocol_field != NULL) {
+ nxt_http_request_forward_protocol(r, protocol_field);
+ }
+
+ return NXT_OK;
+}
+
+
+static void
+nxt_http_request_forward_client_ip(nxt_http_request_t *r,
+ nxt_http_forward_t *forward, nxt_array_t *fields)
+{
+ u_char *start, *p;
+ nxt_int_t ret, i, len;
+ nxt_sockaddr_t *sa, *prev_sa;
+ nxt_http_field_t **f;
+
prev_sa = r->remote;
- fields = (nxt_http_field_t **) fields_arr->elts;
+ f = (nxt_http_field_t **) fields->elts;
- i = fields_arr->nelts;
+ i = fields->nelts;
while (i-- > 0) {
- f = fields[i];
- start = f->value;
- len = f->value_length;
+ start = f[i]->value;
+ len = f[i]->value_length;
do {
for (p = start + len - 1; p > start; p--, len--) {
@@ -385,20 +442,18 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r)
r->remote = prev_sa;
}
- return NXT_OK;
+ return;
}
- if (!client_ip->recursive) {
+ if (!forward->recursive) {
r->remote = sa;
-
- return NXT_OK;
+ return;
}
- ret = nxt_http_route_addr_rule(r, client_ip->source, sa);
+ ret = nxt_http_route_addr_rule(r, forward->source, sa);
if (ret <= 0 || (i == 0 && p == start)) {
r->remote = sa;
-
- return NXT_OK;
+ return;
}
prev_sa = sa;
@@ -406,8 +461,6 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r)
} while (len > 0);
}
-
- return NXT_OK;
}
@@ -451,6 +504,28 @@ nxt_http_request_client_ip_sockaddr(nxt_http_request_t *r, u_char *start,
}
+static void
+nxt_http_request_forward_protocol(nxt_http_request_t *r,
+ nxt_http_field_t *field)
+{
+ if (field->value_length == 4) {
+ if (nxt_memcasecmp(field->value, "http", 4) == 0) {
+ r->tls = 0;
+ }
+
+ } else if (field->value_length == 5) {
+ if (nxt_memcasecmp(field->value, "https", 5) == 0) {
+ r->tls = 1;
+ }
+
+ } else if (field->value_length == 2) {
+ if (nxt_memcasecmp(field->value, "on", 2) == 0) {
+ r->tls = 1;
+ }
+ }
+}
+
+
static const nxt_http_request_state_t nxt_http_request_body_state
nxt_aligned(64) =
{
@@ -718,6 +793,7 @@ nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data)
void
nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data)
{
+ nxt_var_t *log_format;
nxt_http_proto_t proto;
nxt_http_request_t *r;
nxt_http_protocol_t protocol;
@@ -727,20 +803,22 @@ nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data)
r = obj;
proto.any = data;
- nxt_debug(task, "http request close handler");
-
conf = r->conf;
if (!r->logged) {
r->logged = 1;
access_log = conf->socket_conf->router_conf->access_log;
+ log_format = conf->socket_conf->router_conf->log_format;
if (access_log != NULL) {
- access_log->handler(task, r, access_log);
+ access_log->handler(task, r, access_log, log_format);
+ return;
}
}
+ nxt_debug(task, "http request close handler");
+
r->proto.any = NULL;
if (r->body != NULL && nxt_buf_is_file(r->body)
@@ -876,7 +954,7 @@ nxt_http_arguments_parse(nxt_http_request_t *r)
static nxt_http_name_value_t *
nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length,
- uint32_t hash, u_char *start, u_char *end)
+ uint32_t hash, u_char *start, const u_char *end)
{
size_t length;
nxt_http_name_value_t *nv;
@@ -945,7 +1023,7 @@ nxt_http_cookies_parse(nxt_http_request_t *r)
static nxt_int_t
-nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end)
+nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, const u_char *end)
{
size_t name_length;
u_char c, *p, *name;
@@ -994,7 +1072,7 @@ nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end)
static nxt_http_name_value_t *
nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length,
- u_char *start, u_char *end)
+ u_char *start, const u_char *end)
{
u_char c, *p;
uint32_t hash;
@@ -1024,3 +1102,140 @@ nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length,
return nv;
}
+
+
+int64_t
+nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, nxt_bool_t case_sensitive,
+ uint8_t encoding)
+{
+ u_char c, *p, *src, *start, *end, plus;
+ uint8_t d0, d1;
+ uint32_t hash;
+ nxt_str_t str;
+ nxt_uint_t i;
+
+ str.length = name->length;
+
+ str.start = nxt_mp_nget(mp, str.length);
+ if (nxt_slow_path(str.start == NULL)) {
+ return -1;
+ }
+
+ p = str.start;
+
+ hash = NXT_HTTP_FIELD_HASH_INIT;
+
+ if (encoding == NXT_HTTP_URI_ENCODING_NONE) {
+ for (i = 0; i < name->length; i++) {
+ c = name->start[i];
+ *p++ = c;
+
+ c = case_sensitive ? c : nxt_lowcase(c);
+ hash = nxt_http_field_hash_char(hash, c);
+ }
+
+ goto end;
+ }
+
+ plus = (encoding == NXT_HTTP_URI_ENCODING_PLUS) ? ' ' : '+';
+
+ start = name->start;
+ end = start + name->length;
+
+ for (src = start; src < end; src++) {
+ c = *src;
+
+ switch (c) {
+ case '%':
+ if (nxt_slow_path(end - src <= 2)) {
+ return -1;
+ }
+
+ d0 = nxt_hex2int[src[1]];
+ d1 = nxt_hex2int[src[2]];
+ src += 2;
+
+ if (nxt_slow_path((d0 | d1) >= 16)) {
+ return -1;
+ }
+
+ c = (d0 << 4) + d1;
+ *p++ = c;
+ break;
+
+ case '+':
+ c = plus;
+ *p++ = c;
+ break;
+
+ default:
+ *p++ = c;
+ break;
+ }
+
+ c = case_sensitive ? c : nxt_lowcase(c);
+ hash = nxt_http_field_hash_char(hash, c);
+ }
+
+ str.length = p - str.start;
+
+end:
+
+ *name = str;
+
+ return nxt_http_field_hash_end(hash) & 0xFFFF;
+}
+
+
+int64_t
+nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name)
+{
+ return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_PLUS);
+}
+
+
+int64_t
+nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name)
+{
+ u_char c, *p;
+ uint32_t i, hash;
+ nxt_str_t str;
+
+ str.length = name->length;
+
+ str.start = nxt_mp_nget(mp, str.length);
+ if (nxt_slow_path(str.start == NULL)) {
+ return -1;
+ }
+
+ p = str.start;
+ hash = NXT_HTTP_FIELD_HASH_INIT;
+
+ for (i = 0; i < name->length; i++) {
+ c = name->start[i];
+
+ if (c >= 'A' && c <= 'Z') {
+ *p = c | 0x20;
+
+ } else if (c == '_') {
+ *p = '-';
+
+ } else {
+ *p = c;
+ }
+
+ hash = nxt_http_field_hash_char(hash, *p);
+ p++;
+ }
+
+ *name = str;
+
+ return nxt_http_field_hash_end(hash) & 0xFFFF;
+}
+
+
+int64_t
+nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name)
+{
+ return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_NONE);
+}
diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c
index 82c91568..9f3c4fc5 100644
--- a/src/nxt_http_return.c
+++ b/src/nxt_http_return.c
@@ -32,12 +32,15 @@ static const nxt_http_request_state_t nxt_http_return_send_state;
nxt_int_t
-nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action,
+nxt_http_return_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action,
nxt_http_action_conf_t *acf)
{
+ nxt_mp_t *mp;
nxt_str_t str;
nxt_http_return_conf_t *conf;
+ mp = rtcf->mem_pool;
+
conf = nxt_mp_zget(mp, sizeof(nxt_http_return_conf_t));
if (nxt_slow_path(conf == NULL)) {
return NXT_ERROR;
@@ -54,7 +57,7 @@ nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action,
nxt_conf_get_string(acf->location, &str);
- conf->location = nxt_var_compile(&str, mp, 0);
+ conf->location = nxt_var_compile(&str, mp, rtcf->var_fields, 0);
if (nxt_slow_path(conf->location == NULL)) {
return NXT_ERROR;
}
diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c
index 9200dc52..cdc9077f 100644
--- a/src/nxt_http_route.c
+++ b/src/nxt_http_route.c
@@ -40,13 +40,6 @@ typedef enum {
} nxt_http_route_pattern_case_t;
-typedef enum {
- NXT_HTTP_ROUTE_ENCODING_NONE = 0,
- NXT_HTTP_ROUTE_ENCODING_URI,
- NXT_HTTP_ROUTE_ENCODING_URI_PLUS
-} nxt_http_route_encoding_t;
-
-
typedef struct {
nxt_conf_value_t *host;
nxt_conf_value_t *uri;
@@ -169,29 +162,29 @@ static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv);
static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task,
nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task,
nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task,
nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task,
nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
nxt_http_route_pattern_case_t pattern_case,
- nxt_http_route_encoding_t encoding);
+ nxt_http_uri_encoding_t encoding);
static int nxt_http_pattern_compare(const void *one, const void *two);
static int nxt_http_addr_pattern_compare(const void *one, const void *two);
static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
nxt_http_route_pattern_case_t pattern_case,
- nxt_http_route_encoding_t encoding);
+ nxt_http_uri_encoding_t encoding);
static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str,
- nxt_http_route_encoding_t encoding);
+ nxt_http_uri_encoding_t encoding);
static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices,
nxt_str_t *test,
nxt_http_route_pattern_type_t type,
- nxt_http_route_encoding_t encoding,
+ nxt_http_uri_encoding_t encoding,
nxt_http_route_pattern_case_t pattern_case);
static nxt_int_t nxt_http_route_resolve(nxt_task_t *task,
@@ -457,7 +450,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.scheme != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1,
NXT_HTTP_ROUTE_PATTERN_NOCASE,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (rule == NULL) {
return NULL;
}
@@ -470,7 +463,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.host != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1,
NXT_HTTP_ROUTE_PATTERN_LOWCASE,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (rule == NULL) {
return NULL;
}
@@ -484,7 +477,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.uri != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1,
NXT_HTTP_ROUTE_PATTERN_NOCASE,
- NXT_HTTP_ROUTE_ENCODING_URI);
+ NXT_HTTP_URI_ENCODING);
if (rule == NULL) {
return NULL;
}
@@ -498,7 +491,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.method != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1,
NXT_HTTP_ROUTE_PATTERN_UPCASE,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (rule == NULL) {
return NULL;
}
@@ -512,7 +505,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.headers != NULL) {
table = nxt_http_route_table_create(task, mp, mtcf.headers,
NXT_HTTP_ROUTE_HEADER, 0,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (table == NULL) {
return NULL;
}
@@ -524,7 +517,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.arguments != NULL) {
table = nxt_http_route_table_create(task, mp, mtcf.arguments,
NXT_HTTP_ROUTE_ARGUMENT, 1,
- NXT_HTTP_ROUTE_ENCODING_URI_PLUS);
+ NXT_HTTP_URI_ENCODING_PLUS);
if (table == NULL) {
return NULL;
}
@@ -536,7 +529,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.cookies != NULL) {
table = nxt_http_route_table_create(task, mp, mtcf.cookies,
NXT_HTTP_ROUTE_COOKIE, 1,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
if (table == NULL) {
return NULL;
}
@@ -548,7 +541,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
if (mtcf.query != NULL) {
rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1,
NXT_HTTP_ROUTE_PATTERN_NOCASE,
- NXT_HTTP_ROUTE_ENCODING_URI_PLUS);
+ NXT_HTTP_URI_ENCODING_PLUS);
if (rule == NULL) {
return NULL;
}
@@ -650,6 +643,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_mp_t *mp;
nxt_int_t ret;
nxt_str_t pass;
+ nxt_router_conf_t *rtcf;
nxt_http_action_conf_t acf;
nxt_memzero(&acf, sizeof(acf));
@@ -662,10 +656,11 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_memzero(action, sizeof(nxt_http_action_t));
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
if (acf.ret != NULL) {
- return nxt_http_return_init(mp, action, &acf);
+ return nxt_http_return_init(rtcf, action, &acf);
}
if (acf.share != NULL) {
@@ -678,7 +673,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_conf_get_string(acf.pass, &pass);
- action->u.var = nxt_var_compile(&pass, mp, 0);
+ action->u.var = nxt_var_compile(&pass, mp, rtcf->var_fields, 0);
if (nxt_slow_path(action->u.var == NULL)) {
return NXT_ERROR;
}
@@ -690,7 +685,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
static nxt_http_route_table_t *
nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding)
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding)
{
size_t size;
uint32_t i, n;
@@ -729,7 +724,7 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
static nxt_http_route_ruleset_t *
nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
- nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding)
+ nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding)
{
size_t size;
uint32_t i, n, next;
@@ -777,12 +772,9 @@ nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
static nxt_http_route_rule_t *
nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive,
- nxt_http_route_encoding_t encoding)
+ nxt_http_uri_encoding_t encoding)
{
- u_char c, *p, *src, *start, *end, plus;
- uint8_t d0, d1;
- uint32_t hash;
- nxt_uint_t i;
+ int64_t hash;
nxt_http_route_rule_t *rule;
rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive,
@@ -792,73 +784,14 @@ nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
return NULL;
}
- rule->u.name.length = name->length;
-
- p = nxt_mp_nget(mp, name->length);
- if (nxt_slow_path(p == NULL)) {
+ hash = nxt_http_field_hash(mp, name, case_sensitive, encoding);
+ if (nxt_slow_path(hash == -1)) {
return NULL;
}
- hash = NXT_HTTP_FIELD_HASH_INIT;
- rule->u.name.start = p;
-
- if (encoding == NXT_HTTP_ROUTE_ENCODING_NONE) {
- for (i = 0; i < name->length; i++) {
- c = name->start[i];
- *p++ = c;
-
- c = case_sensitive ? c : nxt_lowcase(c);
- hash = nxt_http_field_hash_char(hash, c);
- }
-
- goto end;
- }
-
- plus = (encoding == NXT_HTTP_ROUTE_ENCODING_URI_PLUS) ? ' ' : '+';
-
- start = name->start;
- end = start + name->length;
-
- for (src = start; src < end; src++) {
- c = *src;
-
- switch (c) {
- case '%':
- if (nxt_slow_path(end - src <= 2)) {
- return NULL;
- }
-
- d0 = nxt_hex2int[src[1]];
- d1 = nxt_hex2int[src[2]];
- src += 2;
-
- if (nxt_slow_path((d0 | d1) >= 16)) {
- return NULL;
- }
-
- c = (d0 << 4) + d1;
- *p++ = c;
- break;
-
- case '+':
- c = plus;
- *p++ = c;
- break;
-
- default:
- *p++ = c;
- break;
- }
-
- c = case_sensitive ? c : nxt_lowcase(c);
- hash = nxt_http_field_hash_char(hash, c);
- }
-
- rule->u.name.length = p - rule->u.name.start;
-
-end:
-
- rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF;
+ rule->u.name.hash = hash;
+ rule->u.name.start = name->start;
+ rule->u.name.length = name->length;
return rule;
}
@@ -868,7 +801,7 @@ static nxt_http_route_rule_t *
nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
nxt_http_route_pattern_case_t pattern_case,
- nxt_http_route_encoding_t encoding)
+ nxt_http_uri_encoding_t encoding)
{
size_t size;
uint32_t i, n;
@@ -953,7 +886,7 @@ nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp,
{
return nxt_http_route_rule_create(task, mp, types, 0,
NXT_HTTP_ROUTE_PATTERN_LOWCASE,
- NXT_HTTP_ROUTE_ENCODING_NONE);
+ NXT_HTTP_URI_ENCODING_NONE);
}
@@ -992,7 +925,7 @@ static nxt_int_t
nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
nxt_http_route_pattern_case_t pattern_case,
- nxt_http_route_encoding_t encoding)
+ nxt_http_uri_encoding_t encoding)
{
u_char c, *p, *end;
nxt_str_t test, tmp;
@@ -1188,15 +1121,15 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
static nxt_int_t
-nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding)
+nxt_http_route_decode_str(nxt_str_t *str, nxt_http_uri_encoding_t encoding)
{
u_char *start, *end;
switch (encoding) {
- case NXT_HTTP_ROUTE_ENCODING_NONE:
+ case NXT_HTTP_URI_ENCODING_NONE:
break;
- case NXT_HTTP_ROUTE_ENCODING_URI:
+ case NXT_HTTP_URI_ENCODING:
start = str->start;
end = nxt_decode_uri(start, start, str->length);
@@ -1207,7 +1140,7 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding)
str->length = end - start;
break;
- case NXT_HTTP_ROUTE_ENCODING_URI_PLUS:
+ case NXT_HTTP_URI_ENCODING_PLUS:
start = str->start;
end = nxt_decode_uri_plus(start, start, str->length);
@@ -1228,9 +1161,8 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding)
static nxt_int_t
nxt_http_route_pattern_slice(nxt_array_t *slices,
- nxt_str_t *test,
- nxt_http_route_pattern_type_t type,
- nxt_http_route_encoding_t encoding,
+ nxt_str_t *test, nxt_http_route_pattern_type_t type,
+ nxt_http_uri_encoding_t encoding,
nxt_http_route_pattern_case_t pattern_case)
{
u_char *start;
@@ -1554,16 +1486,18 @@ nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
{
nxt_mp_t *mp;
nxt_int_t ret;
+ nxt_router_conf_t *rtcf;
nxt_http_action_t *action;
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
action = nxt_mp_alloc(mp, sizeof(nxt_http_action_t));
if (nxt_slow_path(action == NULL)) {
return NULL;
}
- action->u.var = nxt_var_compile(pass, mp, 0);
+ action->u.var = nxt_var_compile(pass, mp, rtcf->var_fields, 0);
if (nxt_slow_path(action->u.var == NULL)) {
return NULL;
}
@@ -1884,6 +1818,13 @@ nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p,
break;
#endif
+#if (NXT_HAVE_UNIX_DOMAIN)
+ case AF_UNIX:
+
+ match = (base->addr_family == AF_UNIX);
+ break;
+#endif
+
default:
match = 0;
break;
@@ -2019,14 +1960,13 @@ nxt_http_route_test_argument(nxt_http_request_t *r,
static nxt_int_t
nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
{
- nxt_bool_t tls, https;
+ nxt_bool_t https;
nxt_http_route_pattern_slice_t *pattern_slice;
pattern_slice = rule->pattern[0].u.pattern_slices->elts;
https = (pattern_slice->length == nxt_length("https"));
- tls = (r->tls != NULL);
- return (tls == https);
+ return (r->tls == https);
}
diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c
index 2907a902..34455af4 100644
--- a/src/nxt_http_route_addr.c
+++ b/src/nxt_http_route_addr.c
@@ -41,6 +41,16 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp,
base->negative = 0;
}
+ if (nxt_str_eq(&addr, "unix", 4)) {
+#if (NXT_HAVE_UNIX_DOMAIN)
+ base->addr_family = AF_UNIX;
+
+ return NXT_OK;
+#else
+ return NXT_ADDR_PATTERN_NO_UNIX_ERROR;
+#endif
+ }
+
if (nxt_slow_path(addr.length < 2)) {
return NXT_ADDR_PATTERN_LENGTH_ERROR;
}
@@ -233,7 +243,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp,
}
addr.length = delim - addr.start;
- inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFF << (32 - cidr_prefix)));
+ inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFFULL << (32 - cidr_prefix)));
inet->start = nxt_inet_addr(addr.start, addr.length) & inet->end;
if (nxt_slow_path(inet->start == INADDR_NONE)) {
diff --git a/src/nxt_http_route_addr.h b/src/nxt_http_route_addr.h
index 3b1e1da3..2deda6f8 100644
--- a/src/nxt_http_route_addr.h
+++ b/src/nxt_http_route_addr.h
@@ -26,6 +26,7 @@ enum {
NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR,
NXT_ADDR_PATTERN_CIDR_ERROR,
NXT_ADDR_PATTERN_NO_IPv6_ERROR,
+ NXT_ADDR_PATTERN_NO_UNIX_ERROR,
};
diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c
index 61dd0cb3..0507e038 100644
--- a/src/nxt_http_static.c
+++ b/src/nxt_http_static.c
@@ -79,9 +79,11 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_str_t str, *ret;
nxt_var_t *var;
nxt_conf_value_t *cv;
+ nxt_router_conf_t *rtcf;
nxt_http_static_conf_t *conf;
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t));
if (nxt_slow_path(conf == NULL)) {
@@ -102,7 +104,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
cv = nxt_conf_get_array_element_or_itself(acf->share, i);
nxt_conf_get_string(cv, &str);
- var = nxt_var_compile(&str, mp, 1);
+ var = nxt_var_compile(&str, mp, rtcf->var_fields, NXT_VAR_STRZ);
if (nxt_slow_path(var == NULL)) {
return NXT_ERROR;
}
@@ -128,7 +130,8 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_str_t chr, shr;
nxt_bool_t is_const;
- conf->chroot = nxt_var_compile(&acf->chroot, mp, 1);
+ conf->chroot = nxt_var_compile(&acf->chroot, mp, rtcf->var_fields,
+ NXT_VAR_STRZ);
if (nxt_slow_path(conf->chroot == NULL)) {
return NXT_ERROR;
}
@@ -756,9 +759,7 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten)
end = path->start + path->length;
p = end;
- for ( ;; ) {
- /* There's always '/' in the beginning of the request path. */
-
+ while (p > path->start) {
p--;
ch = *p;
@@ -767,11 +768,14 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten)
p++;
/* Fall through. */
case '.':
- exten->length = end - p;
- exten->start = p;
- return;
+ goto extension;
}
}
+
+extension:
+
+ exten->length = end - p;
+ exten->start = p;
}
@@ -1023,7 +1027,7 @@ typedef struct {
nxt_int_t
nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
- nxt_str_t *exten, nxt_str_t *type)
+ const nxt_str_t *exten, nxt_str_t *type)
{
nxt_lvlhsh_query_t lhq;
nxt_http_static_mtype_t *mtype;
@@ -1048,7 +1052,7 @@ nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
nxt_str_t *
-nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten)
+nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, const nxt_str_t *exten)
{
nxt_lvlhsh_query_t lhq;
nxt_http_static_mtype_t *mtype;
diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c
index b765e177..5a632b24 100644
--- a/src/nxt_http_variables.c
+++ b/src/nxt_http_variables.c
@@ -7,32 +7,90 @@
#include <nxt_http.h>
-static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query,
- nxt_str_t *str, void *ctx);
-static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task,
- nxt_var_query_t *query, nxt_str_t *str, void *ctx);
-static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query,
- nxt_str_t *str, void *ctx);
-static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query,
- nxt_str_t *str, void *ctx);
+static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field);
+static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field);
+static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now,
+ struct tm *tm, size_t size, const char *format);
+static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field);
+static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
+static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str,
+ void *ctx, uint16_t field);
static nxt_var_decl_t nxt_http_vars[] = {
- { nxt_string("method"),
- &nxt_http_var_method,
- 0 },
-
- { nxt_string("request_uri"),
- &nxt_http_var_request_uri,
- 0 },
-
- { nxt_string("uri"),
- &nxt_http_var_uri,
- 0 },
-
- { nxt_string("host"),
- &nxt_http_var_host,
- 0 },
+ {
+ .name = nxt_string("dollar"),
+ .handler = nxt_http_var_dollar,
+ }, {
+ .name = nxt_string("method"),
+ .handler = nxt_http_var_method,
+ }, {
+ .name = nxt_string("request_uri"),
+ .handler = nxt_http_var_request_uri,
+ }, {
+ .name = nxt_string("uri"),
+ .handler = nxt_http_var_uri,
+ }, {
+ .name = nxt_string("host"),
+ .handler = nxt_http_var_host,
+ }, {
+ .name = nxt_string("remote_addr"),
+ .handler = nxt_http_var_remote_addr,
+ }, {
+ .name = nxt_string("time_local"),
+ .handler = nxt_http_var_time_local,
+ }, {
+ .name = nxt_string("request_line"),
+ .handler = nxt_http_var_request_line,
+ }, {
+ .name = nxt_string("status"),
+ .handler = nxt_http_var_status,
+ }, {
+ .name = nxt_string("body_bytes_sent"),
+ .handler = nxt_http_var_body_bytes_sent,
+ }, {
+ .name = nxt_string("header_referer"),
+ .handler = nxt_http_var_referer,
+ }, {
+ .name = nxt_string("header_user_agent"),
+ .handler = nxt_http_var_user_agent,
+ }, {
+ .name = nxt_string("arg"),
+ .handler = nxt_http_var_arg,
+ .field_hash = nxt_http_argument_hash,
+ }, {
+ .name = nxt_string("header"),
+ .handler = nxt_http_var_header,
+ .field_hash = nxt_http_header_hash,
+ }, {
+ .name = nxt_string("cookie"),
+ .handler = nxt_http_var_cookie,
+ .field_hash = nxt_http_cookie_hash,
+ },
};
@@ -44,8 +102,16 @@ nxt_http_register_variables(void)
static nxt_int_t
-nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
- void *ctx)
+nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_str_set(str, "$");
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
{
nxt_http_request_t *r;
@@ -58,8 +124,8 @@ nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
static nxt_int_t
-nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query,
- nxt_str_t *str, void *ctx)
+nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
{
nxt_http_request_t *r;
@@ -72,8 +138,7 @@ nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query,
static nxt_int_t
-nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
- void *ctx)
+nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
{
nxt_http_request_t *r;
@@ -86,8 +151,7 @@ nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
static nxt_int_t
-nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
- void *ctx)
+nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
{
nxt_http_request_t *r;
@@ -97,3 +161,323 @@ nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str,
return NXT_OK;
}
+
+
+static nxt_int_t
+nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ str->length = r->remote->address_length;
+ str->start = nxt_sockaddr_address(r->remote);
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ static nxt_time_string_t date_cache = {
+ (nxt_atomic_uint_t) -1,
+ nxt_http_log_date,
+ "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d",
+ nxt_length("31/Dec/1986:19:40:00 +0300"),
+ NXT_THREAD_TIME_LOCAL,
+ NXT_THREAD_TIME_SEC,
+ };
+
+ r = ctx;
+
+ str->length = date_cache.size;
+
+ str->start = nxt_mp_nget(r->mem_pool, str->length);
+ if (nxt_slow_path(str->start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ str->length = nxt_thread_time_string(task->thread, &date_cache, str->start)
+ - str->start;
+
+ return NXT_OK;
+}
+
+
+static u_char *
+nxt_http_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm,
+ size_t size, const char *format)
+{
+ u_char sign;
+ time_t gmtoff;
+
+ static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+ gmtoff = nxt_timezone(tm) / 60;
+
+ if (gmtoff < 0) {
+ gmtoff = -gmtoff;
+ sign = '-';
+
+ } else {
+ sign = '+';
+ }
+
+ return nxt_sprintf(buf, buf + size, format,
+ tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900,
+ tm->tm_hour, tm->tm_min, tm->tm_sec,
+ sign, gmtoff / 60, gmtoff % 60);
+}
+
+
+static nxt_int_t
+nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ size_t length;
+ u_char *p, *start;
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ length = r->method->length + 1 + r->target.length + 1 + r->version.length;
+
+ start = nxt_mp_nget(r->mem_pool, length);
+ if (nxt_slow_path(start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ p = start;
+
+ if (r->method->length != 0) {
+ p = nxt_cpymem(p, r->method->start, r->method->length);
+
+ if (r->target.length != 0) {
+ *p++ = ' ';
+ p = nxt_cpymem(p, r->target.start, r->target.length);
+
+ if (r->version.length != 0) {
+ *p++ = ' ';
+ p = nxt_cpymem(p, r->version.start, r->version.length);
+ }
+ }
+
+ } else {
+ *p++ = '-';
+ }
+
+ str->start = start;
+ str->length = p - start;
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_off_t bytes;
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN);
+ if (nxt_slow_path(str->start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto);
+
+ str->length = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O",
+ bytes) - str->start;
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ str->start = nxt_mp_nget(r->mem_pool, 3);
+ if (nxt_slow_path(str->start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ str->length = nxt_sprintf(str->start, str->start + 3, "%03d", r->status)
+ - str->start;
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ if (r->referer != NULL) {
+ str->start = r->referer->value;
+ str->length = r->referer->value_length;
+
+ } else {
+ nxt_str_null(str);
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, void *ctx,
+ uint16_t field)
+{
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ if (r->user_agent != NULL) {
+ str->start = r->user_agent->value;
+ str->length = r->user_agent->value_length;
+
+ } else {
+ nxt_str_null(str);
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_array_t *args;
+ nxt_var_field_t *vf;
+ nxt_router_conf_t *rtcf;
+ nxt_http_request_t *r;
+ nxt_http_name_value_t *nv, *start;
+
+ r = ctx;
+
+ rtcf = r->conf->socket_conf->router_conf;
+
+ vf = nxt_var_field_get(rtcf->var_fields, field);
+
+ args = nxt_http_arguments_parse(r);
+ if (nxt_slow_path(args == NULL)) {
+ return NXT_ERROR;
+ }
+
+ start = args->elts;
+ nv = start + args->nelts - 1;
+
+ while (nv >= start) {
+
+ if (vf->hash == nv->hash
+ && vf->name.length == nv->name_length
+ && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0)
+ {
+ str->start = nv->value;
+ str->length = nv->value_length;
+
+ return NXT_OK;
+ }
+
+ nv--;
+ }
+
+ nxt_str_null(str);
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_var_field_t *vf;
+ nxt_http_field_t *f;
+ nxt_router_conf_t *rtcf;
+ nxt_http_request_t *r;
+
+ r = ctx;
+
+ rtcf = r->conf->socket_conf->router_conf;
+
+ vf = nxt_var_field_get(rtcf->var_fields, field);
+
+ nxt_list_each(f, r->fields) {
+
+ if (vf->hash == f->hash
+ && vf->name.length == f->name_length
+ && nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0)
+ {
+ str->start = f->value;
+ str->length = f->value_length;
+
+ return NXT_OK;
+ }
+
+ } nxt_list_loop;
+
+ nxt_str_null(str);
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
+{
+ nxt_array_t *cookies;
+ nxt_var_field_t *vf;
+ nxt_router_conf_t *rtcf;
+ nxt_http_request_t *r;
+ nxt_http_name_value_t *nv, *end;
+
+ r = ctx;
+
+ rtcf = r->conf->socket_conf->router_conf;
+
+ vf = nxt_var_field_get(rtcf->var_fields, field);
+
+ cookies = nxt_http_cookies_parse(r);
+ if (nxt_slow_path(cookies == NULL)) {
+ return NXT_ERROR;
+ }
+
+ nv = cookies->elts;
+ end = nv + cookies->nelts;
+
+ while (nv < end) {
+
+ if (vf->hash == nv->hash
+ && vf->name.length == nv->name_length
+ && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0)
+ {
+ str->start = nv->value;
+ str->length = nv->value_length;
+
+ return NXT_OK;
+ }
+
+ nv++;
+ }
+
+ nxt_str_null(str);
+
+ return NXT_OK;
+}
diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c
index e3cb1f22..796da4c6 100644
--- a/src/nxt_isolation.c
+++ b/src/nxt_isolation.c
@@ -7,7 +7,7 @@
#include <nxt_process.h>
#include <nxt_isolation.h>
-#if (NXT_HAVE_PIVOT_ROOT)
+#if (NXT_HAVE_MNTENT_H)
#include <mntent.h>
#endif
@@ -45,7 +45,7 @@ static int nxt_cdecl nxt_isolation_mount_compare(const void *v1,
const void *v2);
static void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process);
-#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
+#if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
static nxt_int_t nxt_isolation_pivot_root(nxt_task_t *task, const char *rootfs);
static nxt_int_t nxt_isolation_make_private_mount(nxt_task_t *task,
const char *rootfs);
@@ -752,7 +752,7 @@ undo:
}
-#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
+#if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
nxt_int_t
nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process)
@@ -1003,11 +1003,11 @@ fail:
nxt_inline int
nxt_pivot_root(const char *new_root, const char *old_root)
{
- return syscall(__NR_pivot_root, new_root, old_root);
+ return syscall(SYS_pivot_root, new_root, old_root);
}
-#else /* !(NXT_HAVE_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */
+#else /* !(NXT_HAVE_LINUX_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */
nxt_int_t
diff --git a/src/nxt_isolation.h b/src/nxt_isolation.h
index 88a5f9e1..b1bfc33c 100644
--- a/src/nxt_isolation.h
+++ b/src/nxt_isolation.h
@@ -2,8 +2,8 @@
* Copyright (C) NGINX, Inc.
*/
-#ifndef _NXT_ISOLATION_H_
-#define _NXT_ISOLATION_H_
+#ifndef _NXT_ISOLATION_H_INCLUDED_
+#define _NXT_ISOLATION_H_INCLUDED_
nxt_int_t nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process,
@@ -15,4 +15,4 @@ nxt_int_t nxt_isolation_prepare_rootfs(nxt_task_t *task,
nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process);
#endif
-#endif /* _NXT_ISOLATION_H_ */
+#endif /* _NXT_ISOLATION_H_INCLUDED_ */
diff --git a/src/nxt_job_resolve.c b/src/nxt_job_resolve.c
deleted file mode 100644
index 0f1fb9aa..00000000
--- a/src/nxt_job_resolve.c
+++ /dev/null
@@ -1,132 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-#include <nxt_main.h>
-
-
-void
-nxt_job_resolve(nxt_job_resolve_t *jbr)
-{
- int err;
- u_char *host;
- size_t length;
- nxt_mp_t *mp;
- nxt_uint_t n;
- nxt_sockaddr_t *sa;
- struct addrinfo hint, *res, *r;
- nxt_work_handler_t handler;
-
- #define NXT_BUFSIZE 64
- u_char buf[NXT_BUFSIZE];
-
- handler = jbr->error_handler;
- res = NULL;
-
- length = jbr->name.length + 1;
-
- if (nxt_fast_path(length <= NXT_BUFSIZE)) {
- host = buf;
-
- } else {
- host = nxt_mp_alloc(jbr->job.mem_pool, length);
- if (nxt_slow_path(host == NULL)) {
- goto fail;
- }
- }
-
- nxt_cpystrn(host, jbr->name.start, length);
-
- nxt_memzero(&hint, sizeof(struct addrinfo));
- hint.ai_socktype = SOCK_STREAM;
-
- err = getaddrinfo((char *) host, NULL, &hint, &res);
-
- if (err != 0) {
- nxt_thread_log_error(jbr->log_level,
- "getaddrinfo(\"%s\") failed (%d: %s)",
- host, err, gai_strerror(err));
- goto fail;
- }
-
- n = 0;
- for (r = res; r != NULL; r = r->ai_next) {
-
- switch (r->ai_addr->sa_family) {
-#if (NXT_INET6)
- case AF_INET6:
-#endif
- case AF_INET:
- n++;
- break;
-
- default:
- break;
- }
- }
-
- jbr->count = n;
- mp = jbr->job.mem_pool;
-
- jbr->sockaddrs = nxt_mp_alloc(mp, n * sizeof(nxt_sockaddr_t *));
- if (nxt_slow_path(jbr->sockaddrs == NULL)) {
- goto fail;
- }
-
- n = 0;
- for (r = res; r != NULL; r = r->ai_next) {
-
- switch (r->ai_addr->sa_family) {
-#if (NXT_INET6)
- case AF_INET6:
- length = NXT_INET6_ADDR_STR_LEN;
- break;
-#endif
- case AF_INET:
- length = NXT_INET_ADDR_STR_LEN;
- break;
-
- default:
- continue;
- }
-
- sa = nxt_sockaddr_create(mp, r->ai_addr, r->ai_addrlen, length);
- if (nxt_slow_path(sa == NULL)) {
- goto fail;
- }
-
- jbr->sockaddrs[n++] = sa;
-
- if (jbr->port != 0) {
-
- switch (sa->u.sockaddr.sa_family) {
- case AF_INET:
- sa->u.sockaddr_in.sin_port = jbr->port;
- break;
-#if (NXT_INET6)
- case AF_INET6:
- sa->u.sockaddr_in6.sin6_port = jbr->port;
- break;
-#endif
- default:
- break;
- }
- }
- }
-
- handler = jbr->ready_handler;
-
-fail:
-
- if (nxt_fast_path(res != NULL)) {
- freeaddrinfo(res);
- }
-
- if (host != buf) {
- nxt_mp_free(jbr->job.mem_pool, host);
- }
-
- nxt_job_return(jbr->job.task, &jbr->job, handler);
-}
diff --git a/src/nxt_job_resolve.h b/src/nxt_job_resolve.h
deleted file mode 100644
index fef55b99..00000000
--- a/src/nxt_job_resolve.h
+++ /dev/null
@@ -1,29 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-#ifndef _NXT_JOB_RESOLVE_H_INCLUDED_
-#define _NXT_JOB_RESOLVE_H_INCLUDED_
-
-
-typedef struct {
- nxt_job_t job;
- nxt_str_t name;
-
- uint32_t log_level; /* 4 bits */
- in_port_t port;
- uint16_t count;
-
- nxt_sockaddr_t **sockaddrs;
-
- nxt_work_handler_t ready_handler;
- nxt_work_handler_t error_handler;
-} nxt_job_resolve_t;
-
-
-void nxt_job_resolve(nxt_job_resolve_t *jbr);
-
-
-#endif /* _NXT_JOB_RESOLVE_H_INCLUDED_ */
diff --git a/src/nxt_main.h b/src/nxt_main.h
index 7f812568..dca4b6dc 100644
--- a/src/nxt_main.h
+++ b/src/nxt_main.h
@@ -146,7 +146,6 @@ typedef void (*nxt_event_conn_handler_t)(nxt_thread_t *thr, nxt_conn_t *c);
#include <nxt_job_file.h>
#include <nxt_buf_filter.h>
-#include <nxt_job_resolve.h>
#include <nxt_sockaddr.h>
#include <nxt_cache.h>
diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c
index 03761a10..39a8e112 100644
--- a/src/nxt_main_process.c
+++ b/src/nxt_main_process.c
@@ -1187,7 +1187,9 @@ nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls)
#if (NXT_HAVE_UNIX_DOMAIN)
- if (sa->u.sockaddr.sa_family == AF_UNIX) {
+ if (sa->u.sockaddr.sa_family == AF_UNIX
+ && sa->u.sockaddr_un.sun_path[0] != '\0')
+ {
char *filename;
mode_t access;
diff --git a/src/nxt_mp.c b/src/nxt_mp.c
index d0de2c0e..2bd8cdee 100644
--- a/src/nxt_mp.c
+++ b/src/nxt_mp.c
@@ -155,7 +155,7 @@ static void *nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size,
nxt_bool_t freeable);
static intptr_t nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1,
nxt_rbtree_node_t *node2);
-static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p);
+static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p);
static const char *nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster,
u_char *p);
@@ -830,7 +830,7 @@ nxt_mp_free(nxt_mp_t *mp, void *p)
static nxt_mp_block_t *
-nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p)
+nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p)
{
nxt_mp_block_t *block;
nxt_rbtree_node_t *node, *sentinel;
diff --git a/src/nxt_nncq.h b/src/nxt_nncq.h
index 20e7ecff..6c9ab326 100644
--- a/src/nxt_nncq.h
+++ b/src/nxt_nncq.h
@@ -85,7 +85,7 @@ nxt_nncq_empty(nxt_nncq_t const volatile *q)
}
-static void
+static inline void
nxt_nncq_init(nxt_nncq_t volatile *q)
{
q->head = NXT_NNCQ_SIZE;
@@ -94,7 +94,7 @@ nxt_nncq_init(nxt_nncq_t volatile *q)
}
-static void
+static inline void
nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val)
{
nxt_nncq_cycle_t e_cycle, t_cycle;
@@ -128,7 +128,7 @@ nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val)
}
-static nxt_nncq_atomic_t
+static inline nxt_nncq_atomic_t
nxt_nncq_dequeue(nxt_nncq_t volatile *q)
{
nxt_nncq_cycle_t e_cycle, h_cycle;
diff --git a/src/nxt_nvbcq.h b/src/nxt_nvbcq.h
index 2b019dcc..e164615b 100644
--- a/src/nxt_nvbcq.h
+++ b/src/nxt_nvbcq.h
@@ -64,7 +64,7 @@ nxt_nvbcq_empty(nxt_nvbcq_t const volatile *q)
}
-static void
+static inline void
nxt_nvbcq_init(nxt_nvbcq_t volatile *q)
{
nxt_nvbcq_atomic_t i;
@@ -79,7 +79,7 @@ nxt_nvbcq_init(nxt_nvbcq_t volatile *q)
}
-static void
+static inline void
nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val)
{
nxt_nvbcq_atomic_t t, h, i;
@@ -110,7 +110,7 @@ nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val)
}
-static nxt_nvbcq_atomic_t
+static inline nxt_nvbcq_atomic_t
nxt_nvbcq_dequeue(nxt_nvbcq_t volatile *q)
{
nxt_nvbcq_atomic_t h, t, i, e;
diff --git a/src/nxt_port.h b/src/nxt_port.h
index 3b66edfd..3a8da5ad 100644
--- a/src/nxt_port.h
+++ b/src/nxt_port.h
@@ -53,6 +53,9 @@ struct nxt_port_handlers_s {
nxt_port_handler_t data;
nxt_port_handler_t app_restart;
+ /* Status report. */
+ nxt_port_handler_t status;
+
nxt_port_handler_t oosm;
nxt_port_handler_t shm_ack;
nxt_port_handler_t read_queue;
@@ -104,6 +107,7 @@ typedef enum {
_NXT_PORT_MSG_DATA = nxt_port_handler_idx(data),
_NXT_PORT_MSG_APP_RESTART = nxt_port_handler_idx(app_restart),
+ _NXT_PORT_MSG_STATUS = nxt_port_handler_idx(status),
_NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm),
_NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack),
@@ -145,6 +149,7 @@ typedef enum {
NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA,
NXT_PORT_MSG_DATA_LAST = nxt_msg_last(_NXT_PORT_MSG_DATA),
NXT_PORT_MSG_APP_RESTART = nxt_msg_last(_NXT_PORT_MSG_APP_RESTART),
+ NXT_PORT_MSG_STATUS = nxt_msg_last(_NXT_PORT_MSG_STATUS),
NXT_PORT_MSG_OOSM = nxt_msg_last(_NXT_PORT_MSG_OOSM),
NXT_PORT_MSG_SHM_ACK = nxt_msg_last(_NXT_PORT_MSG_SHM_ACK),
@@ -174,9 +179,6 @@ typedef struct {
/* More Fragments followed. */
uint8_t mf; /* 1 bit */
-
- /* Message delivery tracking enabled, next chunk is tracking msg. */
- uint8_t tracking; /* 1 bit */
} nxt_port_msg_t;
@@ -186,7 +188,6 @@ typedef struct {
size_t share;
nxt_fd_t fd[2];
nxt_port_msg_t port_msg;
- uint32_t tracking_msg[2];
uint8_t close_fd; /* 1 bit */
uint8_t allocated; /* 1 bit */
} nxt_port_send_msg_t;
diff --git a/src/nxt_port_memory.c b/src/nxt_port_memory.c
index e799f860..0a4a6c53 100644
--- a/src/nxt_port_memory.c
+++ b/src/nxt_port_memory.c
@@ -539,137 +539,6 @@ nxt_port_get_port_incoming_mmap(nxt_task_t *task, nxt_pid_t spid, uint32_t id)
}
-nxt_int_t
-nxt_port_mmap_get_tracking(nxt_task_t *task, nxt_port_mmaps_t *mmaps,
- nxt_port_mmap_tracking_t *tracking, uint32_t stream)
-{
- nxt_chunk_id_t c;
- nxt_port_mmap_header_t *hdr;
- nxt_port_mmap_handler_t *mmap_handler;
-
- nxt_debug(task, "request tracking for stream #%uD", stream);
-
- mmap_handler = nxt_port_mmap_get(task, mmaps, &c, 1, 1);
- if (nxt_slow_path(mmap_handler == NULL)) {
- return NXT_ERROR;
- }
-
- nxt_port_mmap_handler_use(mmap_handler, 1);
-
- hdr = mmap_handler->hdr;
-
- tracking->mmap_handler = mmap_handler;
- tracking->tracking = hdr->tracking + c;
-
- *tracking->tracking = stream;
-
- nxt_debug(task, "outgoing tracking allocation: %PI->%PI,%d,%d",
- hdr->src_pid, hdr->dst_pid, hdr->id, c);
-
- return NXT_OK;
-}
-
-
-nxt_bool_t
-nxt_port_mmap_tracking_cancel(nxt_task_t *task,
- nxt_port_mmap_tracking_t *tracking, uint32_t stream)
-{
- nxt_bool_t res;
- nxt_chunk_id_t c;
- nxt_port_mmap_header_t *hdr;
- nxt_port_mmap_handler_t *mmap_handler;
-
- mmap_handler = tracking->mmap_handler;
-
- if (nxt_slow_path(mmap_handler == NULL)) {
- return 0;
- }
-
- hdr = mmap_handler->hdr;
-
- res = nxt_atomic_cmp_set(tracking->tracking, stream, 0);
-
- nxt_debug(task, "%s tracking for stream #%uD",
- (res ? "cancelled" : "failed to cancel"), stream);
-
- if (!res) {
- c = tracking->tracking - hdr->tracking;
- nxt_port_mmap_set_chunk_free(hdr->free_tracking_map, c);
- }
-
- nxt_port_mmap_handler_use(mmap_handler, -1);
-
- return res;
-}
-
-
-nxt_int_t
-nxt_port_mmap_tracking_write(uint32_t *buf, nxt_port_mmap_tracking_t *t)
-{
- nxt_port_mmap_handler_t *mmap_handler;
-
- mmap_handler = t->mmap_handler;
-
-#if (NXT_DEBUG)
- {
- nxt_atomic_t *tracking;
-
- tracking = mmap_handler->hdr->tracking;
-
- nxt_assert(t->tracking >= tracking);
- nxt_assert(t->tracking < tracking + PORT_MMAP_CHUNK_COUNT);
- }
-#endif
-
- buf[0] = mmap_handler->hdr->id;
- buf[1] = t->tracking - mmap_handler->hdr->tracking;
-
- return NXT_OK;
-}
-
-nxt_bool_t
-nxt_port_mmap_tracking_read(nxt_task_t *task, nxt_port_recv_msg_t *msg)
-{
- nxt_buf_t *b;
- nxt_bool_t res;
- nxt_chunk_id_t c;
- nxt_port_mmap_header_t *hdr;
- nxt_port_mmap_handler_t *mmap_handler;
- nxt_port_mmap_tracking_msg_t *tracking_msg;
-
- b = msg->buf;
-
- if (nxt_buf_used_size(b) < (int) sizeof(nxt_port_mmap_tracking_msg_t)) {
- nxt_debug(task, "too small message %O", nxt_buf_used_size(b));
- return 0;
- }
-
- tracking_msg = (nxt_port_mmap_tracking_msg_t *) b->mem.pos;
-
- b->mem.pos += sizeof(nxt_port_mmap_tracking_msg_t);
- mmap_handler = nxt_port_get_port_incoming_mmap(task, msg->port_msg.pid,
- tracking_msg->mmap_id);
-
- if (nxt_slow_path(mmap_handler == NULL)) {
- return 0;
- }
-
- hdr = mmap_handler->hdr;
-
- c = tracking_msg->tracking_id;
- res = nxt_atomic_cmp_set(hdr->tracking + c, msg->port_msg.stream, 0);
-
- nxt_debug(task, "tracking for stream #%uD %s", msg->port_msg.stream,
- (res ? "received" : "already cancelled"));
-
- if (!res) {
- nxt_port_mmap_set_chunk_free(hdr->free_tracking_map, c);
- }
-
- return res;
-}
-
-
nxt_buf_t *
nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_mmaps_t *mmaps, size_t size)
{
diff --git a/src/nxt_port_memory.h b/src/nxt_port_memory.h
index a2cdf5dd..f1e70964 100644
--- a/src/nxt_port_memory.h
+++ b/src/nxt_port_memory.h
@@ -15,27 +15,6 @@ typedef struct nxt_port_mmap_handler_s nxt_port_mmap_handler_t;
void nxt_port_mmaps_destroy(nxt_port_mmaps_t *port_mmaps, nxt_bool_t free_elts);
-typedef struct nxt_port_mmap_tracking_s nxt_port_mmap_tracking_t;
-
-struct nxt_port_mmap_tracking_s {
- void *mmap_handler;
- nxt_atomic_t *tracking;
-};
-
-nxt_int_t
-nxt_port_mmap_get_tracking(nxt_task_t *task, nxt_port_mmaps_t *mmaps,
- nxt_port_mmap_tracking_t *tracking, uint32_t stream);
-
-nxt_bool_t
-nxt_port_mmap_tracking_cancel(nxt_task_t *task,
- nxt_port_mmap_tracking_t *tracking, uint32_t stream);
-
-nxt_int_t
-nxt_port_mmap_tracking_write(uint32_t *buf, nxt_port_mmap_tracking_t *t);
-
-nxt_bool_t
-nxt_port_mmap_tracking_read(nxt_task_t *task, nxt_port_recv_msg_t *msg);
-
/*
* Allocates nxt_but_t structure from task's thread engine mem_pool, assigns
* this buf 'mem' pointers to first available shared mem bucket(s). 'size'
diff --git a/src/nxt_port_memory_int.h b/src/nxt_port_memory_int.h
index d2524ee4..21a05b10 100644
--- a/src/nxt_port_memory_int.h
+++ b/src/nxt_port_memory_int.h
@@ -84,13 +84,6 @@ struct nxt_port_mmap_msg_s {
};
-typedef struct nxt_port_mmap_tracking_msg_s nxt_port_mmap_tracking_msg_t;
-
-struct nxt_port_mmap_tracking_msg_s {
- uint32_t mmap_id; /* Mmap index in nxt_process_t.outgoing. */
- nxt_chunk_id_t tracking_id; /* Tracking index. */
-};
-
nxt_inline nxt_bool_t
nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, nxt_chunk_id_t *c);
@@ -107,7 +100,7 @@ nxt_inline void
nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, nxt_chunk_id_t c);
nxt_inline nxt_chunk_id_t
-nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, u_char *p)
+nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, const u_char *p)
{
u_char *mm_start;
diff --git a/src/nxt_port_rpc.c b/src/nxt_port_rpc.c
index 0cac5cbb..28590933 100644
--- a/src/nxt_port_rpc.c
+++ b/src/nxt_port_rpc.c
@@ -512,7 +512,6 @@ nxt_port_rpc_close(nxt_task_t *task, nxt_port_t *port)
msg.port_msg.mmap = 0;
msg.port_msg.nf = 0;
msg.port_msg.mf = 0;
- msg.port_msg.tracking = 0;
msg.size = 0;
msg.cancelled = 0;
msg.u.data = NULL;
diff --git a/src/nxt_port_socket.c b/src/nxt_port_socket.c
index 2a51dfb6..5752d5ab 100644
--- a/src/nxt_port_socket.c
+++ b/src/nxt_port_socket.c
@@ -19,7 +19,7 @@ static uint8_t nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm,
void *qbuf, nxt_buf_t *b);
static nxt_int_t nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port,
nxt_port_send_msg_t *msg);
-static nxt_port_send_msg_t *nxt_port_msg_alloc(nxt_port_send_msg_t *m);
+static nxt_port_send_msg_t *nxt_port_msg_alloc(const nxt_port_send_msg_t *m);
static void nxt_port_write_handler(nxt_task_t *task, void *obj, void *data);
static nxt_port_send_msg_t *nxt_port_msg_first(nxt_port_t *port);
nxt_inline void nxt_port_msg_close_fd(nxt_port_send_msg_t *msg);
@@ -332,7 +332,7 @@ nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port,
static nxt_port_send_msg_t *
-nxt_port_msg_alloc(nxt_port_send_msg_t *m)
+nxt_port_msg_alloc(const nxt_port_send_msg_t *m)
{
nxt_port_send_msg_t *msg;
diff --git a/src/nxt_process.c b/src/nxt_process.c
index 82e66a99..738a03bf 100644
--- a/src/nxt_process.c
+++ b/src/nxt_process.c
@@ -296,6 +296,16 @@ nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process)
} nxt_runtime_process_loop;
+ if (init->siblings != NULL) {
+ nxt_queue_each(p, init->siblings, nxt_process_t, link) {
+
+ nxt_debug(task, "remove sibling process %PI", p->pid);
+
+ nxt_process_close_ports(task, p);
+
+ } nxt_queue_loop;
+ }
+
return NXT_OK;
}
@@ -303,8 +313,9 @@ nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process)
static nxt_pid_t
nxt_process_create(nxt_task_t *task, nxt_process_t *process)
{
- nxt_int_t ret;
- nxt_pid_t pid;
+ nxt_int_t ret;
+ nxt_pid_t pid;
+ nxt_runtime_t *rt;
#if (NXT_HAVE_CLONE)
pid = nxt_clone(SIGCHLD | process->isolation.clone.flags);
@@ -352,7 +363,20 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
process->pid = pid;
process->isolated_pid = pid;
- nxt_runtime_process_add(task, process);
+ rt = task->thread->runtime;
+
+ if (rt->is_pid_isolated) {
+ /*
+ * Do not register process in runtime with isolated pid.
+ * Only global pid can be the key to avoid clash.
+ */
+ nxt_assert(!nxt_queue_is_empty(&process->ports));
+
+ nxt_port_use(task, nxt_process_port_first(process), 1);
+
+ } else {
+ nxt_runtime_process_add(task, process);
+ }
return pid;
}
@@ -798,8 +822,6 @@ nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process)
}
-#if (NXT_HAVE_POSIX_SPAWN)
-
/*
* Linux glibc 2.2 posix_spawn() is implemented via fork()/execve().
* Linux glibc 2.4 posix_spawn() without file actions and spawn
@@ -834,52 +856,6 @@ nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp)
return pid;
}
-#else
-
-nxt_pid_t
-nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp)
-{
- nxt_pid_t pid;
-
- /*
- * vfork() is better than fork() because:
- * it is faster several times;
- * its execution time does not depend on private memory mapping size;
- * it has lesser chances to fail due to the ENOMEM error.
- */
-
- pid = vfork();
-
- switch (pid) {
-
- case -1:
- nxt_alert(task, "vfork() failed while executing \"%s\" %E",
- name, nxt_errno);
- break;
-
- case 0:
- /* A child. */
- nxt_debug(task, "execve(\"%s\")", name);
-
- (void) execve(name, argv, envp);
-
- nxt_alert(task, "execve(\"%s\") failed %E", name, nxt_errno);
-
- exit(1);
- nxt_unreachable();
- break;
-
- default:
- /* A parent. */
- nxt_debug(task, "vfork(): %PI", pid);
- break;
- }
-
- return pid;
-}
-
-#endif
-
nxt_int_t
nxt_process_daemon(nxt_task_t *task)
@@ -1008,6 +984,8 @@ nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process)
{
nxt_port_t *port;
+ nxt_process_use(task, process, 1);
+
nxt_process_port_each(process, port) {
nxt_port_close(task, port);
@@ -1015,6 +993,8 @@ nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process)
nxt_runtime_port_remove(task, port);
} nxt_process_port_loop;
+
+ nxt_process_use(task, process, -1);
}
diff --git a/src/nxt_process.h b/src/nxt_process.h
index 694f457e..15fd4e7f 100644
--- a/src/nxt_process.h
+++ b/src/nxt_process.h
@@ -19,7 +19,7 @@
* fork(2) calls. As we use clone(2) for container, it returns the wrong pid.
*/
#define nxt_getpid() \
- syscall(__NR_getpid)
+ syscall(SYS_getpid)
#else
#define nxt_getpid() \
getpid()
@@ -148,6 +148,8 @@ typedef struct {
const nxt_port_handlers_t *port_handlers;
const nxt_sig_event_t *signals;
+
+ nxt_queue_t *siblings;
} nxt_process_init_t;
diff --git a/src/nxt_router.c b/src/nxt_router.c
index 3a32a363..f02bf3f2 100644
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -7,6 +7,7 @@
#include <nxt_router.h>
#include <nxt_conf.h>
+#include <nxt_status.h>
#if (NXT_TLS)
#include <nxt_cert.h>
#endif
@@ -90,17 +91,14 @@ static void nxt_router_conf_data_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
static void nxt_router_app_restart_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
-static void nxt_router_remove_pid_handler(nxt_task_t *task,
+static void nxt_router_status_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
-static void nxt_router_access_log_reopen_handler(nxt_task_t *task,
+static void nxt_router_remove_pid_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task);
-static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data);
static void nxt_router_conf_ready(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf);
-static void nxt_router_conf_error(nxt_task_t *task,
- nxt_router_temp_conf_t *tmcf);
static void nxt_router_conf_send(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type);
@@ -108,9 +106,10 @@ static nxt_int_t nxt_router_conf_create(nxt_task_t *task,
nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end);
static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task,
nxt_router_conf_t *rtcf, nxt_conf_value_t *conf);
-static nxt_int_t nxt_router_conf_process_client_ip(nxt_task_t *task,
- nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf,
- nxt_conf_value_t *conf);
+static nxt_http_forward_t *nxt_router_conf_forward(nxt_task_t *task,
+ nxt_mp_t *mp, nxt_conf_value_t *conf);
+static nxt_int_t nxt_router_conf_forward_header(nxt_mp_t *mp,
+ nxt_conf_value_t *conf, nxt_http_forward_header_t *fh);
static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name);
static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
@@ -200,27 +199,6 @@ static void nxt_router_req_headers_ack_handler(nxt_task_t *task,
static void nxt_router_listen_socket_release(nxt_task_t *task,
nxt_socket_conf_t *skcf);
-static void nxt_router_access_log_writer(nxt_task_t *task,
- nxt_http_request_t *r, nxt_router_access_log_t *access_log);
-static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now,
- struct tm *tm, size_t size, const char *format);
-static void nxt_router_access_log_open(nxt_task_t *task,
- nxt_router_temp_conf_t *tmcf);
-static void nxt_router_access_log_ready(nxt_task_t *task,
- nxt_port_recv_msg_t *msg, void *data);
-static void nxt_router_access_log_error(nxt_task_t *task,
- nxt_port_recv_msg_t *msg, void *data);
-static void nxt_router_access_log_use(nxt_thread_spinlock_t *lock,
- nxt_router_access_log_t *access_log);
-static void nxt_router_access_log_release(nxt_task_t *task,
- nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log);
-static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj,
- void *data);
-static void nxt_router_access_log_reopen_ready(nxt_task_t *task,
- nxt_port_recv_msg_t *msg, void *data);
-static void nxt_router_access_log_reopen_error(nxt_task_t *task,
- nxt_port_recv_msg_t *msg, void *data);
-
static void nxt_router_app_port_ready(nxt_task_t *task,
nxt_port_recv_msg_t *msg, void *data);
static void nxt_router_app_port_error(nxt_task_t *task,
@@ -270,7 +248,7 @@ static void nxt_router_get_mmap_handler(nxt_task_t *task,
extern const nxt_http_request_state_t nxt_http_websocket;
-static nxt_router_t *nxt_router;
+nxt_router_t *nxt_router;
static const nxt_str_t http_prefix = nxt_string("HTTP_");
static const nxt_str_t empty_prefix = nxt_string("");
@@ -294,6 +272,7 @@ static const nxt_port_handlers_t nxt_router_process_port_handlers = {
.get_mmap = nxt_router_get_mmap_handler,
.data = nxt_router_conf_data_handler,
.app_restart = nxt_router_app_restart_handler,
+ .status = nxt_router_status_handler,
.remove_pid = nxt_router_remove_pid_handler,
.access_log = nxt_router_access_log_reopen_handler,
.rpc_ready = nxt_port_rpc_handler,
@@ -944,6 +923,84 @@ fail:
static void
+nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
+{
+ u_char *p;
+ size_t alloc;
+ nxt_app_t *app;
+ nxt_buf_t *b;
+ nxt_uint_t type;
+ nxt_port_t *port;
+ nxt_status_app_t *app_stat;
+ nxt_event_engine_t *engine;
+ nxt_status_report_t *report;
+
+ port = nxt_runtime_port_find(task->thread->runtime,
+ msg->port_msg.pid,
+ msg->port_msg.reply_port);
+ if (nxt_slow_path(port == NULL)) {
+ nxt_alert(task, "nxt_router_status_handler(): reply port not found");
+ return;
+ }
+
+ alloc = sizeof(nxt_status_report_t);
+
+ nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) {
+
+ alloc += sizeof(nxt_status_app_t) + app->name.length;
+
+ } nxt_queue_loop;
+
+ b = nxt_buf_mem_alloc(port->mem_pool, alloc, 0);
+ if (nxt_slow_path(b == NULL)) {
+ type = NXT_PORT_MSG_RPC_ERROR;
+ goto fail;
+ }
+
+ report = (nxt_status_report_t *) b->mem.free;
+ b->mem.free = b->mem.end;
+
+ nxt_memzero(report, sizeof(nxt_status_report_t));
+
+ nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) {
+
+ report->accepted_conns += engine->accepted_conns_cnt;
+ report->idle_conns += engine->idle_conns_cnt;
+ report->closed_conns += engine->closed_conns_cnt;
+ report->requests += engine->requests_cnt;
+
+ } nxt_queue_loop;
+
+ report->apps_count = 0;
+ app_stat = report->apps;
+ p = b->mem.end;
+
+ nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) {
+ p -= app->name.length;
+
+ nxt_memcpy(p, app->name.start, app->name.length);
+
+ app_stat->name.length = app->name.length;
+ app_stat->name.start = (u_char *) (p - b->mem.pos);
+
+ app_stat->active_requests = app->active_requests;
+ app_stat->pending_processes = app->pending_processes;
+ app_stat->processes = app->processes;
+ app_stat->idle_processes = app->idle_processes;
+
+ report->apps_count++;
+ app_stat++;
+ } nxt_queue_loop;
+
+ type = NXT_PORT_MSG_RPC_READY_LAST;
+
+fail:
+
+ nxt_port_socket_write(task, port, type, -1, msg->port_msg.stream, 0, b);
+}
+
+
+static void
nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port,
void *data)
{
@@ -1003,6 +1060,11 @@ nxt_router_temp_conf(nxt_task_t *task)
rtcf->mem_pool = mp;
+ rtcf->var_fields = nxt_array_create(mp, 4, sizeof(nxt_var_field_t));
+ if (nxt_slow_path(rtcf->var_fields == NULL)) {
+ goto fail;
+ }
+
tmp = nxt_mp_create(1024, 128, 256, 32);
if (nxt_slow_path(tmp == NULL)) {
goto fail;
@@ -1069,7 +1131,7 @@ nxt_router_app_need_start(nxt_app_t *app)
}
-static void
+void
nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data)
{
nxt_int_t ret;
@@ -1225,11 +1287,10 @@ nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
}
-static void
+void
nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
{
nxt_app_t *app;
- nxt_queue_t new_socket_confs;
nxt_socket_t s;
nxt_router_t *router;
nxt_queue_link_t *qlk;
@@ -1252,11 +1313,6 @@ nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
nxt_free(skcf->listen);
}
- nxt_queue_init(&new_socket_confs);
- nxt_queue_add(&new_socket_confs, &updating_sockets);
- nxt_queue_add(&new_socket_confs, &pending_sockets);
- nxt_queue_add(&new_socket_confs, &creating_sockets);
-
rtcf = tmcf->router_conf;
nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) {
@@ -1483,7 +1539,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_mp_t *mp, *app_mp;
uint32_t next, next_target;
nxt_int_t ret;
- nxt_str_t name, path, target;
+ nxt_str_t name, target;
nxt_app_t *app, *prev;
nxt_str_t *t, *s, *targets;
nxt_uint_t n, i;
@@ -1494,16 +1550,15 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_tls_init_t *tls_init;
nxt_conf_value_t *certificate;
#endif
- nxt_conf_value_t *conf, *http, *value, *websocket;
+ nxt_conf_value_t *root, *conf, *http, *value, *websocket;
nxt_conf_value_t *applications, *application;
nxt_conf_value_t *listeners, *listener;
- nxt_conf_value_t *routes_conf, *static_conf, *client_ip_conf;
nxt_socket_conf_t *skcf;
+ nxt_router_conf_t *rtcf;
nxt_http_routes_t *routes;
nxt_event_engine_t *engine;
nxt_app_lang_module_t *lang;
nxt_router_app_conf_t apcf;
- nxt_router_access_log_t *access_log;
nxt_router_listener_conf_t lscf;
static nxt_str_t http_path = nxt_string("/settings/http");
@@ -1520,37 +1575,39 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
#endif
static nxt_str_t static_path = nxt_string("/settings/http/static");
static nxt_str_t websocket_path = nxt_string("/settings/http/websocket");
+ static nxt_str_t forwarded_path = nxt_string("/forwarded");
static nxt_str_t client_ip_path = nxt_string("/client_ip");
- conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL);
- if (conf == NULL) {
+ root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL);
+ if (root == NULL) {
nxt_alert(task, "configuration parsing error");
return NXT_ERROR;
}
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
- ret = nxt_conf_map_object(mp, conf, nxt_router_conf,
- nxt_nitems(nxt_router_conf), tmcf->router_conf);
+ ret = nxt_conf_map_object(mp, root, nxt_router_conf,
+ nxt_nitems(nxt_router_conf), rtcf);
if (ret != NXT_OK) {
nxt_alert(task, "root map error");
return NXT_ERROR;
}
- if (tmcf->router_conf->threads == 0) {
- tmcf->router_conf->threads = nxt_ncpu;
+ if (rtcf->threads == 0) {
+ rtcf->threads = nxt_ncpu;
}
- static_conf = nxt_conf_get_path(conf, &static_path);
+ conf = nxt_conf_get_path(root, &static_path);
- ret = nxt_router_conf_process_static(task, tmcf->router_conf, static_conf);
+ ret = nxt_router_conf_process_static(task, rtcf, conf);
if (nxt_slow_path(ret != NXT_OK)) {
return NXT_ERROR;
}
- router = tmcf->router_conf->router;
+ router = rtcf->router;
- applications = nxt_conf_get_path(conf, &applications_path);
+ applications = nxt_conf_get_path(root, &applications_path);
if (applications != NULL) {
next = 0;
@@ -1599,7 +1656,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_queue_remove(&prev->link);
nxt_queue_insert_tail(&tmcf->previous, &prev->link);
- ret = nxt_router_apps_hash_add(tmcf->router_conf, prev);
+ ret = nxt_router_apps_hash_add(rtcf, prev);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
@@ -1734,7 +1791,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_queue_insert_tail(&tmcf->apps, &app->link);
- ret = nxt_router_apps_hash_add(tmcf->router_conf, app);
+ ret = nxt_router_apps_hash_add(rtcf, app);
if (nxt_slow_path(ret != NXT_OK)) {
goto app_fail;
}
@@ -1785,21 +1842,22 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
}
}
- routes_conf = nxt_conf_get_path(conf, &routes_path);
- if (nxt_fast_path(routes_conf != NULL)) {
- routes = nxt_http_routes_create(task, tmcf, routes_conf);
+ conf = nxt_conf_get_path(root, &routes_path);
+ if (nxt_fast_path(conf != NULL)) {
+ routes = nxt_http_routes_create(task, tmcf, conf);
if (nxt_slow_path(routes == NULL)) {
return NXT_ERROR;
}
- tmcf->router_conf->routes = routes;
+
+ rtcf->routes = routes;
}
- ret = nxt_upstreams_create(task, tmcf, conf);
+ ret = nxt_upstreams_create(task, tmcf, root);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}
- http = nxt_conf_get_path(conf, &http_path);
+ http = nxt_conf_get_path(root, &http_path);
#if 0
if (http == NULL) {
nxt_alert(task, "no \"http\" block");
@@ -1807,9 +1865,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
}
#endif
- websocket = nxt_conf_get_path(conf, &websocket_path);
+ websocket = nxt_conf_get_path(root, &websocket_path);
- listeners = nxt_conf_get_path(conf, &listeners_path);
+ listeners = nxt_conf_get_path(root, &listeners_path);
if (listeners != NULL) {
next = 0;
@@ -1889,11 +1947,22 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
t->length = nxt_strlen(t->start);
}
- client_ip_conf = nxt_conf_get_path(listener, &client_ip_path);
- ret = nxt_router_conf_process_client_ip(task, tmcf, skcf,
- client_ip_conf);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
+ conf = nxt_conf_get_path(listener, &forwarded_path);
+
+ if (conf != NULL) {
+ skcf->forwarded = nxt_router_conf_forward(task, mp, conf);
+ if (nxt_slow_path(skcf->forwarded == NULL)) {
+ return NXT_ERROR;
+ }
+ }
+
+ conf = nxt_conf_get_path(listener, &client_ip_path);
+
+ if (conf != NULL) {
+ skcf->client_ip = nxt_router_conf_forward(task, mp, conf);
+ if (nxt_slow_path(skcf->client_ip == NULL)) {
+ return NXT_ERROR;
+ }
}
#if (NXT_TLS)
@@ -1941,7 +2010,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
#endif
skcf->listen->handler = nxt_http_conn_init;
- skcf->router_conf = tmcf->router_conf;
+ skcf->router_conf = rtcf;
skcf->router_conf->count++;
if (lscf.pass.length != 0) {
@@ -1949,8 +2018,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
/* COMPATIBILITY: listener application. */
} else if (lscf.application.length > 0) {
- skcf->action = nxt_http_pass_application(task,
- tmcf->router_conf,
+ skcf->action = nxt_http_pass_application(task, rtcf,
&lscf.application);
}
@@ -1965,36 +2033,13 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
goto fail;
}
- value = nxt_conf_get_path(conf, &access_log_path);
+ value = nxt_conf_get_path(root, &access_log_path);
if (value != NULL) {
- nxt_conf_get_string(value, &path);
-
- access_log = router->access_log;
-
- if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) {
- nxt_router_access_log_use(&router->lock, access_log);
-
- } else {
- access_log = nxt_malloc(sizeof(nxt_router_access_log_t)
- + path.length);
- if (access_log == NULL) {
- nxt_alert(task, "failed to allocate access log structure");
- goto fail;
- }
-
- access_log->fd = -1;
- access_log->handler = &nxt_router_access_log_writer;
- access_log->count = 1;
-
- access_log->path.length = path.length;
- access_log->path.start = (u_char *) access_log
- + sizeof(nxt_router_access_log_t);
-
- nxt_memcpy(access_log->path.start, path.start, path.length);
+ ret = nxt_router_access_log_create(task, rtcf, value);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
}
-
- tmcf->router_conf->access_log = access_log;
}
nxt_queue_add(&deleting_sockets, &router->sockets);
@@ -2129,74 +2174,103 @@ nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf,
}
-static nxt_int_t
-nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
- nxt_socket_conf_t *skcf, nxt_conf_value_t *conf)
+static nxt_http_forward_t *
+nxt_router_conf_forward(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf)
{
- char c;
- size_t i;
- nxt_mp_t *mp;
- uint32_t hash;
- nxt_str_t header;
- nxt_conf_value_t *source_conf, *header_conf, *recursive_conf;
- nxt_http_client_ip_t *client_ip;
+ nxt_int_t ret;
+ nxt_conf_value_t *header_conf, *client_ip_conf, *protocol_conf;
+ nxt_conf_value_t *source_conf, *recursive_conf;
+ nxt_http_forward_t *forward;
nxt_http_route_addr_rule_t *source;
static nxt_str_t header_path = nxt_string("/header");
+ static nxt_str_t client_ip_path = nxt_string("/client_ip");
+ static nxt_str_t protocol_path = nxt_string("/protocol");
static nxt_str_t source_path = nxt_string("/source");
static nxt_str_t recursive_path = nxt_string("/recursive");
- if (conf == NULL) {
- skcf->client_ip = NULL;
+ header_conf = nxt_conf_get_path(conf, &header_path);
- return NXT_OK;
- }
+ if (header_conf != NULL) {
+ client_ip_conf = nxt_conf_get_path(conf, &header_path);
+ protocol_conf = NULL;
- mp = tmcf->router_conf->mem_pool;
+ } else {
+ client_ip_conf = nxt_conf_get_path(conf, &client_ip_path);
+ protocol_conf = nxt_conf_get_path(conf, &protocol_path);
+ }
source_conf = nxt_conf_get_path(conf, &source_path);
- header_conf = nxt_conf_get_path(conf, &header_path);
recursive_conf = nxt_conf_get_path(conf, &recursive_path);
- if (source_conf == NULL || header_conf == NULL) {
- return NXT_ERROR;
+ if (source_conf == NULL
+ || (protocol_conf == NULL && client_ip_conf == NULL))
+ {
+ return NULL;
}
- client_ip = nxt_mp_zget(mp, sizeof(nxt_http_client_ip_t));
- if (nxt_slow_path(client_ip == NULL)) {
- return NXT_ERROR;
+ forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t));
+ if (nxt_slow_path(forward == NULL)) {
+ return NULL;
}
source = nxt_http_route_addr_rule_create(task, mp, source_conf);
if (nxt_slow_path(source == NULL)) {
- return NXT_ERROR;
+ return NULL;
}
- client_ip->source = source;
-
- nxt_conf_get_string(header_conf, &header);
+ forward->source = source;
if (recursive_conf != NULL) {
- client_ip->recursive = nxt_conf_get_boolean(recursive_conf);
+ forward->recursive = nxt_conf_get_boolean(recursive_conf);
}
- client_ip->header = nxt_str_dup(mp, NULL, &header);
- if (nxt_slow_path(client_ip->header == NULL)) {
+ if (client_ip_conf != NULL) {
+ ret = nxt_router_conf_forward_header(mp, client_ip_conf,
+ &forward->client_ip);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+ }
+
+ if (protocol_conf != NULL) {
+ ret = nxt_router_conf_forward_header(mp, protocol_conf,
+ &forward->protocol);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+ }
+
+ return forward;
+}
+
+
+static nxt_int_t
+nxt_router_conf_forward_header(nxt_mp_t *mp, nxt_conf_value_t *conf,
+ nxt_http_forward_header_t *fh)
+{
+ char c;
+ size_t i;
+ uint32_t hash;
+ nxt_str_t header;
+
+ nxt_conf_get_string(conf, &header);
+
+ fh->header = nxt_str_dup(mp, NULL, &header);
+ if (nxt_slow_path(fh->header == NULL)) {
return NXT_ERROR;
}
hash = NXT_HTTP_FIELD_HASH_INIT;
- for (i = 0; i < client_ip->header->length; i++) {
- c = client_ip->header->start[i];
+ for (i = 0; i < fh->header->length; i++) {
+ c = fh->header->start[i];
hash = nxt_http_field_hash_char(hash, nxt_lowcase(c));
}
hash = nxt_http_field_hash_end(hash) & 0xFFFF;
- client_ip->header_hash = hash;
-
- skcf->client_ip = client_ip;
+ fh->header_hash = hash;
return NXT_OK;
}
@@ -3719,384 +3793,6 @@ nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint)
static void
-nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r,
- nxt_router_access_log_t *access_log)
-{
- size_t size;
- u_char *buf, *p;
- nxt_off_t bytes;
-
- static nxt_time_string_t date_cache = {
- (nxt_atomic_uint_t) -1,
- nxt_router_access_log_date,
- "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d",
- nxt_length("31/Dec/1986:19:40:00 +0300"),
- NXT_THREAD_TIME_LOCAL,
- NXT_THREAD_TIME_SEC,
- };
-
- size = r->remote->address_length
- + 6 /* ' - - [' */
- + date_cache.size
- + 3 /* '] "' */
- + r->method->length
- + 1 /* space */
- + r->target.length
- + 1 /* space */
- + r->version.length
- + 2 /* '" ' */
- + 3 /* status */
- + 1 /* space */
- + NXT_OFF_T_LEN
- + 2 /* ' "' */
- + (r->referer != NULL ? r->referer->value_length : 1)
- + 3 /* '" "' */
- + (r->user_agent != NULL ? r->user_agent->value_length : 1)
- + 2 /* '"\n' */
- ;
-
- buf = nxt_mp_nget(r->mem_pool, size);
- if (nxt_slow_path(buf == NULL)) {
- return;
- }
-
- p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote),
- r->remote->address_length);
-
- p = nxt_cpymem(p, " - - [", 6);
-
- p = nxt_thread_time_string(task->thread, &date_cache, p);
-
- p = nxt_cpymem(p, "] \"", 3);
-
- if (r->method->length != 0) {
- p = nxt_cpymem(p, r->method->start, r->method->length);
-
- if (r->target.length != 0) {
- *p++ = ' ';
- p = nxt_cpymem(p, r->target.start, r->target.length);
-
- if (r->version.length != 0) {
- *p++ = ' ';
- p = nxt_cpymem(p, r->version.start, r->version.length);
- }
- }
-
- } else {
- *p++ = '-';
- }
-
- p = nxt_cpymem(p, "\" ", 2);
-
- p = nxt_sprintf(p, p + 3, "%03d", r->status);
-
- *p++ = ' ';
-
- bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto);
-
- p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes);
-
- p = nxt_cpymem(p, " \"", 2);
-
- if (r->referer != NULL) {
- p = nxt_cpymem(p, r->referer->value, r->referer->value_length);
-
- } else {
- *p++ = '-';
- }
-
- p = nxt_cpymem(p, "\" \"", 3);
-
- if (r->user_agent != NULL) {
- p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length);
-
- } else {
- *p++ = '-';
- }
-
- p = nxt_cpymem(p, "\"\n", 2);
-
- nxt_fd_write(access_log->fd, buf, p - buf);
-}
-
-
-static u_char *
-nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm,
- size_t size, const char *format)
-{
- u_char sign;
- time_t gmtoff;
-
- static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
- gmtoff = nxt_timezone(tm) / 60;
-
- if (gmtoff < 0) {
- gmtoff = -gmtoff;
- sign = '-';
-
- } else {
- sign = '+';
- }
-
- return nxt_sprintf(buf, buf + size, format,
- tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900,
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- sign, gmtoff / 60, gmtoff % 60);
-}
-
-
-static void
-nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
-{
- uint32_t stream;
- nxt_int_t ret;
- nxt_buf_t *b;
- nxt_port_t *main_port, *router_port;
- nxt_runtime_t *rt;
- nxt_router_access_log_t *access_log;
-
- access_log = tmcf->router_conf->access_log;
-
- b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0);
- if (nxt_slow_path(b == NULL)) {
- goto fail;
- }
-
- b->completion_handler = nxt_buf_dummy_completion;
-
- nxt_buf_cpystr(b, &access_log->path);
- *b->mem.free++ = '\0';
-
- rt = task->thread->runtime;
- main_port = rt->port_by_type[NXT_PROCESS_MAIN];
- router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
-
- stream = nxt_port_rpc_register_handler(task, router_port,
- nxt_router_access_log_ready,
- nxt_router_access_log_error,
- -1, tmcf);
- if (nxt_slow_path(stream == 0)) {
- goto fail;
- }
-
- ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1,
- stream, router_port->id, b);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_port_rpc_cancel(task, router_port, stream);
- goto fail;
- }
-
- return;
-
-fail:
-
- nxt_router_conf_error(task, tmcf);
-}
-
-
-static void
-nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
- void *data)
-{
- nxt_router_temp_conf_t *tmcf;
- nxt_router_access_log_t *access_log;
-
- tmcf = data;
-
- access_log = tmcf->router_conf->access_log;
-
- access_log->fd = msg->fd[0];
-
- nxt_work_queue_add(&task->thread->engine->fast_work_queue,
- nxt_router_conf_apply, task, tmcf, NULL);
-}
-
-
-static void
-nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
- void *data)
-{
- nxt_router_temp_conf_t *tmcf;
-
- tmcf = data;
-
- nxt_router_conf_error(task, tmcf);
-}
-
-
-static void
-nxt_router_access_log_use(nxt_thread_spinlock_t *lock,
- nxt_router_access_log_t *access_log)
-{
- if (access_log == NULL) {
- return;
- }
-
- nxt_thread_spin_lock(lock);
-
- access_log->count++;
-
- nxt_thread_spin_unlock(lock);
-}
-
-
-static void
-nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock,
- nxt_router_access_log_t *access_log)
-{
- if (access_log == NULL) {
- return;
- }
-
- nxt_thread_spin_lock(lock);
-
- if (--access_log->count != 0) {
- access_log = NULL;
- }
-
- nxt_thread_spin_unlock(lock);
-
- if (access_log != NULL) {
-
- if (access_log->fd != -1) {
- nxt_fd_close(access_log->fd);
- }
-
- nxt_free(access_log);
- }
-}
-
-
-typedef struct {
- nxt_mp_t *mem_pool;
- nxt_router_access_log_t *access_log;
-} nxt_router_access_log_reopen_t;
-
-
-static void
-nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
-{
- nxt_mp_t *mp;
- uint32_t stream;
- nxt_int_t ret;
- nxt_buf_t *b;
- nxt_port_t *main_port, *router_port;
- nxt_runtime_t *rt;
- nxt_router_access_log_t *access_log;
- nxt_router_access_log_reopen_t *reopen;
-
- access_log = nxt_router->access_log;
-
- if (access_log == NULL) {
- return;
- }
-
- mp = nxt_mp_create(1024, 128, 256, 32);
- if (nxt_slow_path(mp == NULL)) {
- return;
- }
-
- reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t));
- if (nxt_slow_path(reopen == NULL)) {
- goto fail;
- }
-
- reopen->mem_pool = mp;
- reopen->access_log = access_log;
-
- b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0);
- if (nxt_slow_path(b == NULL)) {
- goto fail;
- }
-
- b->completion_handler = nxt_router_access_log_reopen_completion;
-
- nxt_buf_cpystr(b, &access_log->path);
- *b->mem.free++ = '\0';
-
- rt = task->thread->runtime;
- main_port = rt->port_by_type[NXT_PROCESS_MAIN];
- router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
-
- stream = nxt_port_rpc_register_handler(task, router_port,
- nxt_router_access_log_reopen_ready,
- nxt_router_access_log_reopen_error,
- -1, reopen);
- if (nxt_slow_path(stream == 0)) {
- goto fail;
- }
-
- ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1,
- stream, router_port->id, b);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_port_rpc_cancel(task, router_port, stream);
- goto fail;
- }
-
- nxt_mp_retain(mp);
-
- return;
-
-fail:
-
- nxt_mp_destroy(mp);
-}
-
-
-static void
-nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data)
-{
- nxt_mp_t *mp;
- nxt_buf_t *b;
-
- b = obj;
- mp = b->data;
-
- nxt_mp_release(mp);
-}
-
-
-static void
-nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
- void *data)
-{
- nxt_router_access_log_t *access_log;
- nxt_router_access_log_reopen_t *reopen;
-
- reopen = data;
-
- access_log = reopen->access_log;
-
- if (access_log == nxt_router->access_log) {
-
- if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) {
- nxt_alert(task, "dup2(%FD, %FD) failed %E",
- msg->fd[0], access_log->fd, nxt_errno);
- }
- }
-
- nxt_fd_close(msg->fd[0]);
- nxt_mp_release(reopen->mem_pool);
-}
-
-
-static void
-nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
- void *data)
-{
- nxt_router_access_log_reopen_t *reopen;
-
- reopen = data;
-
- nxt_mp_release(reopen->mem_pool);
-}
-
-
-static void
nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data)
{
nxt_port_t *port;
@@ -5390,7 +5086,6 @@ nxt_router_app_prepare_request(nxt_task_t *task,
msg.pm.mmap = 1;
msg.pm.nf = 0;
msg.pm.mf = 0;
- msg.pm.tracking = 0;
nxt_port_mmap_handler_t *mmap_handler = buf->parent;
nxt_port_mmap_header_t *hdr = mmap_handler->hdr;
@@ -5559,7 +5254,7 @@ nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r,
p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length);
*p++ = '\0';
- req->tls = (r->tls != NULL);
+ req->tls = r->tls;
req->websocket_handshake = r->websocket_handshake;
req->server_name_length = r->server_name.length;
diff --git a/src/nxt_router.h b/src/nxt_router.h
index 7e337d27..a6add219 100644
--- a/src/nxt_router.h
+++ b/src/nxt_router.h
@@ -18,7 +18,7 @@ typedef struct nxt_http_request_s nxt_http_request_t;
typedef struct nxt_http_action_s nxt_http_action_t;
typedef struct nxt_http_routes_s nxt_http_routes_t;
-typedef struct nxt_http_client_ip_s nxt_http_client_ip_t;
+typedef struct nxt_http_forward_s nxt_http_forward_t;
typedef struct nxt_upstream_s nxt_upstream_t;
typedef struct nxt_upstreams_s nxt_upstreams_t;
typedef struct nxt_router_access_log_s nxt_router_access_log_t;
@@ -43,6 +43,7 @@ typedef struct {
uint32_t threads;
nxt_mp_t *mem_pool;
+ nxt_array_t *var_fields; /* of nxt_var_field_t */
nxt_router_t *router;
nxt_http_routes_t *routes;
@@ -52,6 +53,7 @@ typedef struct {
nxt_lvlhsh_t apps_hash;
nxt_router_access_log_t *access_log;
+ nxt_var_t *log_format;
} nxt_router_conf_t;
@@ -197,7 +199,8 @@ typedef struct {
uint8_t discard_unsafe_fields; /* 1 bit */
- nxt_http_client_ip_t *client_ip;
+ nxt_http_forward_t *forwarded;
+ nxt_http_forward_t *client_ip;
#if (NXT_TLS)
nxt_tls_conf_t *tls;
@@ -221,7 +224,8 @@ typedef struct {
struct nxt_router_access_log_s {
void (*handler)(nxt_task_t *task, nxt_http_request_t *r,
- nxt_router_access_log_t *access_log);
+ nxt_router_access_log_t *access_log,
+ nxt_var_t *format);
nxt_fd_t fd;
nxt_str_t path;
uint32_t count;
@@ -235,7 +239,23 @@ nxt_int_t nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name,
nxt_str_t *target, nxt_http_action_t *action);
void nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev,
nxt_socket_conf_joint_t *joint);
+
+void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data);
+void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf);
void nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint);
+nxt_int_t nxt_router_access_log_create(nxt_task_t *task,
+ nxt_router_conf_t *rtcf, nxt_conf_value_t *value);
+void nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf);
+void nxt_router_access_log_use(nxt_thread_spinlock_t *lock,
+ nxt_router_access_log_t *access_log);
+void nxt_router_access_log_release(nxt_task_t *task,
+ nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log);
+void nxt_router_access_log_reopen_handler(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg);
+
+
+extern nxt_router_t *nxt_router;
+
#endif /* _NXT_ROUTER_H_INCLUDED_ */
diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c
new file mode 100644
index 00000000..dc2a6687
--- /dev/null
+++ b/src/nxt_router_access_log.c
@@ -0,0 +1,442 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) Valentin V. Bartenev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_router.h>
+#include <nxt_conf.h>
+#include <nxt_http.h>
+
+
+typedef struct {
+ nxt_str_t path;
+ nxt_str_t format;
+} nxt_router_access_log_conf_t;
+
+
+typedef struct {
+ nxt_str_t text;
+ nxt_router_access_log_t *access_log;
+} nxt_router_access_log_ctx_t;
+
+
+static void nxt_router_access_log_writer(nxt_task_t *task,
+ nxt_http_request_t *r, nxt_router_access_log_t *access_log,
+ nxt_var_t *format);
+static void nxt_router_access_log_write_ready(nxt_task_t *task, void *obj,
+ void *data);
+static void nxt_router_access_log_write_error(nxt_task_t *task, void *obj,
+ void *data);
+static void nxt_router_access_log_ready(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+static void nxt_router_access_log_error(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj,
+ void *data);
+static void nxt_router_access_log_reopen_ready(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+static void nxt_router_access_log_reopen_error(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+
+
+static nxt_conf_map_t nxt_router_access_log_conf[] = {
+ {
+ nxt_string("path"),
+ NXT_CONF_MAP_STR,
+ offsetof(nxt_router_access_log_conf_t, path),
+ },
+
+ {
+ nxt_string("format"),
+ NXT_CONF_MAP_STR,
+ offsetof(nxt_router_access_log_conf_t, format),
+ },
+};
+
+
+nxt_int_t
+nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf,
+ nxt_conf_value_t *value)
+{
+ u_char *p;
+ nxt_int_t ret;
+ nxt_str_t str;
+ nxt_var_t *format;
+ nxt_router_t *router;
+ nxt_router_access_log_t *access_log;
+ nxt_router_access_log_conf_t alcf;
+
+ static nxt_str_t log_format_str = nxt_string("$remote_addr - - "
+ "[$time_local] \"$request_line\" $status $body_bytes_sent "
+ "\"$header_referer\" \"$header_user_agent\"");
+
+ alcf.format = log_format_str;
+
+ if (nxt_conf_type(value) == NXT_CONF_STRING) {
+ nxt_conf_get_string(value, &alcf.path);
+
+ } else {
+ ret = nxt_conf_map_object(rtcf->mem_pool, value,
+ nxt_router_access_log_conf,
+ nxt_nitems(nxt_router_access_log_conf),
+ &alcf);
+ if (ret != NXT_OK) {
+ nxt_alert(task, "access log map error");
+ return NXT_ERROR;
+ }
+ }
+
+ router = nxt_router;
+
+ access_log = router->access_log;
+
+ if (access_log != NULL && nxt_strstr_eq(&alcf.path, &access_log->path)) {
+ nxt_router_access_log_use(&router->lock, access_log);
+
+ } else {
+ access_log = nxt_malloc(sizeof(nxt_router_access_log_t)
+ + alcf.path.length);
+ if (access_log == NULL) {
+ nxt_alert(task, "failed to allocate access log structure");
+ return NXT_ERROR;
+ }
+
+ access_log->fd = -1;
+ access_log->handler = &nxt_router_access_log_writer;
+ access_log->count = 1;
+
+ access_log->path.length = alcf.path.length;
+ access_log->path.start = (u_char *) access_log
+ + sizeof(nxt_router_access_log_t);
+
+ nxt_memcpy(access_log->path.start, alcf.path.start, alcf.path.length);
+ }
+
+ str.length = alcf.format.length + 1;
+
+ str.start = nxt_malloc(str.length);
+ if (str.start == NULL) {
+ nxt_alert(task, "failed to allocate log format structure");
+ return NXT_ERROR;
+ }
+
+ p = nxt_cpymem(str.start, alcf.format.start, alcf.format.length);
+ *p = '\n';
+
+ format = nxt_var_compile(&str, rtcf->mem_pool, rtcf->var_fields,
+ NXT_VAR_LOGGING);
+ if (nxt_slow_path(format == NULL)) {
+ return NXT_ERROR;
+ }
+
+ rtcf->access_log = access_log;
+ rtcf->log_format = format;
+
+ return NXT_OK;
+}
+
+
+static void
+nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r,
+ nxt_router_access_log_t *access_log, nxt_var_t *format)
+{
+ nxt_int_t ret;
+ nxt_router_access_log_ctx_t *ctx;
+
+ ctx = nxt_mp_get(r->mem_pool, sizeof(nxt_router_access_log_ctx_t));
+ if (nxt_slow_path(ctx == NULL)) {
+ return;
+ }
+
+ ctx->access_log = access_log;
+
+ if (nxt_var_is_const(format)) {
+ nxt_var_raw(format, &ctx->text);
+
+ nxt_router_access_log_write_ready(task, r, ctx);
+
+ } else {
+ ret = nxt_var_query_init(&r->var_query, r, r->mem_pool);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return;
+ }
+
+ nxt_var_query(task, r->var_query, format, &ctx->text);
+ nxt_var_query_resolve(task, r->var_query, ctx,
+ nxt_router_access_log_write_ready,
+ nxt_router_access_log_write_error);
+ }
+}
+
+
+static void
+nxt_router_access_log_write_ready(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_http_request_t *r;
+ nxt_router_access_log_ctx_t *ctx;
+
+ r = obj;
+ ctx = data;
+
+ nxt_fd_write(ctx->access_log->fd, ctx->text.start, ctx->text.length);
+
+ nxt_http_request_close_handler(task, r, r->proto.any);
+}
+
+
+static void
+nxt_router_access_log_write_error(nxt_task_t *task, void *obj, void *data)
+{
+
+}
+
+
+void
+nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
+{
+ uint32_t stream;
+ nxt_int_t ret;
+ nxt_buf_t *b;
+ nxt_port_t *main_port, *router_port;
+ nxt_runtime_t *rt;
+ nxt_router_access_log_t *access_log;
+
+ access_log = tmcf->router_conf->access_log;
+
+ b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0);
+ if (nxt_slow_path(b == NULL)) {
+ goto fail;
+ }
+
+ b->completion_handler = nxt_buf_dummy_completion;
+
+ nxt_buf_cpystr(b, &access_log->path);
+ *b->mem.free++ = '\0';
+
+ rt = task->thread->runtime;
+ main_port = rt->port_by_type[NXT_PROCESS_MAIN];
+ router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
+
+ stream = nxt_port_rpc_register_handler(task, router_port,
+ nxt_router_access_log_ready,
+ nxt_router_access_log_error,
+ -1, tmcf);
+ if (nxt_slow_path(stream == 0)) {
+ goto fail;
+ }
+
+ ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1,
+ stream, router_port->id, b);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ nxt_port_rpc_cancel(task, router_port, stream);
+ goto fail;
+ }
+
+ return;
+
+fail:
+
+ nxt_router_conf_error(task, tmcf);
+}
+
+
+static void
+nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_router_temp_conf_t *tmcf;
+ nxt_router_access_log_t *access_log;
+
+ tmcf = data;
+
+ access_log = tmcf->router_conf->access_log;
+
+ access_log->fd = msg->fd[0];
+
+ nxt_work_queue_add(&task->thread->engine->fast_work_queue,
+ nxt_router_conf_apply, task, tmcf, NULL);
+}
+
+
+static void
+nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_router_temp_conf_t *tmcf;
+
+ tmcf = data;
+
+ nxt_router_conf_error(task, tmcf);
+}
+
+
+void
+nxt_router_access_log_use(nxt_thread_spinlock_t *lock,
+ nxt_router_access_log_t *access_log)
+{
+ if (access_log == NULL) {
+ return;
+ }
+
+ nxt_thread_spin_lock(lock);
+
+ access_log->count++;
+
+ nxt_thread_spin_unlock(lock);
+}
+
+
+void
+nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock,
+ nxt_router_access_log_t *access_log)
+{
+ if (access_log == NULL) {
+ return;
+ }
+
+ nxt_thread_spin_lock(lock);
+
+ if (--access_log->count != 0) {
+ access_log = NULL;
+ }
+
+ nxt_thread_spin_unlock(lock);
+
+ if (access_log != NULL) {
+
+ if (access_log->fd != -1) {
+ nxt_fd_close(access_log->fd);
+ }
+
+ nxt_free(access_log);
+ }
+}
+
+
+typedef struct {
+ nxt_mp_t *mem_pool;
+ nxt_router_access_log_t *access_log;
+} nxt_router_access_log_reopen_t;
+
+
+void
+nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
+{
+ nxt_mp_t *mp;
+ uint32_t stream;
+ nxt_int_t ret;
+ nxt_buf_t *b;
+ nxt_port_t *main_port, *router_port;
+ nxt_runtime_t *rt;
+ nxt_router_access_log_t *access_log;
+ nxt_router_access_log_reopen_t *reopen;
+
+ access_log = nxt_router->access_log;
+
+ if (access_log == NULL) {
+ return;
+ }
+
+ mp = nxt_mp_create(1024, 128, 256, 32);
+ if (nxt_slow_path(mp == NULL)) {
+ return;
+ }
+
+ reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t));
+ if (nxt_slow_path(reopen == NULL)) {
+ goto fail;
+ }
+
+ reopen->mem_pool = mp;
+ reopen->access_log = access_log;
+
+ b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0);
+ if (nxt_slow_path(b == NULL)) {
+ goto fail;
+ }
+
+ b->completion_handler = nxt_router_access_log_reopen_completion;
+
+ nxt_buf_cpystr(b, &access_log->path);
+ *b->mem.free++ = '\0';
+
+ rt = task->thread->runtime;
+ main_port = rt->port_by_type[NXT_PROCESS_MAIN];
+ router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
+
+ stream = nxt_port_rpc_register_handler(task, router_port,
+ nxt_router_access_log_reopen_ready,
+ nxt_router_access_log_reopen_error,
+ -1, reopen);
+ if (nxt_slow_path(stream == 0)) {
+ goto fail;
+ }
+
+ ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1,
+ stream, router_port->id, b);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ nxt_port_rpc_cancel(task, router_port, stream);
+ goto fail;
+ }
+
+ nxt_mp_retain(mp);
+
+ return;
+
+fail:
+
+ nxt_mp_destroy(mp);
+}
+
+
+static void
+nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_mp_t *mp;
+ nxt_buf_t *b;
+
+ b = obj;
+ mp = b->data;
+
+ nxt_mp_release(mp);
+}
+
+
+static void
+nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_router_access_log_t *access_log;
+ nxt_router_access_log_reopen_t *reopen;
+
+ reopen = data;
+
+ access_log = reopen->access_log;
+
+ if (access_log == nxt_router->access_log) {
+
+ if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) {
+ nxt_alert(task, "dup2(%FD, %FD) failed %E",
+ msg->fd[0], access_log->fd, nxt_errno);
+ }
+ }
+
+ nxt_fd_close(msg->fd[0]);
+ nxt_mp_release(reopen->mem_pool);
+}
+
+
+static void
+nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_router_access_log_reopen_t *reopen;
+
+ reopen = data;
+
+ nxt_mp_release(reopen->mem_pool);
+}
diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c
index 46955f1c..d9c9f2ef 100644
--- a/src/nxt_runtime.c
+++ b/src/nxt_runtime.c
@@ -1408,6 +1408,7 @@ nxt_runtime_process_release(nxt_runtime_t *rt, nxt_process_t *process)
nxt_assert(process->use_count == 0);
nxt_assert(process->registered == 0);
+ nxt_assert(nxt_queue_is_empty(&process->ports));
nxt_port_mmaps_destroy(&process->incoming, 1);
@@ -1579,11 +1580,11 @@ nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process)
process->registered = 1;
- nxt_thread_log_debug("process %PI added", process->pid);
+ nxt_debug(task, "process %PI added", process->pid);
break;
default:
- nxt_thread_log_debug("process %PI failed to add", process->pid);
+ nxt_alert(task, "process %PI failed to add", process->pid);
break;
}
@@ -1597,6 +1598,8 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process)
nxt_pid_t pid;
nxt_lvlhsh_query_t lhq;
+ nxt_assert(process->registered != 0);
+
pid = process->pid;
nxt_runtime_process_lhq_pid(&lhq, &pid);
@@ -1608,9 +1611,9 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process)
switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) {
case NXT_OK:
- rt->nprocesses--;
+ nxt_assert(lhq.value == process);
- process = lhq.value;
+ rt->nprocesses--;
process->registered = 0;
@@ -1618,7 +1621,7 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process)
break;
default:
- nxt_thread_log_debug("process %PI remove failed", pid);
+ nxt_thread_log_alert("process %PI remove failed", pid);
break;
}
diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c
index 730428e4..86c3335e 100644
--- a/src/nxt_sockaddr.c
+++ b/src/nxt_sockaddr.c
@@ -15,10 +15,6 @@ static nxt_sockaddr_t *nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr);
static nxt_sockaddr_t *nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr);
static nxt_sockaddr_t *nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr);
-static nxt_int_t nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs);
-static nxt_int_t nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs);
-static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs);
-
nxt_sockaddr_t *
nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_socket_t *ls)
@@ -208,8 +204,8 @@ nxt_getsockname(nxt_task_t *task, nxt_mp_t *mp, nxt_socket_t s)
#if (NXT_HAVE_UNIX_DOMAIN)
case AF_UNIX:
length = nxt_length("unix:") + socklen;
-#endif
break;
+#endif
case AF_INET:
length = NXT_INET_ADDR_STR_LEN;
@@ -433,82 +429,6 @@ nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2)
}
-size_t
-nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf, u_char *end, nxt_bool_t port)
-{
- u_char *p;
-
- switch (sa->u.sockaddr.sa_family) {
-
- case AF_INET:
- p = (u_char *) &sa->u.sockaddr_in.sin_addr;
-
- if (port) {
- p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud:%d",
- p[0], p[1], p[2], p[3],
- ntohs(sa->u.sockaddr_in.sin_port));
- } else {
- p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud",
- p[0], p[1], p[2], p[3]);
- }
-
- return p - buf;
-
-#if (NXT_INET6)
-
- case AF_INET6:
- p = buf;
-
- if (port) {
- *p++ = '[';
- }
-
- p = nxt_inet6_ntop(sa->u.sockaddr_in6.sin6_addr.s6_addr, p, end);
-
- if (port) {
- p = nxt_sprintf(p, end, "]:%d",
- ntohs(sa->u.sockaddr_in6.sin6_port));
- }
-
- return p - buf;
-#endif
-
-#if (NXT_HAVE_UNIX_DOMAIN)
-
- case AF_UNIX:
-
-#if (NXT_LINUX)
-
- p = (u_char *) sa->u.sockaddr_un.sun_path;
-
- if (p[0] == '\0') {
- size_t length;
-
- /* Linux abstract socket address has no trailing zero. */
-
- length = sa->socklen - offsetof(struct sockaddr_un, sun_path) - 1;
- p = nxt_sprintf(buf, end, "unix:\\0%*s", length, p + 1);
-
- } else {
- p = nxt_sprintf(buf, end, "unix:%s", p);
- }
-
-#else /* !(NXT_LINUX) */
-
- p = nxt_sprintf(buf, end, "unix:%s", sa->u.sockaddr_un.sun_path);
-
-#endif
-
- return p - buf;
-
-#endif /* NXT_HAVE_UNIX_DOMAIN */
-
- default:
- return 0;
- }
-}
-
-
#if (NXT_INET6)
static u_char *
@@ -681,8 +601,6 @@ nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr)
socklen = offsetof(struct sockaddr_un, sun_path) + length + 1;
-#if (NXT_LINUX)
-
/*
* Linux unix(7):
*
@@ -695,9 +613,12 @@ nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr)
if (path[0] == '@') {
path[0] = '\0';
socklen--;
- }
-
+#if !(NXT_LINUX)
+ nxt_thread_log_error(NXT_LOG_ERR,
+ "abstract unix domain sockets are not supported");
+ return NULL;
#endif
+ }
sa = nxt_sockaddr_alloc(mp, socklen, addr->length);
@@ -849,338 +770,6 @@ nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr)
}
-void
-nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs)
-{
- u_char *p;
- size_t length;
- nxt_int_t ret;
- nxt_work_handler_t handler;
-
- nxt_job_set_name(&jbs->resolve.job, "job sockaddr parse");
-
- length = jbs->addr.length;
- p = jbs->addr.start;
-
- if (length > 6 && nxt_memcmp(p, "unix:", 5) == 0) {
- ret = nxt_job_sockaddr_unix_parse(jbs);
-
- } else if (length != 0 && *p == '[') {
- ret = nxt_job_sockaddr_inet6_parse(jbs);
-
- } else {
- ret = nxt_job_sockaddr_inet_parse(jbs);
- }
-
- switch (ret) {
-
- case NXT_OK:
- handler = jbs->resolve.ready_handler;
- break;
-
- case NXT_ERROR:
- handler = jbs->resolve.error_handler;
- break;
-
- default: /* NXT_AGAIN */
- return;
- }
-
- nxt_job_return(jbs->resolve.job.task, &jbs->resolve.job, handler);
-}
-
-
-static nxt_int_t
-nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs)
-{
-#if (NXT_HAVE_UNIX_DOMAIN)
- size_t length, socklen;
- u_char *path;
- nxt_mp_t *mp;
- nxt_sockaddr_t *sa;
-
- /*
- * Actual sockaddr_un length can be lesser or even larger than defined
- * struct sockaddr_un length (see comment in nxt_socket.h). So
- * limit maximum Unix domain socket address length by defined sun_path[]
- * length because some OSes accept addresses twice larger than defined
- * struct sockaddr_un. Also reserve space for a trailing zero to avoid
- * ambiguity, since many OSes accept Unix domain socket addresses
- * without a trailing zero.
- */
- const size_t max_len = sizeof(struct sockaddr_un)
- - offsetof(struct sockaddr_un, sun_path) - 1;
-
- /* cutting "unix:" */
- length = jbs->addr.length - 5;
- path = jbs->addr.start + 5;
-
- if (length > max_len) {
- nxt_thread_log_error(jbs->resolve.log_level,
- "unix domain socket \"%V\" name is too long",
- &jbs->addr);
- return NXT_ERROR;
- }
-
- socklen = offsetof(struct sockaddr_un, sun_path) + length + 1;
-
-#if (NXT_LINUX)
-
- /*
- * Linux unix(7):
- *
- * abstract: an abstract socket address is distinguished by the fact
- * that sun_path[0] is a null byte ('\0'). The socket's address in
- * this namespace is given by the additional bytes in sun_path that
- * are covered by the specified length of the address structure.
- * (Null bytes in the name have no special significance.)
- */
- if (path[0] == '\0') {
- socklen--;
- }
-
-#endif
-
- mp = jbs->resolve.job.mem_pool;
-
- jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *));
-
- if (nxt_fast_path(jbs->resolve.sockaddrs != NULL)) {
- sa = nxt_sockaddr_alloc(mp, socklen, jbs->addr.length);
-
- if (nxt_fast_path(sa != NULL)) {
- jbs->resolve.count = 1;
- jbs->resolve.sockaddrs[0] = sa;
-
- sa->u.sockaddr_un.sun_family = AF_UNIX;
- nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length);
-
- return NXT_OK;
- }
- }
-
- return NXT_ERROR;
-
-#else /* !(NXT_HAVE_UNIX_DOMAIN) */
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "unix domain socket \"%V\" is not supported",
- &jbs->addr);
- return NXT_ERROR;
-
-#endif
-}
-
-
-static nxt_int_t
-nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs)
-{
-#if (NXT_INET6)
- u_char *p, *addr, *addr_end;
- size_t length;
- nxt_mp_t *mp;
- nxt_int_t port;
- nxt_sockaddr_t *sa;
- struct in6_addr *in6_addr;
-
- length = jbs->addr.length - 1;
- addr = jbs->addr.start + 1;
-
- addr_end = nxt_memchr(addr, ']', length);
-
- if (addr_end == NULL) {
- goto invalid_address;
- }
-
- mp = jbs->resolve.job.mem_pool;
-
- jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *));
-
- if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) {
- return NXT_ERROR;
- }
-
- sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6),
- NXT_INET6_ADDR_STR_LEN);
-
- if (nxt_slow_path(sa == NULL)) {
- return NXT_ERROR;
- }
-
- jbs->resolve.count = 1;
- jbs->resolve.sockaddrs[0] = sa;
-
- in6_addr = &sa->u.sockaddr_in6.sin6_addr;
-
- if (nxt_inet6_addr(in6_addr, addr, addr_end - addr) != NXT_OK) {
- goto invalid_address;
- }
-
- p = addr_end + 1;
- length = (addr + length) - p;
-
- if (length == 0) {
- jbs->no_port = 1;
- port = jbs->resolve.port;
- goto found;
- }
-
- if (*p == ':') {
- port = nxt_int_parse(p + 1, length - 1);
-
- if (port >= 1 && port <= 65535) {
- port = htons((in_port_t) port);
- goto found;
- }
- }
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "invalid port in \"%V\"", &jbs->addr);
-
- return NXT_ERROR;
-
-found:
-
- sa->u.sockaddr_in6.sin6_family = AF_INET6;
- sa->u.sockaddr_in6.sin6_port = (in_port_t) port;
-
- if (IN6_IS_ADDR_UNSPECIFIED(in6_addr)) {
- jbs->wildcard = 1;
- }
-
- return NXT_OK;
-
-invalid_address:
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "invalid IPv6 address in \"%V\"", &jbs->addr);
- return NXT_ERROR;
-
-#else
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "IPv6 socket \"%V\" is not supported", &jbs->addr);
- return NXT_ERROR;
-
-#endif
-}
-
-
-static nxt_int_t
-nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs)
-{
- u_char *p, *host;
- size_t length;
- nxt_mp_t *mp;
- nxt_int_t port;
- in_addr_t addr;
- nxt_sockaddr_t *sa;
-
- addr = INADDR_ANY;
-
- length = jbs->addr.length;
- host = jbs->addr.start;
-
- p = nxt_memchr(host, ':', length);
-
- if (p == NULL) {
-
- /* single value port, address, or host name */
-
- port = nxt_int_parse(host, length);
-
- if (port > 0) {
- if (port < 1 || port > 65535) {
- goto invalid_port;
- }
-
- /* "*:XX" */
- port = htons((in_port_t) port);
- jbs->resolve.port = (in_port_t) port;
-
- } else {
- jbs->no_port = 1;
-
- addr = nxt_inet_addr(host, length);
-
- if (addr == INADDR_NONE) {
- jbs->resolve.name.length = length;
- jbs->resolve.name.start = host;
-
- nxt_job_resolve(&jbs->resolve);
- return NXT_AGAIN;
- }
-
- /* "x.x.x.x" */
- port = jbs->resolve.port;
- }
-
- } else {
-
- /* x.x.x.x:XX or host:XX */
-
- p++;
- length = (host + length) - p;
- port = nxt_int_parse(p, length);
-
- if (port < 1 || port > 65535) {
- goto invalid_port;
- }
-
- port = htons((in_port_t) port);
-
- length = (p - 1) - host;
-
- if (length != 1 || host[0] != '*') {
- addr = nxt_inet_addr(host, length);
-
- if (addr == INADDR_NONE) {
- jbs->resolve.name.length = length;
- jbs->resolve.name.start = host;
- jbs->resolve.port = (in_port_t) port;
-
- nxt_job_resolve(&jbs->resolve);
- return NXT_AGAIN;
- }
-
- /* "x.x.x.x:XX" */
- }
- }
-
- mp = jbs->resolve.job.mem_pool;
-
- jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *));
- if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) {
- return NXT_ERROR;
- }
-
- sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in),
- NXT_INET_ADDR_STR_LEN);
-
- if (nxt_fast_path(sa != NULL)) {
- jbs->resolve.count = 1;
- jbs->resolve.sockaddrs[0] = sa;
-
- jbs->wildcard = (addr == INADDR_ANY);
-
- sa->u.sockaddr_in.sin_family = AF_INET;
- sa->u.sockaddr_in.sin_port = (in_port_t) port;
- sa->u.sockaddr_in.sin_addr.s_addr = addr;
-
- return NXT_OK;
- }
-
- return NXT_ERROR;
-
-invalid_port:
-
- nxt_thread_log_error(jbs->resolve.log_level,
- "invalid port in \"%V\"", &jbs->addr);
-
- return NXT_ERROR;
-}
-
-
in_addr_t
nxt_inet_addr(u_char *buf, size_t length)
{
diff --git a/src/nxt_sockaddr.h b/src/nxt_sockaddr.h
index a8f1b393..0f96f6dd 100644
--- a/src/nxt_sockaddr.h
+++ b/src/nxt_sockaddr.h
@@ -58,15 +58,6 @@ struct nxt_sockaddr_s {
};
-typedef struct {
- nxt_job_resolve_t resolve;
- nxt_str_t addr;
-
- uint8_t wildcard; /* 1 bit */
- uint8_t no_port; /* 1 bit */
-} nxt_job_sockaddr_parse_t;
-
-
nxt_sockaddr_t *nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine,
nxt_listen_socket_t *ls);
void nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c);
@@ -88,12 +79,9 @@ NXT_EXPORT void nxt_sockaddr_text(nxt_sockaddr_t *sa);
NXT_EXPORT uint32_t nxt_sockaddr_port_number(nxt_sockaddr_t *sa);
NXT_EXPORT nxt_bool_t nxt_sockaddr_cmp(nxt_sockaddr_t *sa1,
nxt_sockaddr_t *sa2);
-NXT_EXPORT size_t nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf,
- u_char *end, nxt_bool_t port);
NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr);
NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse_optport(nxt_mp_t *mp,
nxt_str_t *addr);
-NXT_EXPORT void nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs);
NXT_EXPORT in_addr_t nxt_inet_addr(u_char *buf, size_t len);
#if (NXT_INET6)
NXT_EXPORT nxt_int_t nxt_inet6_addr(struct in6_addr *in6_addr, u_char *buf,
diff --git a/src/nxt_status.c b/src/nxt_status.c
new file mode 100644
index 00000000..f8002e86
--- /dev/null
+++ b/src/nxt_status.c
@@ -0,0 +1,105 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+#include <nxt_conf.h>
+#include <nxt_status.h>
+
+
+nxt_conf_value_t *
+nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp)
+{
+ size_t i;
+ nxt_str_t name;
+ nxt_int_t ret;
+ nxt_status_app_t *app;
+ nxt_conf_value_t *status, *obj, *apps, *app_obj;
+
+ static nxt_str_t conns_str = nxt_string("connections");
+ static nxt_str_t acc_str = nxt_string("accepted");
+ static nxt_str_t active_str = nxt_string("active");
+ static nxt_str_t idle_str = nxt_string("idle");
+ static nxt_str_t closed_str = nxt_string("closed");
+ static nxt_str_t reqs_str = nxt_string("requests");
+ static nxt_str_t total_str = nxt_string("total");
+ static nxt_str_t apps_str = nxt_string("applications");
+ static nxt_str_t procs_str = nxt_string("processes");
+ static nxt_str_t run_str = nxt_string("running");
+ static nxt_str_t start_str = nxt_string("starting");
+
+ status = nxt_conf_create_object(mp, 3);
+ if (nxt_slow_path(status == NULL)) {
+ return NULL;
+ }
+
+ obj = nxt_conf_create_object(mp, 4);
+ if (nxt_slow_path(obj == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(status, &conns_str, obj, 0);
+
+ nxt_conf_set_member_integer(obj, &acc_str, report->accepted_conns, 0);
+ nxt_conf_set_member_integer(obj, &active_str, report->accepted_conns
+ - report->closed_conns
+ - report->idle_conns, 1);
+ nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2);
+ nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3);
+
+ obj = nxt_conf_create_object(mp, 1);
+ if (nxt_slow_path(obj == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(status, &reqs_str, obj, 1);
+
+ nxt_conf_set_member_integer(obj, &total_str, report->requests, 0);
+
+ apps = nxt_conf_create_object(mp, report->apps_count);
+ if (nxt_slow_path(apps == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(status, &apps_str, apps, 2);
+
+ for (i = 0; i < report->apps_count; i++) {
+ app = &report->apps[i];
+
+ app_obj = nxt_conf_create_object(mp, 2);
+ if (nxt_slow_path(app_obj == NULL)) {
+ return NULL;
+ }
+
+ name.length = app->name.length;
+ name.start = nxt_pointer_to(report, (uintptr_t) app->name.start);
+
+ ret = nxt_conf_set_member_dup(apps, mp, &name, app_obj, i);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
+ obj = nxt_conf_create_object(mp, 3);
+ if (nxt_slow_path(obj == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(app_obj, &procs_str, obj, 0);
+
+ nxt_conf_set_member_integer(obj, &run_str, app->processes, 0);
+ nxt_conf_set_member_integer(obj, &start_str, app->pending_processes, 1);
+ nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2);
+
+ obj = nxt_conf_create_object(mp, 1);
+ if (nxt_slow_path(obj == NULL)) {
+ return NULL;
+ }
+
+ nxt_conf_set_member(app_obj, &reqs_str, obj, 1);
+
+ nxt_conf_set_member_integer(obj, &active_str, app->active_requests, 0);
+ }
+
+ return status;
+}
diff --git a/src/nxt_status.h b/src/nxt_status.h
new file mode 100644
index 00000000..a99ac7d0
--- /dev/null
+++ b/src/nxt_status.h
@@ -0,0 +1,33 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_STATUS_H_INCLUDED_
+#define _NXT_STATUS_H_INCLUDED_
+
+
+typedef struct {
+ nxt_str_t name;
+ uint32_t active_requests;
+ uint32_t pending_processes;
+ uint32_t processes;
+ uint32_t idle_processes;
+} nxt_status_app_t;
+
+
+typedef struct {
+ uint64_t accepted_conns;
+ uint64_t idle_conns;
+ uint64_t closed_conns;
+ uint64_t requests;
+
+ size_t apps_count;
+ nxt_status_app_t apps[];
+} nxt_status_report_t;
+
+
+nxt_conf_value_t *nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp);
+
+
+#endif /* _NXT_STATUS_H_INCLUDED_ */
diff --git a/src/nxt_string.c b/src/nxt_string.c
index b7aef79e..4d89c23c 100644
--- a/src/nxt_string.c
+++ b/src/nxt_string.c
@@ -338,7 +338,7 @@ nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length)
size_t
-nxt_str_strip(u_char *start, u_char *end)
+nxt_str_strip(const u_char *start, u_char *end)
{
u_char *p;
diff --git a/src/nxt_string.h b/src/nxt_string.h
index 80cdbb59..a8673c61 100644
--- a/src/nxt_string.h
+++ b/src/nxt_string.h
@@ -96,7 +96,7 @@ NXT_EXPORT u_char *nxt_memcasestrn(const u_char *s, const u_char *end,
const char *ss, size_t length);
NXT_EXPORT u_char *nxt_rmemstrn(const u_char *s, const u_char *end,
const char *ss, size_t length);
-NXT_EXPORT size_t nxt_str_strip(u_char *start, u_char *end);
+NXT_EXPORT size_t nxt_str_strip(const u_char *start, u_char *end);
typedef struct {
diff --git a/src/nxt_time_parse.c b/src/nxt_time_parse.c
index 94c43289..63620b09 100644
--- a/src/nxt_time_parse.c
+++ b/src/nxt_time_parse.c
@@ -22,7 +22,7 @@ nxt_time_parse(const u_char *p, size_t len)
nxt_uint_t year, days;
const u_char *end;
- static nxt_int_t mday[12] = {
+ static const nxt_int_t mday[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
diff --git a/src/nxt_unit.c b/src/nxt_unit.c
index 32bb07ab..e5cb0b58 100644
--- a/src/nxt_unit.c
+++ b/src/nxt_unit.c
@@ -196,7 +196,8 @@ static int nxt_unit_request_hash_add(nxt_unit_ctx_t *ctx,
static nxt_unit_request_info_t *nxt_unit_request_hash_find(
nxt_unit_ctx_t *ctx, uint32_t stream, int remove);
-static char * nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level);
+static char * nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid,
+ int level);
static void *nxt_unit_lvlhsh_alloc(void *data, size_t size);
static void nxt_unit_lvlhsh_free(void *data, void *p);
static int nxt_unit_memcasecmp(const void *p1, const void *p2, size_t length);
@@ -584,9 +585,14 @@ fail:
static nxt_unit_impl_t *
nxt_unit_create(nxt_unit_init_t *init)
{
- int rc;
- nxt_unit_impl_t *lib;
- nxt_unit_callbacks_t *cb;
+ int rc;
+ nxt_unit_impl_t *lib;
+
+ if (nxt_slow_path(init->callbacks.request_handler == NULL)) {
+ nxt_unit_alert(NULL, "request_handler is NULL");
+
+ return NULL;
+ }
lib = nxt_unit_malloc(NULL,
sizeof(nxt_unit_impl_t) + init->request_data_size);
@@ -629,15 +635,6 @@ nxt_unit_create(nxt_unit_init_t *init)
goto fail;
}
- cb = &lib->callbacks;
-
- if (cb->request_handler == NULL) {
- nxt_unit_alert(NULL, "request_handler is NULL");
-
- pthread_mutex_destroy(&lib->mutex);
- goto fail;
- }
-
nxt_unit_mmaps_init(&lib->incoming);
nxt_unit_mmaps_init(&lib->outgoing);
@@ -942,7 +939,6 @@ nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream, int queue_fd)
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
nxt_socket_msg_oob_init(&oob, fds);
@@ -2644,7 +2640,6 @@ nxt_unit_mmap_buf_send(nxt_unit_request_info_t *req,
m.msg.mmap = hdr != NULL && m.mmap_msg.size > 0;
m.msg.nf = 0;
m.msg.mf = 0;
- m.msg.tracking = 0;
rc = NXT_UNIT_ERROR;
@@ -3077,7 +3072,6 @@ nxt_unit_request_read(nxt_unit_request_info_t *req, void *dst, size_t size)
}
req->content_length -= res;
- size -= res;
dst = nxt_pointer_to(dst, res);
@@ -3296,7 +3290,6 @@ skip_response_send:
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
(void) nxt_unit_port_send(req->ctx, req->response_port,
&msg, sizeof(msg), NULL);
@@ -3619,7 +3612,6 @@ nxt_unit_send_oosm(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port)
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL);
if (nxt_slow_path(res != sizeof(msg))) {
@@ -3816,13 +3808,12 @@ static int
nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size)
{
int fd;
- nxt_unit_impl_t *lib;
-
- lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit);
#if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN)
char name[64];
+ nxt_unit_impl_t *lib;
+ lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit);
snprintf(name, sizeof(name), NXT_SHM_PREFIX "unit.%d.%p",
lib->pid, (void *) (uintptr_t) pthread_self());
#endif
@@ -3905,7 +3896,6 @@ nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, int fd)
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
nxt_socket_msg_oob_init(&oob, fds);
@@ -4390,7 +4380,6 @@ nxt_unit_send_shm_ack(nxt_unit_ctx_t *ctx, pid_t pid)
msg.mmap = 0;
msg.nf = 0;
msg.mf = 0;
- msg.tracking = 0;
res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL);
if (nxt_slow_path(res != sizeof(msg))) {
@@ -5356,7 +5345,6 @@ nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *dst,
m.msg.mmap = 0;
m.msg.nf = 0;
m.msg.mf = 0;
- m.msg.tracking = 0;
m.new_port.id = port->id.id;
m.new_port.pid = port->id.pid;
@@ -6673,7 +6661,7 @@ static const char * nxt_unit_log_levels[] = {
static char *
-nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level)
+nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, int level)
{
struct tm tm;
struct timespec ts;
diff --git a/src/nxt_unix.h b/src/nxt_unix.h
index d8eaabc3..6bc6be5e 100644
--- a/src/nxt_unix.h
+++ b/src/nxt_unix.h
@@ -156,9 +156,7 @@
#include <setjmp.h>
#include <sched.h>
#include <signal.h>
-#if (NXT_HAVE_POSIX_SPAWN)
#include <spawn.h>
-#endif
#include <stdarg.h>
#include <stddef.h> /* offsetof() */
#include <stdio.h>
diff --git a/src/nxt_var.c b/src/nxt_var.c
index 0a722d17..f55a2d30 100644
--- a/src/nxt_var.c
+++ b/src/nxt_var.c
@@ -9,7 +9,7 @@
struct nxt_var_s {
size_t length;
nxt_uint_t vars;
- uint8_t strz; /* 1 bit */
+ nxt_var_flags_t flags;
u_char data[];
/*
@@ -26,19 +26,12 @@ typedef struct {
} nxt_var_sub_t;
-typedef struct {
- nxt_var_t *var;
- nxt_str_t *value;
-} nxt_var_value_t;
-
-
struct nxt_var_query_s {
- nxt_array_t values; /* of nxt_var_value_t */
- nxt_array_t parts; /* of nxt_str_t * */
+ nxt_mp_t *pool;
nxt_lvlhsh_t cache;
-
nxt_str_t *spare;
+
nxt_uint_t waiting;
nxt_uint_t failed; /* 1 bit */
@@ -59,16 +52,18 @@ struct nxt_var_query_s {
static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name);
+static nxt_var_decl_t *nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields,
+ uint32_t *index);
+static nxt_var_field_t *nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name,
+ uint32_t hash);
+
static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data);
-static nxt_str_t *nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index);
-static nxt_int_t nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index,
- nxt_str_t *value, nxt_mp_t *mp);
+static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query,
+ uint32_t index);
static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part,
nxt_bool_t *is_var);
-static void nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query);
-
static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = {
NXT_LVLHSH_DEFAULT,
@@ -91,21 +86,6 @@ static uint32_t nxt_var_count;
static nxt_var_handler_t *nxt_var_index;
-void
-nxt_var_raw(nxt_var_t *var, nxt_str_t *str)
-{
- str->length = var->length;
- str->start = nxt_var_raw_start(var);
-}
-
-
-nxt_bool_t
-nxt_var_is_const(nxt_var_t *var)
-{
- return (var->vars == 0);
-}
-
-
static nxt_int_t
nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
{
@@ -134,46 +114,166 @@ nxt_var_hash_find(nxt_str_t *name)
}
-static nxt_int_t
-nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data)
+static nxt_var_decl_t *
+nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, uint32_t *index)
{
- return NXT_OK;
+ u_char *p, *end;
+ int64_t hash;
+ uint16_t field;
+ nxt_str_t str;
+ nxt_var_decl_t *decl;
+ nxt_var_field_t *f;
+
+ f = NULL;
+ field = 0;
+ decl = nxt_var_hash_find(name);
+
+ if (decl == NULL) {
+ p = name->start;
+ end = p + name->length;
+
+ while (p < end) {
+ if (*p++ == '_') {
+ break;
+ }
+ }
+
+ if (p == end) {
+ return NULL;
+ }
+
+ str.start = name->start;
+ str.length = p - 1 - name->start;
+
+ decl = nxt_var_hash_find(&str);
+
+ if (decl != NULL) {
+ str.start = p;
+ str.length = end - p;
+
+ hash = decl->field_hash(fields->mem_pool, &str);
+ if (nxt_slow_path(hash == -1)) {
+ return NULL;
+ }
+
+ f = nxt_var_field_add(fields, &str, (uint32_t) hash);
+ if (nxt_slow_path(f == NULL)) {
+ return NULL;
+ }
+
+ field = f->index;
+ }
+ }
+
+ if (decl != NULL) {
+ if (decl->field_hash != NULL && f == NULL) {
+ return NULL;
+ }
+
+ if (index != NULL) {
+ *index = (decl->index << 16) | field;
+ }
+ }
+
+ return decl;
}
-static nxt_str_t *
-nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index)
+static nxt_var_field_t *
+nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, uint32_t hash)
{
- nxt_lvlhsh_query_t lhq;
+ nxt_uint_t i;
+ nxt_var_field_t *field;
- lhq.key_hash = nxt_murmur_hash2_uint32(&index);
- lhq.key.length = sizeof(uint32_t);
- lhq.key.start = (u_char *) &index;
- lhq.proto = &nxt_var_cache_proto;
+ field = fields->elts;
- if (nxt_lvlhsh_find(lh, &lhq) != NXT_OK) {
+ for (i = 0; i < fields->nelts; i++) {
+ if (field[i].hash == hash
+ && nxt_strstr_eq(&field[i].name, name))
+ {
+ return field;
+ }
+ }
+
+ field = nxt_array_add(fields);
+ if (nxt_slow_path(field == NULL)) {
return NULL;
}
- return lhq.value;
+ field->name = *name;
+ field->hash = hash;
+ field->index = fields->nelts - 1;
+
+ return field;
+}
+
+
+nxt_var_field_t *
+nxt_var_field_get(nxt_array_t *fields, uint16_t index)
+{
+ nxt_uint_t nfields;
+ nxt_var_field_t *field;
+
+ field = fields->elts;
+ nfields = fields->nelts;
+
+ if (nfields > 0 && index <= nfields) {
+ return &field[index];
+ }
+
+ return NULL;
}
static nxt_int_t
-nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value,
- nxt_mp_t *mp)
+nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data)
{
+ return NXT_OK;
+}
+
+
+static nxt_str_t *
+nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index)
+{
+ nxt_int_t ret;
+ nxt_str_t *value;
nxt_lvlhsh_query_t lhq;
+ value = query->spare;
+
+ if (value == NULL) {
+ value = nxt_mp_zget(query->pool, sizeof(nxt_str_t));
+ if (nxt_slow_path(value == NULL)) {
+ return NULL;
+ }
+
+ query->spare = value;
+ }
+
lhq.key_hash = nxt_murmur_hash2_uint32(&index);
lhq.replace = 0;
lhq.key.length = sizeof(uint32_t);
lhq.key.start = (u_char *) &index;
lhq.value = value;
lhq.proto = &nxt_var_cache_proto;
- lhq.pool = mp;
+ lhq.pool = query->pool;
- return nxt_lvlhsh_insert(lh, &lhq);
+ ret = nxt_lvlhsh_insert(&query->cache, &lhq);
+ if (nxt_slow_path(ret == NXT_ERROR)) {
+ return NULL;
+ }
+
+ if (ret == NXT_OK) {
+ ret = nxt_var_index[index >> 16](task, value, query->ctx,
+ index & 0xffff);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
+ query->spare = NULL;
+ }
+
+ return lhq.value;
}
@@ -230,10 +330,13 @@ nxt_var_index_init(void)
nxt_var_t *
-nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
+nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields,
+ nxt_var_flags_t flags)
{
u_char *p, *end, *next, *src;
size_t size;
+ uint32_t index;
+ nxt_bool_t strz;
nxt_var_t *var;
nxt_str_t part;
nxt_uint_t n;
@@ -241,6 +344,8 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
nxt_var_sub_t *subs;
nxt_var_decl_t *decl;
+ strz = (flags & NXT_VAR_STRZ) != 0;
+
n = 0;
p = str->start;
@@ -266,7 +371,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
var->length = str->length;
var->vars = n;
- var->strz = strz;
+ var->flags = flags;
subs = nxt_var_subs(var);
src = nxt_var_raw_start(var);
@@ -284,12 +389,12 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
next = nxt_var_next_part(p, end - p, &part, &is_var);
if (is_var) {
- decl = nxt_var_hash_find(&part);
+ decl = nxt_var_decl_get(&part, fields, &index);
if (nxt_slow_path(decl == NULL)) {
return NULL;
}
- subs[n].index = decl->index;
+ subs[n].index = index;
subs[n].length = next - p;
subs[n].position = p - str->start;
@@ -304,7 +409,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz)
nxt_int_t
-nxt_var_test(nxt_str_t *str, u_char *error)
+nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error)
{
u_char *p, *end, *next;
nxt_str_t part;
@@ -325,7 +430,7 @@ nxt_var_test(nxt_str_t *str, u_char *error)
}
if (is_var) {
- decl = nxt_var_hash_find(&part);
+ decl = nxt_var_decl_get(&part, fields, NULL);
if (decl == NULL) {
nxt_sprintf(error, error + NXT_MAX_ERROR_STR,
@@ -420,6 +525,21 @@ nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part,
}
+inline void
+nxt_var_raw(nxt_var_t *var, nxt_str_t *str)
+{
+ str->length = var->length;
+ str->start = nxt_var_raw_start(var);
+}
+
+
+inline nxt_bool_t
+nxt_var_is_const(nxt_var_t *var)
+{
+ return (var->vars == 0);
+}
+
+
nxt_int_t
nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp)
{
@@ -432,14 +552,9 @@ nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp)
if (nxt_slow_path(query == NULL)) {
return NXT_ERROR;
}
-
- nxt_array_init(&query->values, mp, sizeof(nxt_var_value_t));
- nxt_array_init(&query->parts, mp, sizeof(nxt_str_t *));
-
- } else {
- nxt_array_reset(&query->values);
}
+ query->pool = mp;
query->ctx = ctx;
*query_p = query;
@@ -452,13 +567,13 @@ void
nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var,
nxt_str_t *str)
{
- uint32_t index;
- nxt_mp_t *mp;
- nxt_str_t *value;
- nxt_int_t ret;
- nxt_uint_t i;
- nxt_var_sub_t *subs;
- nxt_var_value_t *val;
+ u_char *p, *src;
+ size_t length, last, next;
+ nxt_str_t *value, **part;
+ nxt_uint_t i;
+ nxt_bool_t strz, logging;
+ nxt_array_t parts;
+ nxt_var_sub_t *subs;
if (nxt_var_is_const(var)) {
nxt_var_raw(var, str);
@@ -469,53 +584,74 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var,
return;
}
- mp = query->values.mem_pool;
+ nxt_memzero(&parts, sizeof(nxt_array_t));
+ nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *));
+
+ strz = (var->flags & NXT_VAR_STRZ) != 0;
+ logging = (var->flags & NXT_VAR_LOGGING) != 0;
+
subs = nxt_var_subs(var);
- value = query->spare;
- for (i = 0; i < var->vars; i++) {
+ length = var->length;
- if (value == NULL) {
- value = nxt_mp_zget(mp, sizeof(nxt_str_t));
- if (nxt_slow_path(value == NULL)) {
- goto fail;
- }
+ for (i = 0; i < var->vars; i++) {
+ value = nxt_var_cache_value(task, query, subs[i].index);
+ if (nxt_slow_path(value == NULL)) {
+ goto fail;
}
- index = subs[i].index;
+ part = nxt_array_add(&parts);
+ if (nxt_slow_path(part == NULL)) {
+ goto fail;
+ }
- ret = nxt_var_cache_add(&query->cache, index, value, mp);
+ *part = value;
- if (ret != NXT_OK) {
- if (nxt_slow_path(ret == NXT_ERROR)) {
- goto fail;
- }
+ length += value->length - subs[i].length;
- continue; /* NXT_DECLINED */
+ if (logging && value->start == NULL) {
+ length += 1;
}
+ }
- ret = nxt_var_index[index](task, query, value, query->ctx);
+ p = nxt_mp_nget(query->pool, length + strz);
+ if (nxt_slow_path(p == NULL)) {
+ goto fail;
+ }
- value = NULL;
+ str->length = length;
+ str->start = p;
- if (ret != NXT_OK) {
- if (nxt_slow_path(ret != NXT_AGAIN)) {
- goto fail;
- }
+ part = parts.elts;
+ src = nxt_var_raw_start(var);
+
+ last = 0;
- query->waiting++;
+ for (i = 0; i < var->vars; i++) {
+ next = subs[i].position;
+
+ if (next != last) {
+ p = nxt_cpymem(p, &src[last], next - last);
}
+
+ p = nxt_cpymem(p, part[i]->start, part[i]->length);
+
+ if (logging && part[i]->start == NULL) {
+ *p++ = '-';
+ }
+
+ last = next + subs[i].length;
}
- query->spare = value;
+ if (last != var->length) {
+ p = nxt_cpymem(p, &src[last], var->length - last);
+ }
- val = nxt_array_add(&query->values);
- if (nxt_slow_path(val == NULL)) {
- goto fail;
+ if (strz) {
+ *p = '\0';
}
- val->var = var;
- val->value = str;
+ nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str);
return;
@@ -534,7 +670,9 @@ nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data,
query->error = error;
if (query->waiting == 0) {
- nxt_var_query_finish(task, query);
+ nxt_work_queue_add(&task->thread->engine->fast_work_queue,
+ query->failed ? query->error : query->ready,
+ task, query->ctx, query->data);
}
}
@@ -546,94 +684,8 @@ nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query,
query->failed |= failed;
if (--query->waiting == 0) {
- nxt_var_query_finish(task, query);
- }
-}
-
-
-static void
-nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query)
-{
- u_char *p, *src;
- size_t length, last, next;
- nxt_str_t *str, **part;
- nxt_var_t *var;
- nxt_uint_t i, j;
- nxt_var_sub_t *subs;
- nxt_var_value_t *val;
-
- if (query->failed) {
- goto done;
+ nxt_work_queue_add(&task->thread->engine->fast_work_queue,
+ query->failed ? query->error : query->ready,
+ task, query->ctx, query->data);
}
-
- val = query->values.elts;
-
- for (i = 0; i < query->values.nelts; i++) {
- var = val[i].var;
-
- subs = nxt_var_subs(var);
- length = var->length;
-
- for (j = 0; j < var->vars; j++) {
- str = nxt_var_cache_find(&query->cache, subs[j].index);
-
- nxt_assert(str != NULL);
-
- part = nxt_array_add(&query->parts);
-
- if (nxt_slow_path(part == NULL)) {
- query->failed = 1;
- goto done;
- }
-
- *part = str;
-
- length += str->length - subs[j].length;
- }
-
- p = nxt_mp_nget(query->values.mem_pool, length + var->strz);
- if (nxt_slow_path(p == NULL)) {
- query->failed = 1;
- goto done;
- }
-
- val[i].value->length = length;
- val[i].value->start = p;
-
- part = query->parts.elts;
- src = nxt_var_raw_start(var);
-
- last = 0;
-
- for (j = 0; j < var->vars; j++) {
- next = subs[j].position;
-
- if (next != last) {
- p = nxt_cpymem(p, &src[last], next - last);
- }
-
- p = nxt_cpymem(p, part[j]->start, part[j]->length);
-
- last = next + subs[j].length;
- }
-
- if (last != var->length) {
- p = nxt_cpymem(p, &src[last], var->length - last);
- }
-
- if (var->strz) {
- *p = '\0';
- }
-
- nxt_array_reset(&query->parts);
-
- nxt_debug(task, "var: \"%*s\" -> \"%V\"", var->length, src,
- val[i].value);
- }
-
-done:
-
- nxt_work_queue_add(&task->thread->engine->fast_work_queue,
- query->failed ? query->error : query->ready,
- task, query->ctx, query->data);
}
diff --git a/src/nxt_var.h b/src/nxt_var.h
index 3b7d0c28..cc7ff502 100644
--- a/src/nxt_var.h
+++ b/src/nxt_var.h
@@ -12,17 +12,32 @@ typedef struct nxt_var_query_s nxt_var_query_t;
typedef nxt_int_t (*nxt_var_handler_t)(nxt_task_t *task,
- nxt_var_query_t *query,
nxt_str_t *str,
- void *ctx);
+ void *ctx, uint16_t field);
+
+typedef int64_t (*nxt_var_field_hash_t)(nxt_mp_t *mp, nxt_str_t *str);
typedef struct {
- nxt_str_t name;
- nxt_var_handler_t handler;
- uint32_t index;
+ nxt_str_t name;
+ nxt_var_handler_t handler;
+ nxt_var_field_hash_t field_hash;
+ uint32_t index;
} nxt_var_decl_t;
+typedef struct {
+ nxt_str_t name;
+ uint16_t hash;
+ uint32_t index;
+} nxt_var_field_t;
+
+
+typedef enum {
+ NXT_VAR_STRZ = 1 << 0,
+ NXT_VAR_LOGGING = 1 << 1,
+} nxt_var_flags_t;
+
+
nxt_inline nxt_bool_t
nxt_is_var(nxt_str_t *str)
{
@@ -30,13 +45,17 @@ nxt_is_var(nxt_str_t *str)
}
-void nxt_var_raw(nxt_var_t *var, nxt_str_t *str);
-nxt_bool_t nxt_var_is_const(nxt_var_t *var);
-
nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n);
nxt_int_t nxt_var_index_init(void);
-nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz);
-nxt_int_t nxt_var_test(nxt_str_t *str, u_char *error);
+
+nxt_var_field_t *nxt_var_field_get(nxt_array_t *fields, uint16_t index);
+
+nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields,
+ nxt_var_flags_t flags);
+nxt_int_t nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error);
+
+nxt_bool_t nxt_var_is_const(nxt_var_t *var);
+void nxt_var_raw(nxt_var_t *var, nxt_str_t *str);
nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx,
nxt_mp_t *mp);
diff --git a/src/nxt_websocket_accept.c b/src/nxt_websocket_accept.c
index 05cbcb56..0e2cef58 100644
--- a/src/nxt_websocket_accept.c
+++ b/src/nxt_websocket_accept.c
@@ -11,8 +11,8 @@
static void
nxt_websocket_base64_encode(u_char *d, const uint8_t *s, size_t len)
{
- u_char c0, c1, c2;
- static u_char basis[] =
+ u_char c0, c1, c2;
+ static const u_char basis[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
while (len > 2) {
diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c
index 91af8f4b..4ad0857d 100644
--- a/src/python/nxt_python_asgi.c
+++ b/src/python/nxt_python_asgi.c
@@ -30,6 +30,8 @@ static void nxt_py_asgi_close_handler(nxt_unit_request_info_t *req);
static PyObject *nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req);
static PyObject *nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len,
uint16_t port);
+static PyObject *nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr,
+ uint8_t len, uint16_t port);
static PyObject *nxt_py_asgi_create_header(nxt_unit_field_t *f);
static PyObject *nxt_py_asgi_create_subprotocols(nxt_unit_field_t *f);
@@ -736,6 +738,48 @@ fail:
static PyObject *
nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port)
{
+ size_t prefix_len;
+ nxt_str_t addr;
+ PyObject *pair, *v;
+
+ addr.length = len;
+ addr.start = nxt_unit_sptr_get(sptr);
+
+ prefix_len = nxt_length("unix:");
+ if (!nxt_str_start(&addr, "unix:", prefix_len)) {
+ return nxt_py_asgi_create_ip_address(sptr, len, port);
+ }
+
+#if NXT_HAVE_UNIX_DOMAIN
+ pair = PyTuple_New(2);
+ if (nxt_slow_path(pair == NULL)) {
+ return NULL;
+ }
+
+ addr.start += prefix_len;
+ addr.length -= prefix_len;
+
+ v = PyString_FromStringAndSize((const char *) addr.start, addr.length);
+ if (nxt_slow_path(v == NULL)) {
+ Py_DECREF(pair);
+
+ return NULL;
+ }
+
+ PyTuple_SET_ITEM(pair, 0, v);
+ PyTuple_SET_ITEM(pair, 1, Py_None);
+
+ return pair;
+
+#else
+ return NULL;
+#endif
+}
+
+
+static PyObject *
+nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port)
+{
char *p, *s;
PyObject *pair, *v;
diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c
index 8f4afd35..f316d8a5 100644
--- a/src/ruby/nxt_ruby.c
+++ b/src/ruby/nxt_ruby.c
@@ -29,7 +29,6 @@ typedef struct {
static nxt_int_t nxt_ruby_start(nxt_task_t *task,
nxt_process_data_t *data);
static VALUE nxt_ruby_init_basic(VALUE arg);
-static VALUE nxt_ruby_script_basename(nxt_str_t *script);
static VALUE nxt_ruby_hook_procs_load(VALUE path);
static VALUE nxt_ruby_hook_register(VALUE arg);
@@ -50,7 +49,7 @@ static void *nxt_ruby_thread_create_gvl(void *rctx);
static VALUE nxt_ruby_thread_func(VALUE arg);
static void *nxt_ruby_unit_run(void *ctx);
static void nxt_ruby_ubf(void *ctx);
-static int nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c);
+static int nxt_ruby_init_threads(nxt_ruby_app_conf_t *c);
static void nxt_ruby_join_threads(nxt_unit_ctx_t *ctx,
nxt_ruby_app_conf_t *c);
@@ -261,7 +260,7 @@ static nxt_int_t
nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
{
int state, rc;
- VALUE res, path, script;
+ VALUE res, path;
nxt_ruby_ctx_t ruby_ctx;
nxt_unit_ctx_t *unit_ctx;
nxt_unit_init_t ruby_unit_init;
@@ -271,6 +270,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
static char *argv[2] = { (char *) "NGINX_Unit", (char *) "-e0" };
+ signal(SIGINT, SIG_IGN);
+
conf = data->app;
c = &conf->u.ruby;
@@ -283,10 +284,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
ruby_options(2, argv);
ruby_script("NGINX_Unit");
- script = nxt_ruby_script_basename(&c->script);
-
ruby_ctx.env = Qnil;
- ruby_ctx.script = script;
ruby_ctx.io_input = Qnil;
ruby_ctx.io_error = Qnil;
ruby_ctx.thread = Qnil;
@@ -356,7 +354,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
goto fail;
}
- rc = nxt_ruby_init_threads(script, c);
+ rc = nxt_ruby_init_threads(c);
if (nxt_slow_path(rc == NXT_UNIT_ERROR)) {
goto fail;
}
@@ -381,8 +379,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
}
}
- rc = (intptr_t) rb_thread_call_without_gvl(nxt_ruby_unit_run, unit_ctx,
- nxt_ruby_ubf, unit_ctx);
+ rc = (intptr_t) rb_thread_call_without_gvl2(nxt_ruby_unit_run, unit_ctx,
+ nxt_ruby_ubf, unit_ctx);
if (nxt_ruby_hook_procs != Qnil) {
rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_shutdown, &state);
@@ -425,37 +423,6 @@ fail:
static VALUE
-nxt_ruby_script_basename(nxt_str_t *script)
-{
- size_t len;
- u_char *p, *last;
-
- last = NULL;
- p = script->start + script->length;
-
- while (p > script->start) {
-
- if (p[-1] == '/') {
- last = p;
- break;
- }
-
- p--;
- }
-
- if (last != NULL) {
- len = script->length - (last - script->start);
-
- } else {
- last = script->start;
- len = script->length;
- }
-
- return rb_str_new((const char *) last, len);
-}
-
-
-static VALUE
nxt_ruby_init_basic(VALUE arg)
{
int state;
@@ -598,7 +565,7 @@ nxt_ruby_rack_env_create(VALUE arg)
rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MAJOR));
rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MINOR));
- rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rctx->script);
+ rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rb_str_new("", 0));
rb_hash_aset(hash_env, rb_str_new2("rack.version"), version);
rb_hash_aset(hash_env, rb_str_new2("rack.input"), rctx->io_input);
rb_hash_aset(hash_env, rb_str_new2("rack.errors"), rctx->io_error);
@@ -1393,7 +1360,7 @@ nxt_ruby_ubf(void *ctx)
static int
-nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c)
+nxt_ruby_init_threads(nxt_ruby_app_conf_t *c)
{
int state;
uint32_t i;
@@ -1415,7 +1382,6 @@ nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c)
rctx = &nxt_ruby_ctxs[i];
rctx->env = Qnil;
- rctx->script = script;
rctx->io_input = Qnil;
rctx->io_error = Qnil;
rctx->thread = Qnil;
diff --git a/src/ruby/nxt_ruby.h b/src/ruby/nxt_ruby.h
index 3bdd567a..26430021 100644
--- a/src/ruby/nxt_ruby.h
+++ b/src/ruby/nxt_ruby.h
@@ -22,7 +22,6 @@
typedef struct {
VALUE env;
- VALUE script;
VALUE io_input;
VALUE io_error;
VALUE thread;
diff --git a/test/conftest.py b/test/conftest.py
index 904abc32..18851baa 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -20,9 +20,11 @@ from unit.check.isolation import check_isolation
from unit.check.node import check_node
from unit.check.regex import check_regex
from unit.check.tls import check_openssl
+from unit.check.unix_abstract import check_unix_abstract
from unit.http import TestHTTP
from unit.log import Log
from unit.option import option
+from unit.status import Status
from unit.utils import public_dir
from unit.utils import waitforfiles
@@ -213,6 +215,7 @@ def pytest_sessionstart(session):
check_chroot()
check_isolation()
+ check_unix_abstract()
_clear_conf(unit['temp_dir'] + '/control.unit.sock')
@@ -427,6 +430,8 @@ def unit_run(state_dir=None):
controller['pid'] = pid_by_name(controller['name'])
controller['fds'] = _count_fds(controller['pid'])
+ Status._check_zeros()
+
return unit_instance
diff --git a/test/python/ctx_iter_atexit/wsgi.py b/test/python/ctx_iter_atexit/wsgi.py
index b2f12c35..75d40895 100644
--- a/test/python/ctx_iter_atexit/wsgi.py
+++ b/test/python/ctx_iter_atexit/wsgi.py
@@ -15,7 +15,6 @@ class application:
self.start(
'200',
[
- ('Content-Type', self.environ.get('CONTENT_TYPE')),
('Content-Length', str(len(body))),
],
)
diff --git a/test/python/forwarded_header/wsgi.py b/test/python/forwarded_header/wsgi.py
new file mode 100644
index 00000000..44d370ab
--- /dev/null
+++ b/test/python/forwarded_header/wsgi.py
@@ -0,0 +1,10 @@
+def application(env, start_response):
+ start_response(
+ '200',
+ [
+ ('Content-Length', '0'),
+ ('Remote-Addr', env.get('REMOTE_ADDR')),
+ ('Url-Scheme', env.get('wsgi.url_scheme')),
+ ],
+ )
+ return []
diff --git a/test/test_access_log.py b/test/test_access_log.py
index 5d242a1a..b1d89343 100644
--- a/test/test_access_log.py
+++ b/test/test_access_log.py
@@ -15,6 +15,15 @@ class TestAccessLog(TestApplicationPython):
'"' + option.temp_dir + '/access.log"', 'access_log'
), 'access_log configure'
+ def set_format(self, format):
+ assert 'success' in self.conf(
+ {
+ 'path': option.temp_dir + '/access.log',
+ 'format': format,
+ },
+ 'access_log',
+ ), 'access_log format'
+
def wait_for_record(self, pattern, name='access.log'):
return super().wait_for_record(pattern, name)
@@ -27,7 +36,6 @@ class TestAccessLog(TestApplicationPython):
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body='01234',
@@ -38,15 +46,7 @@ class TestAccessLog(TestApplicationPython):
self.wait_for_record(r'"POST / HTTP/1.1" 200 5') is not None
), 'keepalive 1'
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=sock,
- body='0123456789',
- )
+ resp = self.post(sock=sock, body='0123456789')
assert (
self.wait_for_record(r'"POST / HTTP/1.1" 200 10') is not None
@@ -263,3 +263,65 @@ Connection: close
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log')
is not None
), 'change'
+
+ def test_access_log_format(self):
+ self.load('empty')
+
+ def check_format(format, expect, url='/'):
+ self.set_format(format)
+
+ assert self.get(url=url)['status'] == 200
+ assert self.wait_for_record(expect) is not None, 'found'
+
+ format = 'BLAH\t0123456789'
+ check_format(format, format)
+ check_format('$uri $status $uri $status', '/ 200 / 200')
+
+ def test_access_log_variables(self):
+ self.load('mirror')
+
+ # $time_local
+
+ self.set_format('$uri $time_local $uri')
+ assert self.get(url='/time_local')['status'] == 200
+ assert self.wait_for_record('/time_local') is not None, 'time log'
+ date = self.search_in_log(
+ r'^\/time_local (.*) \/time_local$', 'access.log'
+ )[1]
+ assert (
+ abs(
+ self.date_to_sec_epoch(date, '%d/%b/%Y:%X %z')
+ - time.mktime(time.localtime())
+ )
+ < 5
+ ), '$time_local'
+
+ # $request_line
+
+ self.set_format('$request_line')
+ assert self.get(url='/r_line')['status'] == 200
+ assert self.wait_for_record(r'^GET \/r_line HTTP\/1\.1$') is not None
+
+ # $body_bytes_sent
+
+ self.set_format('$uri $body_bytes_sent')
+ body = '0123456789' * 50
+ self.post(url='/bbs', body=body, read_timeout=1)
+ assert (
+ self.wait_for_record(r'^\/bbs ' + str(len(body)) + r'$') is not None
+ ), '$body_bytes_sent'
+
+ def test_access_log_incorrect(self, skip_alert):
+ skip_alert(r'failed to apply new conf')
+
+ assert 'error' in self.conf(
+ option.temp_dir + '/blah/access.log' 'access_log/path',
+ ), 'access_log path incorrect'
+
+ assert 'error' in self.conf(
+ {
+ 'path': option.temp_dir + '/access.log',
+ 'format': '$remote_add',
+ },
+ 'access_log',
+ ), 'access_log format incorrect'
diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py
index 60fcffc1..34dfe18e 100644
--- a/test/test_asgi_application.py
+++ b/test/test_asgi_application.py
@@ -60,6 +60,16 @@ custom-header: BLAH
}, 'headers'
assert resp['body'] == body, 'body'
+ def test_asgi_application_unix(self, temp_dir):
+ self.load('empty')
+
+ addr = temp_dir + '/sock'
+ assert 'success' in self.conf(
+ {"unix:" + addr: {"pass": "applications/empty"}}, 'listeners'
+ )
+
+ assert self.get(sock_type='unix', addr=addr)['status'] == 200
+
def test_asgi_application_query_string(self):
self.load('query_string')
@@ -150,15 +160,7 @@ custom-header: BLAH
assert self.get()['status'] == 200, 'init'
body = '0123456789AB' * 1024 * 1024 # 12 Mb
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- body=body,
- read_buffer_size=1024 * 1024,
- )
+ resp = self.post(body=body, read_buffer_size=1024 * 1024)
assert resp['body'] == body, 'keep-alive 1'
@@ -172,7 +174,6 @@ custom-header: BLAH
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -182,15 +183,7 @@ custom-header: BLAH
assert resp['body'] == body, 'keep-alive 1'
body = '0123456789'
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=sock,
- body=body,
- )
+ resp = self.post(sock=sock, body=body)
assert resp['body'] == body, 'keep-alive 2'
@@ -208,7 +201,6 @@ custom-header: BLAH
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -226,7 +218,6 @@ custom-header: BLAH
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
sock=socks[i],
@@ -239,15 +230,7 @@ custom-header: BLAH
self.load('mirror', processes=i + 1)
for i in range(conns):
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=socks[i],
- body=body,
- )
+ resp = self.post(sock=socks[i], body=body)
assert resp['body'] == body, 'keep-alive close'
@@ -264,7 +247,6 @@ custom-header: BLAH
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -277,16 +259,7 @@ custom-header: BLAH
assert self.get()['status'] == 200, 'init'
- (resp, sock) = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- start=True,
- sock=sock,
- body=body,
- )
+ (resp, sock) = self.post(start=True, sock=sock, body=body)
assert resp['status'] == 200, 'reconfigure 2 keep-alive 2'
assert resp['body'] == '', 'reconfigure 2 keep-alive 2 body'
diff --git a/test/test_asgi_application_unix_abstract.py b/test/test_asgi_application_unix_abstract.py
new file mode 100644
index 00000000..c4ec812f
--- /dev/null
+++ b/test/test_asgi_application_unix_abstract.py
@@ -0,0 +1,23 @@
+from packaging import version
+from unit.applications.lang.python import TestApplicationPython
+
+
+class TestASGIApplicationUnixAbstract(TestApplicationPython):
+ prerequisites = {
+ 'modules': {
+ 'python': lambda v: version.parse(v) >= version.parse('3.5')
+ },
+ 'features': ['unix_abstract'],
+ }
+ load_module = 'asgi'
+
+ def test_asgi_application_unix_abstract(self):
+ self.load('empty')
+
+ addr = '\0sock'
+ assert 'success' in self.conf(
+ {"unix:@" + addr[1:]: {"pass": "applications/empty"}},
+ 'listeners',
+ )
+
+ assert self.get(sock_type='unix', addr=addr)['status'] == 200
diff --git a/test/test_client_ip.py b/test/test_client_ip.py
index 53e52201..50aa6afc 100644
--- a/test/test_client_ip.py
+++ b/test/test_client_ip.py
@@ -1,4 +1,5 @@
from unit.applications.lang.python import TestApplicationPython
+from unit.option import option
class TestClientIP(TestApplicationPython):
@@ -15,15 +16,27 @@ class TestClientIP(TestApplicationPython):
"client_ip": options,
"pass": "applications/client_ip",
},
+ "unix:"
+ + option.temp_dir
+ + "/sock": {
+ "client_ip": options,
+ "pass": "applications/client_ip",
+ },
},
'listeners',
), 'listeners configure'
def get_xff(self, xff, sock_type='ipv4'):
- port = 7081 if sock_type == 'ipv4' else 7082
+ address = {
+ 'ipv4': ('127.0.0.1', 7081),
+ 'ipv6': ('::1', 7082),
+ 'unix': (option.temp_dir + '/sock', None),
+ }
+ (addr, port) = address[sock_type]
return self.get(
sock_type=sock_type,
+ addr=addr,
port=port,
headers={'Connection': 'close', 'X-Forwarded-For': xff},
)['body']
@@ -31,7 +44,7 @@ class TestClientIP(TestApplicationPython):
def setup_method(self):
self.load('client_ip')
- def test_settings_client_ip_single_ip(self):
+ def test_client_ip_single_ip(self):
self.client_ip(
{'header': 'X-Forwarded-For', 'source': '123.123.123.123'}
)
@@ -59,7 +72,7 @@ class TestClientIP(TestApplicationPython):
assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source 3'
assert self.get_xff('1.1.1.1', 'ipv6') == '1.1.1.1', 'replace 2'
- def test_settings_client_ip_ipv4(self):
+ def test_client_ip_ipv4(self):
self.client_ip({'header': 'X-Forwarded-For', 'source': '127.0.0.1'})
assert (
@@ -72,7 +85,7 @@ class TestClientIP(TestApplicationPython):
self.get_xff(['8.8.8.8', '127.0.0.1, 10.0.1.1']) == '10.0.1.1'
), 'xff replace multi'
- def test_settings_client_ip_ipv6(self):
+ def test_client_ip_ipv6(self):
self.client_ip({'header': 'X-Forwarded-For', 'source': '::1'})
assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4'
@@ -85,7 +98,19 @@ class TestClientIP(TestApplicationPython):
]:
assert self.get_xff(ip, 'ipv6') == ip, 'replace'
- def test_settings_client_ip_recursive(self):
+ def test_client_ip_unix(self, temp_dir):
+ self.client_ip({'header': 'X-Forwarded-For', 'source': 'unix'})
+
+ assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4'
+ assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6'
+
+ for ip in [
+ '1.1.1.1',
+ '::11.22.33.44',
+ ]:
+ assert self.get_xff(ip, 'unix') == ip, 'replace'
+
+ def test_client_ip_recursive(self):
self.client_ip(
{
'header': 'X-Forwarded-For',
@@ -118,20 +143,41 @@ class TestClientIP(TestApplicationPython):
== '2001:db8:3c4d:15::1a2f:1a2b'
), 'xff chain ipv6'
- def test_settings_client_ip_invalid(self):
- assert 'error' in self.conf(
- {
- "http": {
- "client_ip": {'header': 'X-Forwarded-For', 'source': []}
- }
- },
- 'settings',
- ), 'empty array source'
+ def test_client_ip_case_insensitive(self):
+ self.client_ip({'header': 'x-forwarded-for', 'source': '127.0.0.1'})
+
+ assert self.get_xff('1.1.1.1') == '1.1.1.1', 'case insensitive'
+
+ def test_client_ip_empty_source(self):
+ self.client_ip({'header': 'X-Forwarded-For', 'source': []})
+
+ assert self.get_xff('1.1.1.1') == '127.0.0.1', 'empty source'
+
+ def test_client_ip_invalid(self):
assert 'error' in self.conf(
{
- "http": {
- "client_ip": {'header': 'X-Forwarded-For', 'source': 'a'}
+ "127.0.0.1:7081": {
+ "client_ip": {"source": '127.0.0.1'},
+ "pass": "applications/client_ip",
}
},
- 'settings',
- ), 'empty source invalid'
+ 'listeners',
+ ), 'invalid header'
+
+ def check_invalid_source(source):
+ assert 'error' in self.conf(
+ {
+ "127.0.0.1:7081": {
+ "client_ip": {
+ "header": "X-Forwarded-For",
+ "source": source,
+ },
+ "pass": "applications/client_ip",
+ }
+ },
+ 'listeners',
+ ), 'invalid source'
+
+ check_invalid_source(None)
+ check_invalid_source('a')
+ check_invalid_source(['a'])
diff --git a/test/test_configuration.py b/test/test_configuration.py
index 4a9d9840..7c612db0 100644
--- a/test/test_configuration.py
+++ b/test/test_configuration.py
@@ -2,6 +2,7 @@ import socket
import pytest
from unit.control import TestControl
+from unit.option import option
class TestConfiguration(TestControl):
@@ -226,6 +227,15 @@ class TestConfiguration(TestControl):
{"*:7080": {"pass": "applications/app"}}, 'listeners'
), 'listeners no app'
+ def test_listeners_unix_abstract(self):
+ if option.system != 'Linux':
+ assert 'error' in self.try_addr("unix:@sock"), 'abstract at'
+
+ pytest.skip('not yet')
+
+ assert 'error' in self.try_addr("unix:\0soc"), 'abstract \0'
+ assert 'error' in self.try_addr("unix:\u0000soc"), 'abstract \0 unicode'
+
def test_listeners_addr(self):
assert 'success' in self.try_addr("*:7080"), 'wildcard'
assert 'success' in self.try_addr("127.0.0.1:7081"), 'explicit'
diff --git a/test/test_forwarded_header.py b/test/test_forwarded_header.py
new file mode 100644
index 00000000..eb2f25f8
--- /dev/null
+++ b/test/test_forwarded_header.py
@@ -0,0 +1,266 @@
+from unit.applications.lang.python import TestApplicationPython
+
+
+class TestForwardedHeader(TestApplicationPython):
+ prerequisites = {'modules': {'python': 'any'}}
+
+ def forwarded_header(self, forwarded):
+ assert 'success' in self.conf(
+ {
+ "127.0.0.1:7081": {
+ "forwarded": forwarded,
+ "pass": "applications/forwarded_header",
+ },
+ "[::1]:7082": {
+ "forwarded": forwarded,
+ "pass": "applications/forwarded_header",
+ },
+ },
+ 'listeners',
+ ), 'listeners configure'
+
+ def get_fwd(self, sock_type='ipv4', xff=None, xfp=None):
+ port = 7081 if sock_type == 'ipv4' else 7082
+
+ headers = {'Connection': 'close'}
+
+ if xff is not None:
+ headers['X-Forwarded-For'] = xff
+
+ if xfp is not None:
+ headers['X-Forwarded-Proto'] = xfp
+
+ return self.get(sock_type=sock_type, port=port, headers=headers)[
+ 'headers'
+ ]
+
+ def get_addr(self, *args, **kwargs):
+ return self.get_fwd(*args, **kwargs)['Remote-Addr']
+
+ def get_scheme(self, *args, **kwargs):
+ return self.get_fwd(*args, **kwargs)['Url-Scheme']
+
+ def setup_method(self):
+ self.load('forwarded_header')
+
+ def test_forwarded_header_single_ip(self):
+ self.forwarded_header(
+ {
+ 'client_ip': 'X-Forwarded-For',
+ 'protocol': 'X-Forwarded-Proto',
+ 'source': '123.123.123.123',
+ }
+ )
+
+ resp = self.get_fwd(xff='1.1.1.1', xfp='https')
+ assert resp['Remote-Addr'] == '127.0.0.1', 'both headers addr'
+ assert resp['Url-Scheme'] == 'http', 'both headers proto'
+
+ assert self.get_addr() == '127.0.0.1', 'ipv4 default addr'
+ assert self.get_addr('ipv6') == '::1', 'ipv6 default addr'
+ assert self.get_addr(xff='1.1.1.1') == '127.0.0.1', 'bad source'
+ assert self.get_addr(xff='blah') == '127.0.0.1', 'bad xff'
+ assert self.get_addr('ipv6', '1.1.1.1') == '::1', 'bad source ipv6'
+
+ assert self.get_scheme() == 'http', 'ipv4 default proto'
+ assert self.get_scheme('ipv6') == 'http', 'ipv6 default proto'
+ assert self.get_scheme(xfp='https') == 'http', 'bad proto'
+ assert self.get_scheme(xfp='blah') == 'http', 'bad xfp'
+ assert self.get_scheme('ipv6', xfp='https') == 'http', 'bad proto ipv6'
+
+ self.forwarded_header(
+ {
+ 'client_ip': 'X-Forwarded-For',
+ 'protocol': 'X-Forwarded-Proto',
+ 'source': '127.0.0.1',
+ }
+ )
+
+ resp = self.get_fwd(xff='1.1.1.1', xfp='https')
+ assert resp['Remote-Addr'] == '1.1.1.1', 'both headers addr 2'
+ assert resp['Url-Scheme'] == 'https', 'both headers proto 2'
+
+ assert self.get_addr() == '127.0.0.1', 'ipv4 default addr 2'
+ assert self.get_addr('ipv6') == '::1', 'ipv6 default addr 2'
+ assert self.get_addr(xff='1.1.1.1') == '1.1.1.1', 'xff replace'
+ assert self.get_addr('ipv6', '1.1.1.1') == '::1', 'bad source ipv6 2'
+
+ assert self.get_scheme() == 'http', 'ipv4 default proto 2'
+ assert self.get_scheme('ipv6') == 'http', 'ipv6 default proto 2'
+ assert self.get_scheme(xfp='https') == 'https', 'xfp replace'
+ assert self.get_scheme(xfp='on') == 'https', 'xfp replace 2'
+ assert (
+ self.get_scheme('ipv6', xfp='https') == 'http'
+ ), 'bad proto ipv6 2'
+
+ self.forwarded_header(
+ {
+ 'client_ip': 'X-Forwarded-For',
+ 'protocol': 'X-Forwarded-Proto',
+ 'source': '!127.0.0.1',
+ }
+ )
+
+ assert self.get_addr(xff='1.1.1.1') == '127.0.0.1', 'bad source 3'
+ assert self.get_addr('ipv6', '1.1.1.1') == '1.1.1.1', 'xff replace 2'
+ assert self.get_scheme(xfp='https') == 'http', 'bad proto 2'
+ assert self.get_scheme('ipv6', xfp='https') == 'https', 'xfp replace 3'
+
+ def test_forwarded_header_ipv4(self):
+ self.forwarded_header(
+ {
+ 'client_ip': 'X-Forwarded-For',
+ 'protocol': 'X-Forwarded-Proto',
+ 'source': '127.0.0.1',
+ }
+ )
+
+ assert (
+ self.get_addr(xff='8.8.8.8, 84.23.23.11') == '84.23.23.11'
+ ), 'xff replace'
+ assert (
+ self.get_addr(xff='8.8.8.8, 84.23.23.11, 127.0.0.1') == '127.0.0.1'
+ ), 'xff replace 2'
+ assert (
+ self.get_addr(xff=['8.8.8.8', '127.0.0.1, 10.0.1.1']) == '10.0.1.1'
+ ), 'xff replace multi'
+
+ assert self.get_scheme(xfp='http, https') == 'http', 'xfp replace'
+ assert (
+ self.get_scheme(xfp='http, https, http') == 'http'
+ ), 'xfp replace 2'
+ assert (
+ self.get_scheme(xfp=['http, https', 'http', 'https']) == 'http'
+ ), 'xfp replace multi'
+
+ def test_forwarded_header_ipv6(self):
+ self.forwarded_header(
+ {
+ 'client_ip': 'X-Forwarded-For',
+ 'protocol': 'X-Forwarded-Proto',
+ 'source': '::1',
+ }
+ )
+
+ assert self.get_addr(xff='1.1.1.1') == '127.0.0.1', 'bad source ipv4'
+
+ for ip in [
+ 'f607:7403:1e4b:6c66:33b2:843f:2517:da27',
+ '2001:db8:3c4d:15::1a2f:1a2b',
+ '2001::3c4d:15:1a2f:1a2b',
+ '::11.22.33.44',
+ ]:
+ assert self.get_addr('ipv6', ip) == ip, 'replace'
+
+ assert self.get_scheme(xfp='https') == 'http', 'bad source ipv4'
+
+ for proto in ['http', 'https']:
+ assert self.get_scheme('ipv6', xfp=proto) == proto, 'replace'
+
+ def test_forwarded_header_recursive(self):
+ self.forwarded_header(
+ {
+ 'client_ip': 'X-Forwarded-For',
+ 'recursive': True,
+ 'source': ['127.0.0.1', '10.50.0.17', '10.5.2.1'],
+ }
+ )
+
+ assert self.get_addr(xff='1.1.1.1') == '1.1.1.1', 'xff chain'
+ assert (
+ self.get_addr(xff='1.1.1.1, 10.5.2.1') == '1.1.1.1'
+ ), 'xff chain 2'
+ assert (
+ self.get_addr(xff='8.8.8.8, 1.1.1.1, 10.5.2.1') == '1.1.1.1'
+ ), 'xff chain 3'
+ assert (
+ self.get_addr(xff='10.50.0.17, 10.5.2.1, 10.5.2.1') == '10.50.0.17'
+ ), 'xff chain 4'
+ assert (
+ self.get_addr(xff=['8.8.8.8', '1.1.1.1, 127.0.0.1']) == '1.1.1.1'
+ ), 'xff replace multi'
+ assert (
+ self.get_addr(xff=['8.8.8.8', '1.1.1.1, 127.0.0.1', '10.5.2.1'])
+ == '1.1.1.1'
+ ), 'xff replace multi 2'
+ assert (
+ self.get_addr(xff=['10.5.2.1', '10.50.0.17, 1.1.1.1', '10.5.2.1'])
+ == '1.1.1.1'
+ ), 'xff replace multi 3'
+ assert (
+ self.get_addr(
+ xff='8.8.8.8, 2001:db8:3c4d:15::1a2f:1a2b, 127.0.0.1'
+ )
+ == '2001:db8:3c4d:15::1a2f:1a2b'
+ ), 'xff chain ipv6'
+
+ def test_forwarded_header_case_insensitive(self):
+ self.forwarded_header(
+ {
+ 'client_ip': 'x-forwarded-for',
+ 'protocol': 'x-forwarded-proto',
+ 'source': '127.0.0.1',
+ }
+ )
+
+ assert self.get_addr() == '127.0.0.1', 'ipv4 default addr'
+ assert self.get_addr('ipv6') == '::1', 'ipv6 default addr'
+ assert self.get_addr(xff='1.1.1.1') == '1.1.1.1', 'replace'
+
+ assert self.get_scheme() == 'http', 'ipv4 default proto'
+ assert self.get_scheme('ipv6') == 'http', 'ipv6 default proto'
+ assert self.get_scheme(xfp='https') == 'https', 'replace 1'
+ assert self.get_scheme(xfp='oN') == 'https', 'replace 2'
+
+ def test_forwarded_header_source_empty(self):
+ self.forwarded_header(
+ {
+ 'client_ip': 'X-Forwarded-For',
+ 'protocol': 'X-Forwarded-Proto',
+ 'source': [],
+ }
+ )
+
+ assert self.get_addr(xff='1.1.1.1') == '127.0.0.1', 'empty source xff'
+ assert self.get_scheme(xfp='https') == 'http', 'empty source xfp'
+
+ def test_forwarded_header_source_range(self):
+ self.forwarded_header(
+ {
+ 'client_ip': 'X-Forwarded-For',
+ 'protocol': 'X-Forwarded-Proto',
+ 'source': '127.0.0.0-127.0.0.1',
+ }
+ )
+
+ assert self.get_addr(xff='1.1.1.1') == '1.1.1.1', 'source range'
+ assert self.get_addr('ipv6', '1.1.1.1') == '::1', 'source range 2'
+
+ def test_forwarded_header_invalid(self):
+ assert 'error' in self.conf(
+ {
+ "127.0.0.1:7081": {
+ "forwarded": {"source": '127.0.0.1'},
+ "pass": "applications/forwarded_header",
+ }
+ },
+ 'listeners',
+ ), 'invalid forward'
+
+ def check_invalid_source(source):
+ assert 'error' in self.conf(
+ {
+ "127.0.0.1:7081": {
+ "forwarded": {
+ "client_ip": "X-Forwarded-For",
+ "source": source,
+ },
+ "pass": "applications/forwarded_header",
+ }
+ },
+ 'listeners',
+ ), 'invalid source'
+
+ check_invalid_source(None)
+ check_invalid_source('a')
+ check_invalid_source(['a'])
diff --git a/test/test_go_application.py b/test/test_go_application.py
index c8cf3e53..a746c6f4 100644
--- a/test/test_go_application.py
+++ b/test/test_go_application.py
@@ -95,7 +95,6 @@ class TestGoApplication(TestApplicationGo):
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -105,16 +104,7 @@ class TestGoApplication(TestApplicationGo):
assert resp['body'] == body, 'keep-alive 1'
body = '0123456789'
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Content-Type': 'text/html',
- 'Connection': 'close',
- },
- sock=sock,
- body=body,
- )
-
+ resp = self.post(sock=sock, body=body)
assert resp['body'] == body, 'keep-alive 2'
def test_go_application_cookies(self):
diff --git a/test/test_node_application.py b/test/test_node_application.py
index fc722582..c26c72d0 100644
--- a/test/test_node_application.py
+++ b/test/test_node_application.py
@@ -124,7 +124,6 @@ class TestNodeApplication(TestApplicationNode):
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -134,15 +133,7 @@ class TestNodeApplication(TestApplicationNode):
assert resp['body'] == '0123456789' * 500, 'keep-alive 1'
body = '0123456789'
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=sock,
- body=body,
- )
+ resp = self.post(sock=sock, body=body)
assert resp['body'] == body, 'keep-alive 2'
diff --git a/test/test_php_application.py b/test/test_php_application.py
index 606ac723..f1dcc995 100644
--- a/test/test_php_application.py
+++ b/test/test_php_application.py
@@ -226,7 +226,6 @@ opcache.preload_user = %(user)s
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -236,15 +235,7 @@ opcache.preload_user = %(user)s
assert resp['body'] == body, 'keep-alive 1'
body = '0123456789'
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=sock,
- body=body,
- )
+ resp = self.post(sock=sock, body=body)
assert resp['body'] == body, 'keep-alive 2'
diff --git a/test/test_proxy.py b/test/test_proxy.py
index 68ae2394..b0d471e4 100644
--- a/test/test_proxy.py
+++ b/test/test_proxy.py
@@ -370,7 +370,6 @@ Content-Length: 10
resp = self.post_http10(
headers={
'Host': 'localhost',
- 'Content-Type': 'text/html',
'Content-Length': str(len(body)),
'X-Parts': '2',
'X-Delay': '1',
@@ -384,7 +383,6 @@ Content-Length: 10
resp = self.post_http10(
headers={
'Host': 'localhost',
- 'Content-Type': 'text/html',
'Content-Length': str(len(body)),
'X-Parts': '2',
'X-Delay': '1',
@@ -403,7 +401,6 @@ Content-Length: 10
_, sock = self.post_http10(
headers={
'Host': 'localhost',
- 'Content-Type': 'text/html',
'Content-Length': '10000',
'X-Parts': '3',
'X-Delay': '1',
@@ -419,7 +416,6 @@ Content-Length: 10
_, sock = self.post_http10(
headers={
'Host': 'localhost',
- 'Content-Type': 'text/html',
'Content-Length': '10000',
'X-Parts': '3',
'X-Delay': '1',
diff --git a/test/test_python_application.py b/test/test_python_application.py
index befbd4d8..2ea9a22e 100644
--- a/test/test_python_application.py
+++ b/test/test_python_application.py
@@ -138,14 +138,7 @@ custom-header: BLAH
def test_python_application_ctx_iter_atexit(self):
self.load('ctx_iter_atexit')
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- body='0123456789',
- )
+ resp = self.post(body='0123456789')
assert resp['status'] == 200, 'ctx iter status'
assert resp['body'] == '0123456789', 'ctx iter body'
@@ -166,7 +159,6 @@ custom-header: BLAH
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -176,15 +168,7 @@ custom-header: BLAH
assert resp['body'] == body, 'keep-alive 1'
body = '0123456789'
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=sock,
- body=body,
- )
+ resp = self.post(sock=sock, body=body)
assert resp['body'] == body, 'keep-alive 2'
@@ -202,7 +186,6 @@ custom-header: BLAH
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -220,7 +203,6 @@ custom-header: BLAH
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
sock=socks[i],
@@ -233,15 +215,7 @@ custom-header: BLAH
self.load('mirror', processes=i + 1)
for i in range(conns):
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=socks[i],
- body=body,
- )
+ resp = self.post(sock=socks[i], body=body)
assert resp['body'] == body, 'keep-alive close'
@@ -258,7 +232,6 @@ custom-header: BLAH
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -271,16 +244,7 @@ custom-header: BLAH
assert self.get()['status'] == 200, 'init'
- (resp, sock) = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- start=True,
- sock=sock,
- body=body,
- )
+ (resp, sock) = self.post(start=True, sock=sock, body=body)
assert resp['status'] == 200, 'reconfigure 2 keep-alive 2'
assert resp['body'] == '', 'reconfigure 2 keep-alive 2 body'
diff --git a/test/test_routing.py b/test/test_routing.py
index fda429a4..3649b37c 100644
--- a/test/test_routing.py
+++ b/test/test_routing.py
@@ -1723,18 +1723,26 @@ class TestRouting(TestApplicationPython):
addr = temp_dir + '/sock'
assert 'success' in self.conf(
- {"unix:" + addr: {"pass": "routes"}}, 'listeners'
+ {
+ "127.0.0.1:7081": {"pass": "routes"},
+ "unix:" + addr: {"pass": "routes"},
+ },
+ 'listeners',
), 'source listeners configure'
self.route_match({"source": "!0.0.0.0/0"})
assert (
self.get(sock_type='unix', addr=addr)['status'] == 200
- ), 'unix ipv4'
+ ), 'unix ipv4 neg'
self.route_match({"source": "!::/0"})
assert (
self.get(sock_type='unix', addr=addr)['status'] == 200
- ), 'unix ipv6'
+ ), 'unix ipv6 neg'
+
+ self.route_match({"source": "unix"})
+ assert self.get(port=7081)['status'] == 404, 'unix ipv4'
+ assert self.get(sock_type='unix', addr=addr)['status'] == 200, 'unix'
def test_routes_match_source(self):
self.route_match({"source": "::"})
diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py
index 95c75d47..83af39be 100644
--- a/test/test_ruby_application.py
+++ b/test/test_ruby_application.py
@@ -44,7 +44,7 @@ class TestRubyApplication(TestApplicationRuby):
'Request-Method': 'POST',
'Request-Uri': '/',
'Http-Host': 'localhost',
- 'Script-Name': 'config.ru',
+ 'Script-Name': '',
'Server-Protocol': 'HTTP/1.1',
'Custom-Header': 'blah',
'Rack-Version': '13',
@@ -347,7 +347,6 @@ class TestRubyApplication(TestApplicationRuby):
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body=body,
@@ -357,15 +356,7 @@ class TestRubyApplication(TestApplicationRuby):
assert resp['body'] == body, 'keep-alive 1'
body = '0123456789'
- resp = self.post(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=sock,
- body=body,
- )
+ resp = self.post(sock=sock, body=body)
assert resp['body'] == body, 'keep-alive 2'
diff --git a/test/test_static_chroot.py b/test/test_static_chroot.py
index b896a9b9..e33a181c 100644
--- a/test/test_static_chroot.py
+++ b/test/test_static_chroot.py
@@ -14,8 +14,7 @@ class TestStaticChroot(TestApplicationProto):
Path(temp_dir + '/assets/index.html').write_text('0123456789')
Path(temp_dir + '/assets/dir/file').write_text('blah')
- test = Path(__file__)
- self.test_path = '/' + test.parent.name + '/' + test.name
+ self.test_path = '/' + os.path.relpath(Path(__file__))
self._load_conf(
{
@@ -39,26 +38,18 @@ class TestStaticChroot(TestApplicationProto):
assert self.get(url='/dir/file')['status'] == 200, 'default chroot'
assert self.get(url='/index.html')['status'] == 200, 'default chroot 2'
- assert 'success' in self.conf(
- {
- "share": temp_dir + "/assets$uri",
- "chroot": temp_dir + "/assets/dir",
- },
- 'routes/0/action',
- ), 'configure chroot'
+ assert 'success' in self.update_action(
+ temp_dir + "/assets$uri", temp_dir + "/assets/dir"
+ )
assert self.get(url='/dir/file')['status'] == 200, 'chroot'
assert self.get(url='/index.html')['status'] == 403, 'chroot 403 2'
assert self.get(url='/file')['status'] == 403, 'chroot 403'
def test_share_chroot_array(self, temp_dir):
- assert 'success' in self.conf(
- {
- "share": ["/blah", temp_dir + "/assets$uri"],
- "chroot": temp_dir + "/assets/dir",
- },
- 'routes/0/action',
- ), 'configure share array'
+ assert 'success' in self.update_action(
+ ["/blah", temp_dir + "/assets$uri"], temp_dir + "/assets/dir"
+ )
assert self.get(url='/dir/file')['status'] == 200, 'share array'
assert 'success' in self.update_action(
@@ -66,13 +57,9 @@ class TestStaticChroot(TestApplicationProto):
)
assert self.get_custom('/dir/file', 'dir') == 200, 'array variable'
- assert 'success' in self.conf(
- {
- "share": ["/blah", "/blah2"],
- "chroot": temp_dir + "/assets/dir",
- },
- 'routes/0/action',
- ), 'configure share array bad'
+ assert 'success' in self.update_action(
+ ["/blah", "/blah2"], temp_dir + "/assets/dir"
+ )
assert self.get()['status'] != 200, 'share array bad'
def test_static_chroot_permission(self, is_su, temp_dir):
@@ -81,58 +68,30 @@ class TestStaticChroot(TestApplicationProto):
os.chmod(temp_dir + '/assets/dir', 0o100)
- assert 'success' in self.conf(
- {
- "share": temp_dir + "/assets$uri",
- "chroot": temp_dir + "/assets/dir",
- },
- 'routes/0/action',
+ assert 'success' in self.update_action(
+ temp_dir + "/assets$uri", temp_dir + "/assets/dir"
), 'configure chroot'
assert self.get(url='/dir/file')['status'] == 200, 'chroot'
def test_static_chroot_empty(self, temp_dir):
- assert 'success' in self.conf(
- {"share": temp_dir + "/assets$uri", "chroot": ""},
- 'routes/0/action',
- ), 'configure chroot empty absolute'
-
- assert (
- self.get(url='/dir/file')['status'] == 200
- ), 'chroot empty absolute'
-
- assert 'success' in self.conf(
- {"share": ".$uri", "chroot": ""},
- 'routes/0/action',
- ), 'configure chroot empty relative'
+ assert 'success' in self.update_action(temp_dir + "/assets$uri", "")
+ assert self.get(url='/dir/file')['status'] == 200, 'empty absolute'
- assert (
- self.get(url=self.test_path)['status'] == 200
- ), 'chroot empty relative'
+ assert 'success' in self.update_action(".$uri", "")
+ assert self.get(url=self.test_path)['status'] == 200, 'empty relative'
def test_static_chroot_relative(self, is_su, temp_dir):
if is_su:
pytest.skip('does\'t work under root')
- assert 'success' in self.conf(
- {"share": temp_dir + "/assets$uri", "chroot": "."},
- 'routes/0/action',
- ), 'configure relative chroot'
-
+ assert 'success' in self.update_action(temp_dir + "/assets$uri", ".")
assert self.get(url='/dir/file')['status'] == 403, 'relative chroot'
- assert 'success' in self.conf(
- {"share": ".$uri"},
- 'routes/0/action',
- ), 'configure relative share'
-
+ assert 'success' in self.conf({"share": ".$uri"}, 'routes/0/action')
assert self.get(url=self.test_path)['status'] == 200, 'relative share'
- assert 'success' in self.conf(
- {"share": ".$uri", "chroot": "."},
- 'routes/0/action',
- ), 'configure relative'
-
+ assert 'success' in self.update_action(".$uri", ".")
assert self.get(url=self.test_path)['status'] == 200, 'relative'
def test_static_chroot_variables(self, temp_dir):
@@ -150,64 +109,41 @@ class TestStaticChroot(TestApplicationProto):
assert 'success' in self.update_action(
temp_dir + '/assets/dir/$host', '$uri/assets/dir'
)
-
assert self.get_custom(temp_dir, 'file') == 200
def test_static_chroot_variables_buildin_mid(self, temp_dir):
assert 'success' in self.update_action(
temp_dir + '/assets$uri', temp_dir + '/$host/dir'
)
-
assert self.get_custom('/dir/file', 'assets') == 200
def test_static_chroot_variables_buildin_end(self, temp_dir):
assert 'success' in self.update_action(
temp_dir + '/assets$uri', temp_dir + '/assets/$host'
)
-
assert self.get_custom('/dir/file', 'dir') == 200
def test_static_chroot_slash(self, temp_dir):
- assert 'success' in self.conf(
- {
- "share": temp_dir + "/assets$uri",
- "chroot": temp_dir + "/assets/dir/",
- },
- 'routes/0/action',
- ), 'configure chroot slash end'
-
+ assert 'success' in self.update_action(
+ temp_dir + "/assets$uri", temp_dir + "/assets/dir/"
+ )
assert self.get(url='/dir/file')['status'] == 200, 'slash end'
assert self.get(url='/dirxfile')['status'] == 403, 'slash end bad'
- assert 'success' in self.conf(
- {
- "share": temp_dir + "/assets$uri",
- "chroot": temp_dir + "/assets/dir",
- },
- 'routes/0/action',
- ), 'configure chroot no slash end'
-
+ assert 'success' in self.update_action(
+ temp_dir + "/assets$uri", temp_dir + "/assets/dir"
+ )
assert self.get(url='/dir/file')['status'] == 200, 'no slash end'
- assert 'success' in self.conf(
- {
- "share": temp_dir + "/assets$uri",
- "chroot": temp_dir + "/assets/dir/",
- },
- 'routes/0/action',
- ), 'configure chroot slash end 2'
-
+ assert 'success' in self.update_action(
+ temp_dir + "/assets$uri", temp_dir + "/assets/dir/"
+ )
assert self.get(url='/dir/file')['status'] == 200, 'slash end 2'
assert self.get(url='/dirxfile')['status'] == 403, 'slash end 2 bad'
- assert 'success' in self.conf(
- {
- "share": temp_dir + "///assets/////$uri",
- "chroot": temp_dir + "//assets////dir///",
- },
- 'routes/0/action',
- ), 'configure chroot multiple slashes'
-
+ assert 'success' in self.update_action(
+ temp_dir + "///assets/////$uri", temp_dir + "//assets////dir///"
+ )
assert self.get(url='/dir/file')['status'] == 200, 'multiple slashes'
def test_static_chroot_invalid(self, temp_dir):
diff --git a/test/test_status.py b/test/test_status.py
new file mode 100644
index 00000000..214072d4
--- /dev/null
+++ b/test/test_status.py
@@ -0,0 +1,223 @@
+import time
+
+import pytest
+from unit.applications.lang.python import TestApplicationPython
+from unit.option import option
+from unit.status import Status
+
+
+class TestStatus(TestApplicationPython):
+ prerequisites = {'modules': {'python': 'any'}}
+
+ def test_status(self):
+ assert 'error' in self.conf_delete('/status'), 'DELETE method'
+
+ def test_status_requests(self, skip_alert):
+ skip_alert(r'Python failed to import module "blah"')
+
+ assert 'success' in self.conf(
+ {
+ "listeners": {
+ "*:7080": {"pass": "routes"},
+ "*:7081": {"pass": "applications/empty"},
+ "*:7082": {"pass": "applications/blah"},
+ },
+ "routes": [{"action": {"return": 200}}],
+ "applications": {
+ "empty": {
+ "type": self.get_application_type(),
+ "processes": {"spare": 0},
+ "path": option.test_dir + '/python/empty',
+ "working_directory": option.test_dir + '/python/empty',
+ "module": "wsgi",
+ },
+ "blah": {
+ "type": self.get_application_type(),
+ "processes": {"spare": 0},
+ "module": "blah",
+ },
+ },
+ },
+ )
+
+ Status.init()
+
+ assert self.get()['status'] == 200
+ assert Status.get('/requests/total') == 1, '2xx'
+
+ assert self.get(port=7081)['status'] == 200
+ assert Status.get('/requests/total') == 2, '2xx app'
+
+ assert (
+ self.get(headers={'Host': '/', 'Connection': 'close'})['status']
+ == 400
+ )
+ assert Status.get('/requests/total') == 3, '4xx'
+
+ assert self.get(port=7082)['status'] == 503
+ assert Status.get('/requests/total') == 4, '5xx'
+
+ self.http(
+ b"""GET / HTTP/1.1
+Host: localhost
+
+GET / HTTP/1.1
+Host: localhost
+Connection: close
+
+""",
+ raw=True,
+ )
+ assert Status.get('/requests/total') == 6, 'pipeline'
+
+ (_, sock) = self.get(port=7081, no_recv=True, start=True)
+
+ time.sleep(1)
+
+ assert Status.get('/requests/total') == 7, 'no receive'
+
+ sock.close()
+
+ def test_status_connections(self):
+ def check_connections(accepted, active, idle, closed):
+ Status.get('/connections') == {
+ 'accepted': accepted,
+ 'active': active,
+ 'idle': idle,
+ 'closed': closed,
+ }
+
+ assert 'success' in self.conf(
+ {
+ "listeners": {
+ "*:7080": {"pass": "routes"},
+ "*:7081": {"pass": "applications/delayed"},
+ },
+ "routes": [{"action": {"return": 200}}],
+ "applications": {
+ "delayed": {
+ "type": self.get_application_type(),
+ "processes": {"spare": 0},
+ "path": option.test_dir + "/python/delayed",
+ "working_directory": option.test_dir
+ + "/python/delayed",
+ "module": "wsgi",
+ },
+ },
+ },
+ )
+
+ Status.init()
+
+ # accepted, closed
+
+ assert self.get()['status'] == 200
+ check_connections(1, 0, 0, 1)
+
+ # idle
+
+ _, sock = self.http(b'', start=True, raw=True, no_recv=True)
+ check_connections(2, 0, 1, 1)
+
+ self.get(sock=sock)
+ check_connections(2, 0, 0, 2)
+
+ # active
+
+ (_, sock) = self.get(
+ headers={
+ 'Host': 'localhost',
+ 'X-Delay': '2',
+ 'Connection': 'close',
+ },
+ port=7081,
+ start=True,
+ read_timeout=1,
+ )
+ check_connections(3, 1, 0, 2)
+
+ self.get(sock=sock)
+ check_connections(3, 0, 0, 3)
+
+ def test_status_applications(self):
+ def check_applications(expert):
+ apps = list(self.conf_get('/status/applications').keys()).sort()
+ assert apps == expert.sort()
+
+ def check_application(name, running, starting, idle, active):
+ Status.get('/applications/' + name) == {
+ 'processes': {
+ 'running': running,
+ 'starting': starting,
+ 'idle': idle,
+ },
+ 'requests': {'active': active},
+ }
+
+ self.load('delayed')
+ Status.init()
+
+ check_applications(['delayed'])
+ check_application('delayed', 0, 0, 0, 0)
+
+ # idle
+
+ assert self.get()['status'] == 200
+ check_application('delayed', 1, 0, 1, 0)
+
+ assert 'success' in self.conf('4', 'applications/delayed/processes')
+ check_application('delayed', 4, 0, 4, 0)
+
+ # active
+
+ (_, sock) = self.get(
+ headers={
+ 'Host': 'localhost',
+ 'X-Delay': '2',
+ 'Connection': 'close',
+ },
+ start=True,
+ read_timeout=1,
+ )
+ check_application('delayed', 4, 0, 3, 1)
+ sock.close()
+
+ # starting
+
+ assert 'success' in self.conf(
+ {
+ "listeners": {
+ "*:7080": {"pass": "applications/restart"},
+ "*:7081": {"pass": "applications/delayed"},
+ },
+ "routes": [],
+ "applications": {
+ "restart": {
+ "type": self.get_application_type(),
+ "processes": {"spare": 0},
+ "path": option.test_dir + "/python/restart",
+ "working_directory": option.test_dir
+ + "/python/restart",
+ "module": "longstart",
+ },
+ "delayed": {
+ "type": self.get_application_type(),
+ "processes": {"spare": 0},
+ "path": option.test_dir + "/python/delayed",
+ "working_directory": option.test_dir
+ + "/python/delayed",
+ "module": "wsgi",
+ },
+ },
+ },
+ )
+ Status.init()
+
+ check_applications(['delayed', 'restart'])
+ check_application('restart', 0, 0, 0, 0)
+ check_application('delayed', 0, 0, 0, 0)
+
+ self.get(read_timeout=1)
+
+ check_application('restart', 0, 1, 0, 1)
+ check_application('delayed', 0, 0, 0, 0)
diff --git a/test/test_status_tls.py b/test/test_status_tls.py
new file mode 100644
index 00000000..dc3d68da
--- /dev/null
+++ b/test/test_status_tls.py
@@ -0,0 +1,30 @@
+from unit.applications.tls import TestApplicationTLS
+from unit.status import Status
+
+
+class TestStatusTLS(TestApplicationTLS):
+ prerequisites = {'modules': {'openssl': 'any'}}
+
+ def test_status_tls_requests(self):
+ self.certificate()
+
+ assert 'success' in self.conf(
+ {
+ "listeners": {
+ "*:7080": {"pass": "routes"},
+ "*:7081": {
+ "pass": "routes",
+ "tls": {"certificate": "default"},
+ },
+ },
+ "routes": [{"action": {"return": 200}}],
+ "applications": {},
+ }
+ )
+
+ Status.init()
+
+ assert self.get()['status'] == 200
+ assert self.get_ssl(port=7081)['status'] == 200
+
+ assert Status.get('/requests/total') == 2
diff --git a/test/test_tls.py b/test/test_tls.py
index 56ee8298..d4edcbd3 100644
--- a/test/test_tls.py
+++ b/test/test_tls.py
@@ -1,5 +1,4 @@
import io
-import re
import ssl
import subprocess
import time
@@ -13,7 +12,7 @@ class TestTLS(TestApplicationTLS):
prerequisites = {'modules': {'python': 'any', 'openssl': 'any'}}
def openssl_date_to_sec_epoch(self, date):
- return self.date_to_sec_epoch(date, '%b %d %H:%M:%S %Y %Z')
+ return self.date_to_sec_epoch(date, '%b %d %X %Y %Z')
def add_tls(self, application='empty', cert='default', port=7080):
assert 'success' in self.conf(
@@ -506,7 +505,6 @@ basicConstraints = critical,CA:TRUE"""
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body='0123456789',
@@ -519,7 +517,6 @@ basicConstraints = critical,CA:TRUE"""
headers={
'Host': 'localhost',
'Connection': 'close',
- 'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
@@ -571,9 +568,7 @@ basicConstraints = critical,CA:TRUE"""
assert 'success' in self.conf_delete('/certificates/default')
try:
- resp = self.get_ssl(
- headers={'Host': 'localhost', 'Connection': 'close'}, sock=sock
- )
+ resp = self.get_ssl(sock=sock)
except KeyboardInterrupt:
raise
@@ -606,7 +601,6 @@ basicConstraints = critical,CA:TRUE"""
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
- 'Content-Type': 'text/html',
},
start=True,
body='0123456789',
@@ -617,23 +611,13 @@ basicConstraints = critical,CA:TRUE"""
subprocess.check_output(['kill', '-9', app_id])
- skip_alert(r'process .* %s.* exited on signal 9' % app_id)
+ skip_alert(r'process %s exited on signal 9' % app_id)
self.wait_for_record(
- re.compile(
- r' (?!' + app_id + r'#)(\d+)#\d+ "mirror" application started'
- )
+ r' (?!' + app_id + r'#)(\d+)#\d+ "mirror" application started'
)
- resp = self.post_ssl(
- headers={
- 'Host': 'localhost',
- 'Connection': 'close',
- 'Content-Type': 'text/html',
- },
- sock=sock,
- body='0123456789',
- )
+ resp = self.post_ssl(sock=sock, body='0123456789')
assert resp['status'] == 200, 'application respawn status'
assert resp['body'] == '0123456789', 'application respawn body'
diff --git a/test/test_tls_sni.py b/test/test_tls_sni.py
index dbd5d900..44cc21e1 100644
--- a/test/test_tls_sni.py
+++ b/test/test_tls_sni.py
@@ -18,7 +18,7 @@ class TestTLSSNI(TestApplicationTLS):
)
def openssl_date_to_sec_epoch(self, date):
- return self.date_to_sec_epoch(date, '%b %d %H:%M:%S %Y %Z')
+ return self.date_to_sec_epoch(date, '%b %d %X %Y %Z')
def add_tls(self, cert='default'):
assert 'success' in self.conf(
diff --git a/test/test_unix_abstract.py b/test/test_unix_abstract.py
new file mode 100644
index 00000000..195b0aa7
--- /dev/null
+++ b/test/test_unix_abstract.py
@@ -0,0 +1,109 @@
+from unit.applications.lang.python import TestApplicationPython
+from unit.option import option
+
+
+class TestUnixAbstract(TestApplicationPython):
+ prerequisites = {
+ 'modules': {'python': 'any'},
+ 'features': ['unix_abstract'],
+ }
+
+ def test_unix_abstract_source(self):
+ addr = '\0sock'
+
+ def source(source):
+ assert 'success' in self.conf(
+ '"' + source + '"', 'routes/0/match/source'
+ )
+
+ assert 'success' in self.conf(
+ {
+ "listeners": {
+ "127.0.0.1:7080": {"pass": "routes"},
+ "unix:@" + addr[1:]: {"pass": "routes"},
+ },
+ "routes": [
+ {
+ "match": {"source": "!0.0.0.0/0"},
+ "action": {"return": 200},
+ }
+ ],
+ "applications": {},
+ }
+ )
+
+ assert (
+ self.get(sock_type='unix', addr=addr)['status'] == 200
+ ), 'neg ipv4'
+
+ source("!::/0")
+ assert (
+ self.get(sock_type='unix', addr=addr)['status'] == 200
+ ), 'neg ipv6'
+
+ source("unix")
+ assert self.get()['status'] == 404, 'ipv4'
+ assert self.get(sock_type='unix', addr=addr)['status'] == 200, 'unix'
+
+ def test_unix_abstract_client_ip(self):
+ def get_xff(xff, sock_type='ipv4'):
+ address = {
+ 'ipv4': ('127.0.0.1', 7080),
+ 'ipv6': ('::1', 7081),
+ 'unix': ('\0sock', None),
+ }
+ (addr, port) = address[sock_type]
+
+ return self.get(
+ sock_type=sock_type,
+ addr=addr,
+ port=port,
+ headers={'Connection': 'close', 'X-Forwarded-For': xff},
+ )['body']
+
+ assert 'success' in self.conf(
+ {
+ "listeners": {
+ "127.0.0.1:7080": {
+ "client_ip": {
+ "header": "X-Forwarded-For",
+ "source": "unix",
+ },
+ "pass": "applications/client_ip",
+ },
+ "[::1]:7081": {
+ "client_ip": {
+ "header": "X-Forwarded-For",
+ "source": "unix",
+ },
+ "pass": "applications/client_ip",
+ },
+ "unix:@sock": {
+ "client_ip": {
+ "header": "X-Forwarded-For",
+ "source": "unix",
+ },
+ "pass": "applications/client_ip",
+ },
+ },
+ "applications": {
+ "client_ip": {
+ "type": self.get_application_type(),
+ "processes": {"spare": 0},
+ "path": option.test_dir + "/python/client_ip",
+ "working_directory": option.test_dir
+ + "/python/client_ip",
+ "module": "wsgi",
+ }
+ },
+ }
+ )
+
+ assert get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4'
+ assert get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6'
+
+ for ip in [
+ '1.1.1.1',
+ '::11.22.33.44',
+ ]:
+ assert get_xff(ip, 'unix') == ip, 'replace'
diff --git a/test/test_variables.py b/test/test_variables.py
index 71553685..2ddfdc0a 100644
--- a/test/test_variables.py
+++ b/test/test_variables.py
@@ -18,6 +18,11 @@ class TestVariables(TestApplicationProto):
"GETGET": [{"action": {"return": 207}}],
"localhost": [{"action": {"return": 208}}],
"9?q#a": [{"action": {"return": 209}}],
+ "blah": [{"action": {"return": 210}}],
+ "127.0.0.1": [{"action": {"return": 211}}],
+ "::1": [{"action": {"return": 212}}],
+ "referer-value": [{"action": {"return": 213}}],
+ "MSIE": [{"action": {"return": 214}}],
},
},
), 'configure routes'
@@ -62,6 +67,74 @@ class TestVariables(TestApplicationProto):
check_host('www.localhost', 404)
check_host('localhost1', 404)
+ def test_variables_remote_addr(self):
+ self.conf_routes("\"routes/$remote_addr\"")
+ assert self.get()['status'] == 211
+
+ assert 'success' in self.conf(
+ {"[::1]:7080": {"pass": "routes/$remote_addr"}}, 'listeners'
+ )
+ assert self.get(sock_type='ipv6')['status'] == 212
+
+ def test_variables_header_referer(self):
+ self.conf_routes("\"routes/$header_referer\"")
+
+ def check_referer(referer, status=213):
+ assert (
+ self.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'Referer': referer,
+ }
+ )['status']
+ == status
+ )
+
+ check_referer('referer-value')
+ check_referer('', 404)
+ check_referer('no', 404)
+
+ def test_variables_header_user_agent(self):
+ self.conf_routes("\"routes/$header_user_agent\"")
+
+ def check_user_agent(user_agent, status=214):
+ assert (
+ self.get(
+ headers={
+ 'Host': 'localhost',
+ 'Connection': 'close',
+ 'User-Agent': user_agent,
+ }
+ )['status']
+ == status
+ )
+
+ check_user_agent('MSIE')
+ check_user_agent('', 404)
+ check_user_agent('no', 404)
+
+ def test_variables_dollar(self):
+ assert 'success' in self.conf(
+ {
+ "listeners": {"*:7080": {"pass": "routes"}},
+ "routes": [{"action": {"return": 301}}],
+ }
+ )
+
+ def check_dollar(location, expect):
+ assert 'success' in self.conf(
+ '"' + location + '"',
+ 'routes/0/action/location',
+ )
+ assert self.get()['headers']['Location'] == expect
+
+ check_dollar(
+ 'https://${host}${uri}path${dollar}dollar',
+ 'https://localhost/path$dollar',
+ )
+ check_dollar('path$dollar${dollar}', 'path$$')
+
def test_variables_many(self):
self.conf_routes("\"routes$uri$method\"")
assert self.get(url='/5')['status'] == 206, 'many'
@@ -124,6 +197,80 @@ class TestVariables(TestApplicationProto):
update_pass("applications")
assert self.get(url='/3')['status'] == 404
+ def test_variables_dynamic(self):
+ self.conf_routes("\"routes/$header_foo$arg_foo$cookie_foo\"")
+
+ self.get(
+ url='/?foo=h',
+ headers={'Foo': 'b', 'Cookie': 'foo=la', 'Connection': 'close'},
+ )['status'] = 210
+
+ def test_variables_dynamic_headers(self):
+ def check_header(header, status=210):
+ assert (
+ self.get(headers={header: "blah", 'Connection': 'close'})[
+ 'status'
+ ]
+ == status
+ )
+
+ self.conf_routes("\"routes/$header_foo_bar\"")
+ check_header('foo-bar')
+ check_header('Foo-Bar')
+ check_header('foo_bar', 404)
+ check_header('Foo', 404)
+ check_header('Bar', 404)
+ check_header('foobar', 404)
+
+ self.conf_routes("\"routes/$header_Foo_Bar\"")
+ check_header('Foo-Bar')
+ check_header('foo-bar')
+ check_header('foo_bar', 404)
+ check_header('foobar', 404)
+
+ self.conf_routes("\"routes/$header_foo-bar\"")
+ check_header('foo_bar', 404)
+
+ def test_variables_dynamic_arguments(self):
+ self.conf_routes("\"routes/$arg_foo_bar\"")
+ assert self.get(url='/?foo_bar=blah')['status'] == 210
+ assert self.get(url='/?foo_b%61r=blah')['status'] == 210
+ assert self.get(url='/?bar&foo_bar=blah&foo')['status'] == 210
+ assert self.get(url='/?Foo_bar=blah')['status'] == 404
+ assert self.get(url='/?foo-bar=blah')['status'] == 404
+ assert self.get()['status'] == 404
+ assert self.get(url='/?foo_bar=')['status'] == 404
+ assert self.get(url='/?foo_bar=l&foo_bar=blah')['status'] == 210
+ assert self.get(url='/?foo_bar=blah&foo_bar=l')['status'] == 404
+
+ self.conf_routes("\"routes/$arg_foo_b%61r\"")
+ assert self.get(url='/?foo_b=blah')['status'] == 404
+ assert self.get(url='/?foo_bar=blah')['status'] == 404
+
+ self.conf_routes("\"routes/$arg_f!~\"")
+ assert self.get(url='/?f=blah')['status'] == 404
+ assert self.get(url='/?f!~=blah')['status'] == 404
+
+ def test_variables_dynamic_cookies(self):
+ def check_cookie(cookie, status=210):
+ assert (
+ self.get(
+ headers={
+ 'Host': 'localhost',
+ 'Cookie': cookie,
+ 'Connection': 'close',
+ },
+ )['status']
+ == status
+ ), 'match cookie'
+
+ self.conf_routes("\"routes/$cookie_foo_bar\"")
+ check_cookie('foo_bar=blah', 210)
+ check_cookie('fOo_bar=blah', 404)
+ assert self.get()['status'] == 404
+ check_cookie('foo_bar', 404)
+ check_cookie('foo_bar=', 404)
+
def test_variables_invalid(self):
def check_variables(routes):
assert 'error' in self.conf(
@@ -137,3 +284,10 @@ class TestVariables(TestApplicationProto):
check_variables("\"routes$uriblah\"")
check_variables("\"routes${uri\"")
check_variables("\"routes${{uri}\"")
+ check_variables("\"routes$ar\"")
+ check_variables("\"routes$arg\"")
+ check_variables("\"routes$arg_\"")
+ check_variables("\"routes$cookie\"")
+ check_variables("\"routes$cookie_\"")
+ check_variables("\"routes$header\"")
+ check_variables("\"routes$header_\"")
diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py
index 04af26e1..3db955f3 100644
--- a/test/unit/applications/lang/go.py
+++ b/test/unit/applications/lang/go.py
@@ -9,6 +9,11 @@ from unit.option import option
class TestApplicationGo(TestApplicationProto):
@staticmethod
def prepare_env(script, name='app', static=False):
+ try:
+ subprocess.check_output(['which', 'go'])
+ except subprocess.CalledProcessError:
+ return None
+
temp_dir = option.temp_dir + '/go/'
if not os.path.exists(temp_dir):
diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py
index cd8672ba..f04ee408 100644
--- a/test/unit/applications/proto.py
+++ b/test/unit/applications/proto.py
@@ -13,21 +13,21 @@ class TestApplicationProto(TestControl):
def sec_epoch(self):
return time.mktime(time.gmtime())
- def date_to_sec_epoch(self, date, template='%a, %d %b %Y %H:%M:%S %Z'):
+ def date_to_sec_epoch(self, date, template='%a, %d %b %Y %X %Z'):
return time.mktime(time.strptime(date, template))
- def findall(self, pattern, name='unit.log'):
+ def findall(self, pattern, name='unit.log', flags=re.M):
with Log.open(name) as f:
- return re.findall(pattern, f.read())
+ return re.findall(pattern, f.read(), flags)
- def search_in_log(self, pattern, name='unit.log'):
+ def search_in_log(self, pattern, name='unit.log', flags=re.M):
with Log.open(name) as f:
- return re.search(pattern, f.read())
+ return re.search(pattern, f.read(), flags)
- def wait_for_record(self, pattern, name='unit.log', wait=150):
+ def wait_for_record(self, pattern, name='unit.log', wait=150, flags=re.M):
with Log.open(name) as f:
for i in range(wait):
- found = re.search(pattern, f.read())
+ found = re.search(pattern, f.read(), flags)
if found is not None:
break
diff --git a/test/unit/check/unix_abstract.py b/test/unit/check/unix_abstract.py
new file mode 100644
index 00000000..5d1f629e
--- /dev/null
+++ b/test/unit/check/unix_abstract.py
@@ -0,0 +1,25 @@
+import json
+
+from unit.http import TestHTTP
+from unit.option import option
+
+http = TestHTTP()
+
+
+def check_unix_abstract():
+ available = option.available
+
+ resp = http.put(
+ url='/config',
+ sock_type='unix',
+ addr=option.temp_dir + '/control.unit.sock',
+ body=json.dumps(
+ {
+ "listeners": {"unix:@sock": {"pass": "routes"}},
+ "routes": [],
+ }
+ ),
+ )
+
+ if 'success' in resp['body']:
+ available['features']['unix_abstract'] = True
diff --git a/test/unit/http.py b/test/unit/http.py
index b4a1a17b..b29667c9 100644
--- a/test/unit/http.py
+++ b/test/unit/http.py
@@ -51,7 +51,7 @@ class TestHTTP:
connect_args = addr if sock_type == 'unix' else (addr, port)
try:
sock.connect(connect_args)
- except ConnectionRefusedError:
+ except (ConnectionRefusedError, FileNotFoundError):
sock.close()
pytest.fail('Client can\'t connect to the server.')
@@ -209,9 +209,7 @@ class TestHTTP:
return {}
headers_text, body = m.group(1), m.group(2)
-
- p = re.compile('(.*?)\x0d\x0a?', re.M | re.S)
- headers_lines = p.findall(headers_text)
+ headers_lines = re.findall('(.*?)\x0d\x0a?', headers_text, re.M | re.S)
status = re.search(
r'^HTTP\/\d\.\d\s(\d+)|$', headers_lines.pop(0)
diff --git a/test/unit/status.py b/test/unit/status.py
new file mode 100644
index 00000000..17416f17
--- /dev/null
+++ b/test/unit/status.py
@@ -0,0 +1,45 @@
+from unit.control import TestControl
+
+
+class Status:
+ _status = None
+ control = TestControl()
+
+ def _check_zeros():
+ assert Status.control.conf_get('/status') == {
+ 'connections': {
+ 'accepted': 0,
+ 'active': 0,
+ 'idle': 0,
+ 'closed': 0,
+ },
+ 'requests': {'total': 0},
+ 'applications': {},
+ }
+
+ def init(status=None):
+ Status._status = (
+ status if status is not None else Status.control.conf_get('/status')
+ )
+
+ def diff():
+ def find_diffs(d1, d2):
+ if isinstance(d1, dict) and isinstance(d2, dict):
+ return {
+ k: find_diffs(d1.get(k, 0), d2.get(k, 0))
+ for k in d1
+ if k in d2
+ }
+ else:
+ return d1 - d2
+
+ return find_diffs(Status.control.conf_get('/status'), Status._status)
+
+ def get(path='/'):
+ path = path.split('/')[1:]
+ diff = Status.diff()
+
+ for p in path:
+ diff = diff[p]
+
+ return diff
diff --git a/version b/version
index 1d59a58f..df1f7c8e 100644
--- a/version
+++ b/version
@@ -1,5 +1,5 @@
# Copyright (C) NGINX, Inc.
-NXT_VERSION=1.27.0
-NXT_VERNUM=12700
+NXT_VERSION=1.28.0
+NXT_VERNUM=12800