summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrei Belov <defan@nginx.com>2018-10-25 19:00:07 +0300
committerAndrei Belov <defan@nginx.com>2018-10-25 19:00:07 +0300
commitdc3e83f26ce9f92a157d4332c723d531ca411b80 (patch)
treea723f2ce7d8c91527fdfb94eeae708292a705417
parent8b37c0c70a183f19f7f4245ce0825954d8dbcaf7 (diff)
parentfd99a738e586326ee5b40a6bc3d09c64b18f394a (diff)
downloadunit-1.5-1.tar.gz
unit-1.5-1.tar.bz2
Merged with the default branch.1.5-1
-rw-r--r--.hgtags1
-rw-r--r--CHANGES24
-rw-r--r--auto/help4
-rw-r--r--auto/make26
-rw-r--r--auto/modules/conf4
-rw-r--r--auto/modules/nodejs161
-rw-r--r--auto/options12
-rw-r--r--auto/save2
-rw-r--r--auto/sources4
-rw-r--r--auto/summary2
-rwxr-xr-xconfigure2
-rw-r--r--docs/changes.xml72
-rw-r--r--docs/changes.xsls5
-rw-r--r--docs/changes.xslt5
-rw-r--r--pkg/Makefile8
-rw-r--r--pkg/deb/Makefile2
-rw-r--r--pkg/deb/Makefile.go2
-rw-r--r--pkg/deb/Makefile.go1102
-rw-r--r--pkg/deb/Makefile.go172
-rw-r--r--pkg/deb/Makefile.go182
-rw-r--r--pkg/deb/Makefile.go192
-rw-r--r--pkg/deb/Makefile.perl2
-rw-r--r--pkg/deb/Makefile.php2
-rw-r--r--pkg/deb/Makefile.python2
-rw-r--r--pkg/deb/Makefile.python272
-rw-r--r--pkg/deb/Makefile.python342
-rw-r--r--pkg/deb/Makefile.python352
-rw-r--r--pkg/deb/Makefile.python362
-rw-r--r--pkg/deb/Makefile.ruby2
-rw-r--r--pkg/deb/debian.module/unit.example-go-config30
-rw-r--r--pkg/deb/debian.module/unit.example-go1.10-config30
-rw-r--r--pkg/deb/debian.module/unit.example-go1.7-config30
-rw-r--r--pkg/deb/debian.module/unit.example-go1.8-config30
-rw-r--r--pkg/deb/debian.module/unit.example-go1.9-config30
-rw-r--r--pkg/deb/debian/control8
-rw-r--r--pkg/deb/debian/rules.in8
-rw-r--r--pkg/deb/debian/unit.example.config102
-rw-r--r--pkg/docker/Dockerfile.full2
-rw-r--r--pkg/docker/Dockerfile.go1.7-dev2
-rw-r--r--pkg/docker/Dockerfile.go1.8-dev2
-rw-r--r--pkg/docker/Dockerfile.minimal2
-rw-r--r--pkg/docker/Dockerfile.perl5.242
-rw-r--r--pkg/docker/Dockerfile.php7.02
-rw-r--r--pkg/docker/Dockerfile.python2.72
-rw-r--r--pkg/docker/Dockerfile.python3.52
-rw-r--r--pkg/docker/Dockerfile.ruby2.32
-rw-r--r--pkg/docker/Makefile2
-rw-r--r--pkg/npm/Makefile27
-rw-r--r--pkg/rpm/Makefile2
-rw-r--r--pkg/rpm/Makefile.go2
-rw-r--r--pkg/rpm/Makefile.perl2
-rw-r--r--pkg/rpm/Makefile.php2
-rw-r--r--pkg/rpm/Makefile.python2
-rw-r--r--pkg/rpm/Makefile.python272
-rw-r--r--pkg/rpm/Makefile.python342
-rw-r--r--pkg/rpm/Makefile.python352
-rw-r--r--pkg/rpm/Makefile.python362
-rw-r--r--pkg/rpm/Makefile.ruby2
-rw-r--r--pkg/rpm/rpmbuild/SOURCES/unit.example-go-config2
-rw-r--r--pkg/rpm/rpmbuild/SOURCES/unit.example.config2
-rw-r--r--pkg/rpm/unit.spec.in20
-rw-r--r--src/go/unit/nxt_cgo_lib.c2
-rw-r--r--src/go/unit/port.go2
-rw-r--r--src/nodejs/unit-http/README.md21
-rw-r--r--src/nodejs/unit-http/addon.cpp15
-rw-r--r--src/nodejs/unit-http/binding.gyp12
-rw-r--r--src/nodejs/unit-http/binding_pub.gyp7
-rwxr-xr-xsrc/nodejs/unit-http/http.js23
-rwxr-xr-xsrc/nodejs/unit-http/http_server.js331
-rw-r--r--src/nodejs/unit-http/package.json29
-rwxr-xr-xsrc/nodejs/unit-http/socket.js99
-rw-r--r--src/nodejs/unit-http/unit.cpp905
-rw-r--r--src/nodejs/unit-http/unit.h77
-rw-r--r--src/nxt_app_log.c2
-rw-r--r--src/nxt_application.c8
-rw-r--r--src/nxt_application.h26
-rw-r--r--src/nxt_conf_validation.c32
-rw-r--r--src/nxt_conn.h2
-rw-r--r--src/nxt_conn_read.c4
-rw-r--r--src/nxt_conn_write.c4
-rw-r--r--src/nxt_epoll_engine.c60
-rw-r--r--src/nxt_event_engine.h2
-rw-r--r--src/nxt_external.c (renamed from src/nxt_go.c)45
-rw-r--r--src/nxt_h1proto.c11
-rw-r--r--src/nxt_http.h1
-rw-r--r--src/nxt_http_request.c2
-rw-r--r--src/nxt_main.h4
-rw-r--r--src/nxt_main_process.c42
-rw-r--r--src/nxt_openssl.c2
-rw-r--r--src/nxt_port.c2
-rw-r--r--src/nxt_router.c6
-rw-r--r--src/nxt_runtime.c18
-rw-r--r--src/nxt_runtime.h1
-rw-r--r--src/nxt_timer.c180
-rw-r--r--src/nxt_timer.h44
-rw-r--r--src/nxt_unit.c20
-rw-r--r--src/nxt_worker_process.c4
-rw-r--r--test/test_python_application.py1
-rw-r--r--test/test_tls.py3
-rw-r--r--test/unit.py2
100 files changed, 2348 insertions, 422 deletions
diff --git a/.hgtags b/.hgtags
index 067bb0f9..0bcf5546 100644
--- a/.hgtags
+++ b/.hgtags
@@ -11,3 +11,4 @@ fbe7f5a3867e9559ef0884786fe5150aa60414e6 1.2
b3cf22b8a17e0e35ca80decb03ed2cceb662c3de 1.3
8f4524a9cf87fbddf626302da071f5055cf33f28 1.4
99d69d59aa5edee3405d304886d9319291e392ba 1.4-2
+b3dee0cc5a4edd046345511769b5cfec49044f1c 1.5
diff --git a/CHANGES b/CHANGES
index 50b9a026..b1047284 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,28 @@
+Changes with Unit 1.5 25 Oct 2018
+
+ *) Change: the "type" of application object for Go was changed to
+ "external".
+
+ *) Feature: initial version of Node.js package with basic HTTP
+ request-response support.
+
+ *) Feature: compatibility with LibreSSL.
+
+ *) Feature: --libdir and --incdir ./configure options to install libunit
+ headers and static library.
+
+ *) Bugfix: connection might be closed prematurely while sending
+ response; the bug had appeared in 1.3.
+
+ *) Bugfix: application processes might have stopped handling requests,
+ producing "last message send failed: Resource temporarily
+ unavailable" alerts in log; the bug had appeared in 1.4.
+
+ *) Bugfix: Go applications didn't work when Unit was built with musl C
+ library.
+
+
Changes with Unit 1.4 20 Sep 2018
*) Change: the control API maps the configuration object only at
diff --git a/auto/help b/auto/help
index 98c877fb..91be220f 100644
--- a/auto/help
+++ b/auto/help
@@ -16,6 +16,8 @@ cat << END
default: "$NXT_BINDIR"
--sbindir=DIRECTORY set system admin executables directory name
default: "$NXT_SBINDIR"
+ --libdir=DIRECTORY set library directory name, default: "$NXT_LIBDIR"
+ --incdir=DIRECTORY set includes directory name, default: "$NXT_INCDIR"
--modules=DIRECTORY set modules directory name, default: "$NXT_MODULES"
--state=DIRECTORY set state directory name, default: "$NXT_STATE"
@@ -33,6 +35,8 @@ cat << END
--no-ipv6 disable IPv6 support
--no-unix-sockets disable Unix domain sockets support
+ --openssl enable OpenSSL library usage
+
--debug enable debug logging
diff --git a/auto/make b/auto/make
index bace16e9..5bbca9e4 100644
--- a/auto/make
+++ b/auto/make
@@ -277,6 +277,32 @@ ${NXT_DAEMON}-uninstall:
END
+cat << END >> $NXT_MAKEFILE
+
+.PHONY: libunit-install libunit-uninstall
+
+libunit-install: $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC
+ install -d \$(DESTDIR)$NXT_LIBDIR
+ install -p -m u=rw,go=r $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC \
+ \$(DESTDIR)$NXT_LIBDIR/
+ install -d \$(DESTDIR)$NXT_INCDIR
+ install -p -m u=rw,go=r src/nxt_unit.h src/nxt_unit_field.h \
+ src/nxt_unit_request.h src/nxt_unit_response.h src/nxt_unit_sptr.h \
+ src/nxt_unit_typedefs.h \$(DESTDIR)$NXT_INCDIR/
+
+libunit-uninstall:
+ rm -f \$(DESTDIR)$NXT_LIBDIR/$NXT_LIB_UNIT_STATIC
+ @rmdir -p \$(DESTDIR)$NXT_LIBDIR 2>/dev/null || true
+ rm -f \$(DESTDIR)$NXT_INCDIR/nxt_unit.h \
+ \$(DESTDIR)$NXT_INCDIR/nxt_unit_field.h \
+ \$(DESTDIR)$NXT_INCDIR/nxt_unit_request.h \
+ \$(DESTDIR)$NXT_INCDIR/nxt_unit_response.h \
+ \$(DESTDIR)$NXT_INCDIR/nxt_unit_sptr.h \
+ \$(DESTDIR)$NXT_INCDIR/nxt_unit_typedefs.h
+ @rmdir -p \$(DESTDIR)$NXT_INCDIR 2>/dev/null || true
+
+END
+
# Makefile.
# *.dSYM is MacOSX Clang debug information.
diff --git a/auto/modules/conf b/auto/modules/conf
index 93d28601..409b4bea 100644
--- a/auto/modules/conf
+++ b/auto/modules/conf
@@ -25,6 +25,10 @@ case "$nxt_module" in
. auto/modules/ruby
;;
+ nodejs)
+ . auto/modules/nodejs
+ ;;
+
*)
echo
echo $0: error: invalid module \"$nxt_module\".
diff --git a/auto/modules/nodejs b/auto/modules/nodejs
new file mode 100644
index 00000000..56f84876
--- /dev/null
+++ b/auto/modules/nodejs
@@ -0,0 +1,161 @@
+
+# Copyright (C) NGINX, Inc.
+
+
+shift
+
+for nxt_option; do
+
+ case "$nxt_option" in
+ -*=*) value=`echo "$nxt_option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) value="" ;;
+ esac
+
+ case "$nxt_option" in
+ --node=*) NXT_NODE="$value" ;;
+ --npm=*) NXT_NPM="$value" ;;
+ --node-gyp=*) NXT_NODE_GYP="$value" ;;
+
+ --help)
+ cat << END
+
+ --node=NAME set node executable
+ --npm=NAME set npm executable
+ --node-gyp=NAME set node-gyp executable
+
+END
+ exit 0
+ ;;
+
+ *)
+ echo
+ echo $0: error: invalid Node option \"$nxt_option\"
+ echo
+ exit 1
+ ;;
+
+ esac
+
+done
+
+
+if [ ! -f $NXT_AUTOCONF_DATA ]; then
+ echo
+ echo Please run common $0 before configuring module \"$nxt_module\".
+ echo
+ exit 1
+fi
+
+. $NXT_AUTOCONF_DATA
+
+
+$echo "configuring nodejs module"
+$echo "configuring nodejs module..." >> $NXT_AUTOCONF_ERR
+
+NXT_NODE=${NXT_NODE=node}
+NXT_NPM=${NXT_NPM=npm}
+NXT_NODE_GYP=${NXT_NODE_GYP=node-gyp}
+
+$echo -n "checking for node ..."
+$echo "checking for node ..." >> $NXT_AUTOCONF_ERR
+
+if /bin/sh -c "${NXT_NODE} -v" >> $NXT_AUTOCONF_ERR 2>&1; then
+ $echo " found"
+
+ NXT_NODE_VERSION="`${NXT_NODE} -v`"
+ $echo " + node version ${NXT_NODE_VERSION}"
+
+else
+ $echo " not found"
+ $echo
+ $echo $0: error: no Node found.
+ $echo
+ exit 1;
+fi
+
+$echo -n "checking for npm ..."
+$echo "checking for npm ..." >> $NXT_AUTOCONF_ERR
+
+if /bin/sh -c "${NXT_NPM} -v" >> $NXT_AUTOCONF_ERR 2>&1; then
+ $echo " found"
+
+ NXT_NPM_VERSION="`${NXT_NPM} -v`"
+ $echo " + npm version ${NXT_NPM_VERSION}"
+
+else
+ $echo " not found"
+ $echo
+ $echo $0: error: no npm found.
+ $echo
+ exit 1;
+fi
+
+$echo -n "checking for node-gyp ..."
+$echo "checking for node-gyp ..." >> $NXT_AUTOCONF_ERR
+
+if /bin/sh -c "${NXT_NODE_GYP} -v" >> $NXT_AUTOCONF_ERR 2>&1; then
+ $echo " found"
+
+ NXT_NODE_GYP_VERSION="`${NXT_NODE_GYP} -v`"
+ $echo " + node-gyp version ${NXT_NODE_GYP_VERSION}"
+
+else
+ $echo " not found"
+ $echo
+ $echo $0: error: no node-gyp found.
+ $echo
+ exit 1;
+fi
+
+if grep ^$NXT_NODE: $NXT_MAKEFILE 2>&1 > /dev/null; then
+ $echo
+ $echo $0: error: duplicate \"$NXT_NODE\" package configured.
+ $echo
+ exit 1;
+fi
+
+NXT_NODE_TMP=${NXT_BUILD_DIR}/src/${NXT_NODE}/unit-http
+NXT_NODE_TARBALL=${NXT_BUILD_DIR}/${NXT_NODE}-unit-http.tar.gz
+NXT_NODE_EXPORTS="export UNIT_SRC_PATH=${PWD}/src && \
+ export UNIT_LIB_STATIC_PATH=${PWD}/${NXT_BUILD_DIR}/libunit.a"
+
+cat << END >> $NXT_MAKEFILE
+
+.PHONY: ${NXT_NODE}
+.PHONY: ${NXT_NODE}-copy
+.PHONY: ${NXT_NODE}-install
+.PHONY: ${NXT_NODE}-uninstall
+
+all:
+
+${NXT_NODE}: ${NXT_NODE}-copy $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC
+ ${NXT_NODE_EXPORTS} && \\
+ cd ${NXT_NODE_TMP} && ${NXT_NODE_GYP} configure build clean
+
+${NXT_NODE}-copy:
+ mkdir -p ${NXT_BUILD_DIR}/src/
+ cp -rp src/nodejs/ ${NXT_BUILD_DIR}/src/${NXT_NODE}
+
+${NXT_NODE_TARBALL}: ${NXT_NODE}-copy
+ tar -zcvf ${NXT_NODE_TARBALL} -C ${NXT_NODE_TMP} .
+
+${NXT_NODE}-install: ${NXT_NODE_TARBALL} \
+ $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC
+ ${NXT_NODE_EXPORTS} && \\
+ ${NXT_NPM} install -g ${PWD}/${NXT_NODE_TARBALL} --unsafe-perm=true
+
+${NXT_NODE}-local-install: ${NXT_NODE_TARBALL} \
+ $NXT_BUILD_DIR/$NXT_LIB_UNIT_STATIC
+ ${NXT_NODE_EXPORTS} && \\
+ mkdir -p \$(DESTDIR) && \\
+ cd \$(DESTDIR) && ${NXT_NPM} install ${PWD}/${NXT_NODE_TARBALL}
+
+${NXT_NODE}-build: ${NXT_NODE}
+
+${NXT_NODE}-publish: ${NXT_NODE}
+ cd ${NXT_NODE_TMP} && ${NXT_NPM} publish
+
+${NXT_NODE}-uninstall:
+ ${NXT_NPM} uninstall -g unit-http
+
+END
diff --git a/auto/options b/auto/options
index eadfb198..0d31abad 100644
--- a/auto/options
+++ b/auto/options
@@ -54,6 +54,8 @@ do
--prefix=*) NXT_PREFIX="$value" ;;
--bindir=*) NXT_BINDIR="$value" ;;
--sbindir=*) NXT_SBINDIR="$value" ;;
+ --libdir=*) NXT_LIBDIR="$value" ;;
+ --incdir=*) NXT_INCDIR="$value" ;;
--modules=*) NXT_MODULES="$value" ;;
--state=*) NXT_STATE="$value" ;;
@@ -127,6 +129,16 @@ case "$NXT_SBINDIR" in
*) NXT_SBINDIR="$NXT_PREFIX$NXT_SBINDIR" ;;
esac
+case "$NXT_LIBDIR" in
+ /*) ;;
+ *) NXT_LIBDIR="$NXT_PREFIX$NXT_LIBDIR" ;;
+esac
+
+case "$NXT_INCDIR" in
+ /*) ;;
+ *) NXT_INCDIR="$NXT_PREFIX$NXT_INCDIR" ;;
+esac
+
case "$NXT_MODULES" in
/*) ;;
*) NXT_MODULES="$NXT_PREFIX$NXT_MODULES" ;;
diff --git a/auto/save b/auto/save
index 3a04a698..350c9c1f 100644
--- a/auto/save
+++ b/auto/save
@@ -26,6 +26,8 @@ echo=$NXT_BUILD_DIR/echo
NXT_LIB_AUX_CFLAGS=
NXT_LIB_AUX_LIBS=
+NXT_LIB_UNIT_STATIC='$NXT_LIB_UNIT_STATIC'
+
NXT_MODULES='$NXT_MODULES'
END
diff --git a/auto/sources b/auto/sources
index e7074345..bc979fe2 100644
--- a/auto/sources
+++ b/auto/sources
@@ -74,7 +74,6 @@ NXT_LIB_SRCS=" \
src/nxt_runtime.c \
src/nxt_conf.c \
src/nxt_conf_validation.c \
- src/nxt_stream_module.c \
src/nxt_main_process.c \
src/nxt_worker_process.c \
src/nxt_controller.c \
@@ -84,13 +83,14 @@ NXT_LIB_SRCS=" \
src/nxt_http_response.c \
src/nxt_http_error.c \
src/nxt_application.c \
- src/nxt_go.c \
+ src/nxt_external.c \
src/nxt_port_hash.c \
"
NXT_LIB_SRC0=" \
src/nxt_buf_filter.c \
src/nxt_job_file.c \
+ src/nxt_stream_module.c \
src/nxt_stream_source.c \
src/nxt_upstream_source.c \
src/nxt_http_source.c \
diff --git a/auto/summary b/auto/summary
index 695b21f7..ce6b42db 100644
--- a/auto/summary
+++ b/auto/summary
@@ -9,6 +9,8 @@ Configuration summary:
unit bin directory: "$NXT_BINDIR"
unit sbin directory: "$NXT_SBINDIR"
+ unit lib directory: "$NXT_LIBDIR"
+ unit include directory: "$NXT_INCDIR"
unit modules directory: "$NXT_MODULES"
unit state directory: "$NXT_STATE"
diff --git a/configure b/configure
index db64cb1e..13f2db6b 100755
--- a/configure
+++ b/configure
@@ -32,6 +32,8 @@ CC=${CC:-cc}
NXT_DAEMON=unitd
NXT_BINDIR="bin"
NXT_SBINDIR="sbin"
+NXT_LIBDIR="lib"
+NXT_INCDIR="include"
NXT_MODULES="modules"
NXT_STATE="state"
NXT_PID="unit.pid"
diff --git a/docs/changes.xml b/docs/changes.xml
index fae63a2a..5be0a94e 100644
--- a/docs/changes.xml
+++ b/docs/changes.xml
@@ -11,6 +11,78 @@
unit-go unit-go1.7 unit-go1.8 unit-go1.9 unit-go1.10
unit-perl
unit-ruby"
+ ver="1.5" rev="1"
+ date="2018-10-25" time="18:00:00 +0300"
+ packager="Andrei Belov &lt;defan@nginx.com&gt;">
+
+<change>
+<para>
+NGINX Unit updated to 1.5.
+</para>
+</change>
+
+</changes>
+
+
+<changes apply="unit" ver="1.5" rev="1"
+ date="2018-10-25" time="18:00:00 +0300"
+ packager="Andrei Belov &lt;defan@nginx.com&gt;">
+
+<change type="change">
+<para>
+the "type" of application object for Go was changed to "external".
+</para>
+</change>
+
+<change type="feature">
+<para>
+initial version of Node.js package with basic HTTP request-response support.
+</para>
+</change>
+
+<change type="feature">
+<para>
+compatibility with LibreSSL.
+</para>
+</change>
+
+<change type="feature">
+<para>
+--libdir and --incdir ./configure options to install libunit headers
+and static library.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+connection might be closed prematurely while sending response;
+the bug had appeared in 1.3.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+application processes might have stopped handling requests, producing
+"last message send failed: Resource temporarily unavailable" alerts in log;
+the bug had appeared in 1.4.
+</para>
+</change>
+
+<change type="bugfix">
+<para>
+Go applications didn't work when Unit was built with musl C library.
+</para>
+</change>
+
+</changes>
+
+
+<changes apply="unit-php
+ unit-python unit-python2.7
+ unit-python3.4 unit-python3.5 unit-python3.6
+ unit-go unit-go1.7 unit-go1.8 unit-go1.9 unit-go1.10
+ unit-perl
+ unit-ruby"
ver="1.4" rev="2"
date="2018-09-27" time="13:30:00 +0300"
packager="Andrei Belov &lt;defan@nginx.com&gt;">
diff --git a/docs/changes.xsls b/docs/changes.xsls
index f2ba1c8e..2f3bcc46 100644
--- a/docs/changes.xsls
+++ b/docs/changes.xsls
@@ -63,6 +63,9 @@ X:template = "changes" {
X:var apply = { !string_in_list(list="@apply", string="$pkgname") }
X:var pkgname_ = { !beautify(pkgname="$pkgname") }
+ X:choose {
+ X:when "$pkgname='unit' and $format='generic' and @rev!=1" {}
+ X:otherwise {
X:if "$apply=$pkgname" {
X:if "$format='generic'" {
@@ -112,6 +115,8 @@ X:template = "changes" {
X:text {&#10;}
}
}
+ }
+ }
}
diff --git a/docs/changes.xslt b/docs/changes.xslt
index 22abb656..032d5c37 100644
--- a/docs/changes.xslt
+++ b/docs/changes.xslt
@@ -64,6 +64,9 @@
<xsl:variable name="apply"> <xsl:call-template name="string_in_list"><xsl:with-param select="@apply" name="list"/><xsl:with-param select="$pkgname" name="string"/></xsl:call-template></xsl:variable>
<xsl:variable name="pkgname_"> <xsl:call-template name="beautify"><xsl:with-param select="$pkgname" name="pkgname"/></xsl:call-template></xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$pkgname='unit' and $format='generic' and @rev!=1"/>
+ <xsl:otherwise>
<xsl:if test="$apply=$pkgname">
<xsl:if test="$format='generic'">
@@ -113,6 +116,8 @@
<xsl:text>&#10;</xsl:text>
</xsl:if>
</xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:template>
diff --git a/pkg/Makefile b/pkg/Makefile
index f5cfd3c2..6001a034 100644
--- a/pkg/Makefile
+++ b/pkg/Makefile
@@ -6,7 +6,7 @@ VERSION ?= $(shell grep 'define NXT_VERSION' ../src/nxt_main.h \
RELEASE ?= 1
default:
- @echo "available targets: dist rpm deb docker"
+ @echo "available targets: dist rpm deb docker npm"
dist:
rm -f unit-$(VERSION).tar.gz
@@ -24,9 +24,13 @@ deb:
docker:
@cd docker && VERSION=$(VERSION) RELEASE=$(RELEASE) make all
+npm:
+ @cd npm && VERSION=$(VERSION) RELEASE=$(RELEASE) make all
+
clean:
@cd rpm && make clean
@cd deb && make clean
@cd docker && make clean
+ @cd npm && make clean
-.PHONY: default rpm deb docker clean
+.PHONY: default rpm deb docker npm clean
diff --git a/pkg/deb/Makefile b/pkg/deb/Makefile
index 6ed1c94a..735f283b 100644
--- a/pkg/deb/Makefile
+++ b/pkg/deb/Makefile
@@ -3,7 +3,7 @@
DEFAULT_VERSION := $(shell grep 'define NXT_VERSION' ../../src/nxt_main.h \
| sed -e 's/^.*"\(.*\)".*/\1/')
-DEFAULT_RELEASE := 2
+DEFAULT_RELEASE := 1
VERSION ?= $(DEFAULT_VERSION)
RELEASE ?= $(DEFAULT_RELEASE)
diff --git a/pkg/deb/Makefile.go b/pkg/deb/Makefile.go
index 66792a55..2d7d6537 100644
--- a/pkg/deb/Makefile.go
+++ b/pkg/deb/Makefile.go
@@ -4,7 +4,7 @@ MODULE_SUFFIX_go= go
MODULE_SUMMARY_go= Go module for NGINX Unit
MODULE_VERSION_go= $(VERSION)
-MODULE_RELEASE_go= 2
+MODULE_RELEASE_go= 1
MODULE_CONFARGS_go= go --go-path=/usr/share/gocode
MODULE_MAKEARGS_go= go
diff --git a/pkg/deb/Makefile.go110 b/pkg/deb/Makefile.go110
index e4883af4..863f7c90 100644
--- a/pkg/deb/Makefile.go110
+++ b/pkg/deb/Makefile.go110
@@ -4,7 +4,7 @@ MODULE_SUFFIX_go110= go1.10
MODULE_SUMMARY_go110= Go 1.10 module for NGINX Unit
MODULE_VERSION_go110= $(VERSION)
-MODULE_RELEASE_go110= 2
+MODULE_RELEASE_go110= 1
MODULE_CONFARGS_go110= go --go=/usr/lib/go-1.10/bin/go --go-path=/usr/share/gocode
MODULE_MAKEARGS_go110= /usr/lib/go-1.10/bin/go
diff --git a/pkg/deb/Makefile.go17 b/pkg/deb/Makefile.go17
index 74084b49..201b32b2 100644
--- a/pkg/deb/Makefile.go17
+++ b/pkg/deb/Makefile.go17
@@ -4,7 +4,7 @@ MODULE_SUFFIX_go17= go1.7
MODULE_SUMMARY_go17= Go 1.7 module for NGINX Unit
MODULE_VERSION_go17= $(VERSION)
-MODULE_RELEASE_go17= 2
+MODULE_RELEASE_go17= 1
MODULE_CONFARGS_go17= go --go=/usr/lib/go-1.7/bin/go --go-path=/usr/share/gocode
MODULE_MAKEARGS_go17= /usr/lib/go-1.7/bin/go
diff --git a/pkg/deb/Makefile.go18 b/pkg/deb/Makefile.go18
index aaaae40d..70b155d4 100644
--- a/pkg/deb/Makefile.go18
+++ b/pkg/deb/Makefile.go18
@@ -4,7 +4,7 @@ MODULE_SUFFIX_go18= go1.8
MODULE_SUMMARY_go18= Go 1.8 module for NGINX Unit
MODULE_VERSION_go18= $(VERSION)
-MODULE_RELEASE_go18= 2
+MODULE_RELEASE_go18= 1
MODULE_CONFARGS_go18= go --go=/usr/lib/go-1.8/bin/go --go-path=/usr/share/gocode
MODULE_MAKEARGS_go18= /usr/lib/go-1.8/bin/go
diff --git a/pkg/deb/Makefile.go19 b/pkg/deb/Makefile.go19
index aef41844..9ddcc493 100644
--- a/pkg/deb/Makefile.go19
+++ b/pkg/deb/Makefile.go19
@@ -4,7 +4,7 @@ MODULE_SUFFIX_go19= go1.9
MODULE_SUMMARY_go19= Go 1.9 module for NGINX Unit
MODULE_VERSION_go19= $(VERSION)
-MODULE_RELEASE_go19= 2
+MODULE_RELEASE_go19= 1
MODULE_CONFARGS_go19= go --go=/usr/lib/go-1.9/bin/go --go-path=/usr/share/gocode
MODULE_MAKEARGS_go19= /usr/lib/go-1.9/bin/go
diff --git a/pkg/deb/Makefile.perl b/pkg/deb/Makefile.perl
index 31aa976a..186b8e5a 100644
--- a/pkg/deb/Makefile.perl
+++ b/pkg/deb/Makefile.perl
@@ -4,7 +4,7 @@ MODULE_SUFFIX_perl= perl
MODULE_SUMMARY_perl= Perl module for NGINX Unit
MODULE_VERSION_perl= $(VERSION)
-MODULE_RELEASE_perl= 2
+MODULE_RELEASE_perl= 1
MODULE_CONFARGS_perl= perl
MODULE_MAKEARGS_perl= perl
diff --git a/pkg/deb/Makefile.php b/pkg/deb/Makefile.php
index 4f76e13d..193670e7 100644
--- a/pkg/deb/Makefile.php
+++ b/pkg/deb/Makefile.php
@@ -4,7 +4,7 @@ MODULE_SUFFIX_php= php
MODULE_SUMMARY_php= PHP module for NGINX Unit
MODULE_VERSION_php= $(VERSION)
-MODULE_RELEASE_php= 2
+MODULE_RELEASE_php= 1
MODULE_CONFARGS_php= php
MODULE_MAKEARGS_php= php
diff --git a/pkg/deb/Makefile.python b/pkg/deb/Makefile.python
index d4822c84..dec64b26 100644
--- a/pkg/deb/Makefile.python
+++ b/pkg/deb/Makefile.python
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python= python
MODULE_SUMMARY_python= Python module for NGINX Unit
MODULE_VERSION_python= $(VERSION)
-MODULE_RELEASE_python= 2
+MODULE_RELEASE_python= 1
MODULE_CONFARGS_python= python
MODULE_MAKEARGS_python= python
diff --git a/pkg/deb/Makefile.python27 b/pkg/deb/Makefile.python27
index d9dee872..ae1ae4c0 100644
--- a/pkg/deb/Makefile.python27
+++ b/pkg/deb/Makefile.python27
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python27= python2.7
MODULE_SUMMARY_python27= Python 2.7 module for NGINX Unit
MODULE_VERSION_python27= $(VERSION)
-MODULE_RELEASE_python27= 2
+MODULE_RELEASE_python27= 1
MODULE_CONFARGS_python27= python --config=python2.7-config
MODULE_MAKEARGS_python27= python2.7
diff --git a/pkg/deb/Makefile.python34 b/pkg/deb/Makefile.python34
index 7a9db98a..5e043ef4 100644
--- a/pkg/deb/Makefile.python34
+++ b/pkg/deb/Makefile.python34
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python34= python3.4
MODULE_SUMMARY_python34= Python 3.4 module for NGINX Unit
MODULE_VERSION_python34= $(VERSION)
-MODULE_RELEASE_python34= 2
+MODULE_RELEASE_python34= 1
MODULE_CONFARGS_python34= python --config=python3.4-config
MODULE_MAKEARGS_python34= python3.4
diff --git a/pkg/deb/Makefile.python35 b/pkg/deb/Makefile.python35
index 60256680..557690a9 100644
--- a/pkg/deb/Makefile.python35
+++ b/pkg/deb/Makefile.python35
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python35= python3.5
MODULE_SUMMARY_python35= Python 3.5 module for NGINX Unit
MODULE_VERSION_python35= $(VERSION)
-MODULE_RELEASE_python35= 2
+MODULE_RELEASE_python35= 1
MODULE_CONFARGS_python35= python --config=python3.5-config
MODULE_MAKEARGS_python35= python3.5
diff --git a/pkg/deb/Makefile.python36 b/pkg/deb/Makefile.python36
index 5f912ac1..07cbba90 100644
--- a/pkg/deb/Makefile.python36
+++ b/pkg/deb/Makefile.python36
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python36= python3.6
MODULE_SUMMARY_python36= Python 3.6 module for NGINX Unit
MODULE_VERSION_python36= $(VERSION)
-MODULE_RELEASE_python36= 2
+MODULE_RELEASE_python36= 1
MODULE_CONFARGS_python36= python --config=python3.6-config
MODULE_MAKEARGS_python36= python3.6
diff --git a/pkg/deb/Makefile.ruby b/pkg/deb/Makefile.ruby
index 48ac4ede..1cb6baab 100644
--- a/pkg/deb/Makefile.ruby
+++ b/pkg/deb/Makefile.ruby
@@ -4,7 +4,7 @@ MODULE_SUFFIX_ruby= ruby
MODULE_SUMMARY_ruby= Ruby module for NGINX Unit
MODULE_VERSION_ruby= $(VERSION)
-MODULE_RELEASE_ruby= 2
+MODULE_RELEASE_ruby= 1
MODULE_CONFARGS_ruby= ruby
MODULE_MAKEARGS_ruby= ruby
diff --git a/pkg/deb/debian.module/unit.example-go-config b/pkg/deb/debian.module/unit.example-go-config
index 6ee4d001..079ce0b8 100644
--- a/pkg/deb/debian.module/unit.example-go-config
+++ b/pkg/deb/debian.module/unit.example-go-config
@@ -1,15 +1,15 @@
-{
- "applications": {
- "example_go": {
- "type": "go",
- "user": "nobody",
- "executable": "/tmp/go-app"
- }
- },
-
- "listeners": {
- "*:8500": {
- "application": "example_go"
- }
- }
-}
+{
+ "applications": {
+ "example_go": {
+ "type": "external",
+ "user": "nobody",
+ "executable": "/tmp/go-app"
+ }
+ },
+
+ "listeners": {
+ "*:8500": {
+ "application": "example_go"
+ }
+ }
+}
diff --git a/pkg/deb/debian.module/unit.example-go1.10-config b/pkg/deb/debian.module/unit.example-go1.10-config
index 68733256..29bb9059 100644
--- a/pkg/deb/debian.module/unit.example-go1.10-config
+++ b/pkg/deb/debian.module/unit.example-go1.10-config
@@ -1,15 +1,15 @@
-{
- "applications": {
- "example_go": {
- "type": "go",
- "user": "nobody",
- "executable": "/tmp/go1.10-app"
- }
- },
-
- "listeners": {
- "*:8500": {
- "application": "example_go"
- }
- }
-}
+{
+ "applications": {
+ "example_go": {
+ "type": "external",
+ "user": "nobody",
+ "executable": "/tmp/go1.10-app"
+ }
+ },
+
+ "listeners": {
+ "*:8500": {
+ "application": "example_go"
+ }
+ }
+}
diff --git a/pkg/deb/debian.module/unit.example-go1.7-config b/pkg/deb/debian.module/unit.example-go1.7-config
index 1b1943e0..bd98fe3a 100644
--- a/pkg/deb/debian.module/unit.example-go1.7-config
+++ b/pkg/deb/debian.module/unit.example-go1.7-config
@@ -1,15 +1,15 @@
-{
- "applications": {
- "example_go": {
- "type": "go",
- "user": "nobody",
- "executable": "/tmp/go1.7-app"
- }
- },
-
- "listeners": {
- "*:8500": {
- "application": "example_go"
- }
- }
-}
+{
+ "applications": {
+ "example_go": {
+ "type": "external",
+ "user": "nobody",
+ "executable": "/tmp/go1.7-app"
+ }
+ },
+
+ "listeners": {
+ "*:8500": {
+ "application": "example_go"
+ }
+ }
+}
diff --git a/pkg/deb/debian.module/unit.example-go1.8-config b/pkg/deb/debian.module/unit.example-go1.8-config
index 6cfa0cec..1c14ca25 100644
--- a/pkg/deb/debian.module/unit.example-go1.8-config
+++ b/pkg/deb/debian.module/unit.example-go1.8-config
@@ -1,15 +1,15 @@
-{
- "applications": {
- "example_go": {
- "type": "go",
- "user": "nobody",
- "executable": "/tmp/go1.8-app"
- }
- },
-
- "listeners": {
- "*:8500": {
- "application": "example_go"
- }
- }
-}
+{
+ "applications": {
+ "example_go": {
+ "type": "external",
+ "user": "nobody",
+ "executable": "/tmp/go1.8-app"
+ }
+ },
+
+ "listeners": {
+ "*:8500": {
+ "application": "example_go"
+ }
+ }
+}
diff --git a/pkg/deb/debian.module/unit.example-go1.9-config b/pkg/deb/debian.module/unit.example-go1.9-config
index 4074df3b..341894b7 100644
--- a/pkg/deb/debian.module/unit.example-go1.9-config
+++ b/pkg/deb/debian.module/unit.example-go1.9-config
@@ -1,15 +1,15 @@
-{
- "applications": {
- "example_go": {
- "type": "go",
- "user": "nobody",
- "executable": "/tmp/go1.9-app"
- }
- },
-
- "listeners": {
- "*:8500": {
- "application": "example_go"
- }
- }
-}
+{
+ "applications": {
+ "example_go": {
+ "type": "external",
+ "user": "nobody",
+ "executable": "/tmp/go1.9-app"
+ }
+ },
+
+ "listeners": {
+ "*:8500": {
+ "application": "example_go"
+ }
+ }
+}
diff --git a/pkg/deb/debian/control b/pkg/deb/debian/control
index e1b1bde8..c0873a1c 100644
--- a/pkg/deb/debian/control
+++ b/pkg/deb/debian/control
@@ -29,3 +29,11 @@ Depends: unit (= ${binary:Version}),
${misc:Depends}
Description: NGINX Unit (debug symbols)
This package contains the debugging symbols for NGINX Unit.
+
+Package: unit-dev
+Section: libdevel
+Priority: optional
+Architecture: any
+Depends: ${misc:Depends}
+Description: NGINX Unit (development files)
+ Library and include files required for NGINX Unit modules development.
diff --git a/pkg/deb/debian/rules.in b/pkg/deb/debian/rules.in
index a9f68189..7eab391d 100644
--- a/pkg/deb/debian/rules.in
+++ b/pkg/deb/debian/rules.in
@@ -9,9 +9,12 @@ export DEB_LDFLAGS_MAINT_APPEND=-Wl,--as-needed -pie
DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/buildflags.mk
+DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
+
BUILDDIR_unit = $(CURDIR)/debian/build-unit
BUILDDIR_unit_debug = $(CURDIR)/debian/build-unit-debug
INSTALLDIR = $(CURDIR)/debian/unit
+INSTALLDIR_dev = $(CURDIR)/debian/unit-dev
BASEDIR = $(CURDIR)
DOTESTS = 0
@@ -30,6 +33,7 @@ configure.unit: config.env.unit
CFLAGS= ./configure \
%%CONFIGURE_ARGS%% \
--modules=/usr/lib/unit/modules \
+ --libdir=/usr/lib/$(DEB_HOST_MULTIARCH) \
--cc-opt="$(CFLAGS)" \
--ld-opt="$(LDFLAGS)"
touch $@
@@ -39,6 +43,7 @@ configure.unit_debug: config.env.unit_debug
CFLAGS= ./configure \
%%CONFIGURE_ARGS%% \
--modules=/usr/lib/unit/debug-modules \
+ --libdir=/usr/lib/$(DEB_HOST_MULTIARCH) \
--cc-opt="$(CFLAGS)" \
--ld-opt="$(LDFLAGS)" \
--debug
@@ -47,6 +52,7 @@ configure.unit_debug: config.env.unit_debug
build-arch.%: configure.%
dh_testdir
$(MAKE) -C $(BUILDDIR_$*)
+ $(MAKE) -C $(BUILDDIR_$*) build/libunit.a
ifeq ($(DOTESTS), 1)
$(MAKE) -C $(BUILDDIR_$*) tests
endif
@@ -86,7 +92,9 @@ install: build do.tests
dh_installinit
dh_installlogrotate
cd $(BUILDDIR_unit) && DESTDIR=$(INSTALLDIR) make install
+ cd $(BUILDDIR_unit) && DESTDIR=$(INSTALLDIR_dev) make libunit-install
install -m 755 $(BUILDDIR_unit_debug)/build/unitd $(INSTALLDIR)/usr/sbin/unitd-debug
+ install -m 644 $(BUILDDIR_unit_debug)/build/libunit.a $(INSTALLDIR_dev)/usr/lib/$(DEB_HOST_MULTIARCH)/libunit-debug.a
mkdir -p $(INSTALLDIR)/usr/share/doc/unit/examples
install -m 644 debian/unit.example.config $(INSTALLDIR)/usr/share/doc/unit/examples/example.config
install -m 644 CHANGES $(INSTALLDIR)/usr/share/doc/unit/
diff --git a/pkg/deb/debian/unit.example.config b/pkg/deb/debian/unit.example.config
index f3126457..8d86acbe 100644
--- a/pkg/deb/debian/unit.example.config
+++ b/pkg/deb/debian/unit.example.config
@@ -1,51 +1,51 @@
-{
- "applications": {
- "example_php": {
- "type": "php",
- "user": "nobody",
- "processes": 2,
- "root": "/usr/share/doc/unit/examples/php-app",
- "index": "index.php"
- },
-
- "example_python": {
- "type": "python",
- "user": "nobody",
- "processes": 2,
- "path": "/usr/share/doc/unit/examples/python-app",
- "module": "wsgi"
- },
-
- "example_go": {
- "type": "go",
- "user": "nobody",
- "executable": "/tmp/go-app"
- },
-
- "example_perl": {
- "type": "perl",
- "user": "nobody",
- "processes": 1,
- "working_directory": "/usr/share/doc/unit-perl/examples/perl-app",
- "script": "/usr/share/doc/unit-perl/examples/perl-app/index.pl"
- }
- },
-
- "listeners": {
- "*:8300": {
- "application": "example_php"
- },
-
- "*:8400": {
- "application": "example_python"
- },
-
- "*:8500": {
- "application": "example_go"
- },
-
- "*:8600": {
- "application": "example_perl"
- }
- }
-}
+{
+ "applications": {
+ "example_php": {
+ "type": "php",
+ "user": "nobody",
+ "processes": 2,
+ "root": "/usr/share/doc/unit/examples/php-app",
+ "index": "index.php"
+ },
+
+ "example_python": {
+ "type": "python",
+ "user": "nobody",
+ "processes": 2,
+ "path": "/usr/share/doc/unit/examples/python-app",
+ "module": "wsgi"
+ },
+
+ "example_go": {
+ "type": "external",
+ "user": "nobody",
+ "executable": "/tmp/go-app"
+ },
+
+ "example_perl": {
+ "type": "perl",
+ "user": "nobody",
+ "processes": 1,
+ "working_directory": "/usr/share/doc/unit-perl/examples/perl-app",
+ "script": "/usr/share/doc/unit-perl/examples/perl-app/index.pl"
+ }
+ },
+
+ "listeners": {
+ "*:8300": {
+ "application": "example_php"
+ },
+
+ "*:8400": {
+ "application": "example_python"
+ },
+
+ "*:8500": {
+ "application": "example_go"
+ },
+
+ "*:8600": {
+ "application": "example_perl"
+ }
+ }
+}
diff --git a/pkg/docker/Dockerfile.full b/pkg/docker/Dockerfile.full
index 1ccd4350..2ccfc16c 100644
--- a/pkg/docker/Dockerfile.full
+++ b/pkg/docker/Dockerfile.full
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Dockerfile.go1.7-dev b/pkg/docker/Dockerfile.go1.7-dev
index 20b5dea8..aa915518 100644
--- a/pkg/docker/Dockerfile.go1.7-dev
+++ b/pkg/docker/Dockerfile.go1.7-dev
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Dockerfile.go1.8-dev b/pkg/docker/Dockerfile.go1.8-dev
index a87033c1..e623182b 100644
--- a/pkg/docker/Dockerfile.go1.8-dev
+++ b/pkg/docker/Dockerfile.go1.8-dev
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Dockerfile.minimal b/pkg/docker/Dockerfile.minimal
index 8fe65bfc..0ff59411 100644
--- a/pkg/docker/Dockerfile.minimal
+++ b/pkg/docker/Dockerfile.minimal
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Dockerfile.perl5.24 b/pkg/docker/Dockerfile.perl5.24
index 53b650c0..06067fc7 100644
--- a/pkg/docker/Dockerfile.perl5.24
+++ b/pkg/docker/Dockerfile.perl5.24
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Dockerfile.php7.0 b/pkg/docker/Dockerfile.php7.0
index e20c2908..a6b816bf 100644
--- a/pkg/docker/Dockerfile.php7.0
+++ b/pkg/docker/Dockerfile.php7.0
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Dockerfile.python2.7 b/pkg/docker/Dockerfile.python2.7
index 8bd7d9df..b02fe194 100644
--- a/pkg/docker/Dockerfile.python2.7
+++ b/pkg/docker/Dockerfile.python2.7
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Dockerfile.python3.5 b/pkg/docker/Dockerfile.python3.5
index 53e72e2b..32ecfcf5 100644
--- a/pkg/docker/Dockerfile.python3.5
+++ b/pkg/docker/Dockerfile.python3.5
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Dockerfile.ruby2.3 b/pkg/docker/Dockerfile.ruby2.3
index 84dc10d0..ce5fefda 100644
--- a/pkg/docker/Dockerfile.ruby2.3
+++ b/pkg/docker/Dockerfile.ruby2.3
@@ -2,7 +2,7 @@ FROM debian:stretch-slim
LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-ENV UNIT_VERSION 1.4-2~stretch
+ENV UNIT_VERSION 1.5-1~stretch
RUN set -x \
&& apt-get update \
diff --git a/pkg/docker/Makefile b/pkg/docker/Makefile
index 319e14c0..140ac5b3 100644
--- a/pkg/docker/Makefile
+++ b/pkg/docker/Makefile
@@ -2,7 +2,7 @@
DEFAULT_VERSION := $(shell grep 'define NXT_VERSION' ../../src/nxt_main.h \
| sed -e 's/^.*"\(.*\)".*/\1/')
-DEFAULT_RELEASE := 2
+DEFAULT_RELEASE := 1
VERSION ?= $(DEFAULT_VERSION)
RELEASE ?= $(DEFAULT_RELEASE)
diff --git a/pkg/npm/Makefile b/pkg/npm/Makefile
new file mode 100644
index 00000000..2696c226
--- /dev/null
+++ b/pkg/npm/Makefile
@@ -0,0 +1,27 @@
+#!/usr/bin/make
+
+DEFAULT_VERSION := $(shell grep 'define NXT_VERSION' ../../src/nxt_main.h \
+ | sed -e 's/^.*"\(.*\)".*/\1/')
+
+VERSION ?= $(DEFAULT_VERSION)
+NPM ?= npm
+
+default:
+ @echo "valid targets: all publish clean"
+
+copy:
+ cp -rp ../../src/nodejs/unit-http .
+ mv unit-http/binding_pub.gyp unit-http/binding.gyp
+ sed -e 's/"version"\s*:.*/"version": "${VERSION}.0",/' \
+ unit-http/package.json > unit-http/package.json.tmp
+ mv unit-http/package.json.tmp unit-http/package.json
+
+publish: copy
+ cd unit-http && $(NPM) publish
+
+all: copy
+
+clean:
+ rm -rf unit-http
+
+.PHONY: default all copy publish clean
diff --git a/pkg/rpm/Makefile b/pkg/rpm/Makefile
index 5eb4213d..ef7f3361 100644
--- a/pkg/rpm/Makefile
+++ b/pkg/rpm/Makefile
@@ -3,7 +3,7 @@
DEFAULT_VERSION := $(shell grep 'define NXT_VERSION' ../../src/nxt_main.h \
| sed -e 's/^.*"\(.*\)".*/\1/')
-DEFAULT_RELEASE := 2
+DEFAULT_RELEASE := 1
VERSION ?= $(DEFAULT_VERSION)
RELEASE ?= $(DEFAULT_RELEASE)
diff --git a/pkg/rpm/Makefile.go b/pkg/rpm/Makefile.go
index a5735c12..40ebf8fb 100644
--- a/pkg/rpm/Makefile.go
+++ b/pkg/rpm/Makefile.go
@@ -4,7 +4,7 @@ MODULE_SUFFIX_go= go
MODULE_SUMMARY_go= Go module for NGINX Unit
MODULE_VERSION_go= $(VERSION)
-MODULE_RELEASE_go= 2
+MODULE_RELEASE_go= 1
MODULE_CONFARGS_go= go --go-path=%{gopath}
MODULE_MAKEARGS_go= go
diff --git a/pkg/rpm/Makefile.perl b/pkg/rpm/Makefile.perl
index fed66e58..90259e9e 100644
--- a/pkg/rpm/Makefile.perl
+++ b/pkg/rpm/Makefile.perl
@@ -4,7 +4,7 @@ MODULE_SUFFIX_perl= perl
MODULE_SUMMARY_perl= Perl module for NGINX Unit
MODULE_VERSION_perl= $(VERSION)
-MODULE_RELEASE_perl= 2
+MODULE_RELEASE_perl= 1
MODULE_CONFARGS_perl= perl
MODULE_MAKEARGS_perl= perl
diff --git a/pkg/rpm/Makefile.php b/pkg/rpm/Makefile.php
index 1235777f..b4f093b7 100644
--- a/pkg/rpm/Makefile.php
+++ b/pkg/rpm/Makefile.php
@@ -4,7 +4,7 @@ MODULE_SUFFIX_php= php
MODULE_SUMMARY_php= PHP module for NGINX Unit
MODULE_VERSION_php= $(VERSION)
-MODULE_RELEASE_php= 2
+MODULE_RELEASE_php= 1
MODULE_CONFARGS_php= php
MODULE_MAKEARGS_php= php
diff --git a/pkg/rpm/Makefile.python b/pkg/rpm/Makefile.python
index e40ba6b8..0b0eb7bd 100644
--- a/pkg/rpm/Makefile.python
+++ b/pkg/rpm/Makefile.python
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python= python
MODULE_SUMMARY_python= Python module for NGINX Unit
MODULE_VERSION_python= $(VERSION)
-MODULE_RELEASE_python= 2
+MODULE_RELEASE_python= 1
MODULE_CONFARGS_python= python
MODULE_MAKEARGS_python= python
diff --git a/pkg/rpm/Makefile.python27 b/pkg/rpm/Makefile.python27
index c0c354d5..7d15bdd9 100644
--- a/pkg/rpm/Makefile.python27
+++ b/pkg/rpm/Makefile.python27
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python27= python2.7
MODULE_SUMMARY_python27= Python 2.7 module for NGINX Unit
MODULE_VERSION_python27= $(VERSION)
-MODULE_RELEASE_python27= 2
+MODULE_RELEASE_python27= 1
MODULE_CONFARGS_python27= python --config=python2.7-config
MODULE_MAKEARGS_python27= python2.7
diff --git a/pkg/rpm/Makefile.python34 b/pkg/rpm/Makefile.python34
index af37dea3..152007a2 100644
--- a/pkg/rpm/Makefile.python34
+++ b/pkg/rpm/Makefile.python34
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python34= python3.4
MODULE_SUMMARY_python34= Python 3.4 module for NGINX Unit
MODULE_VERSION_python34= $(VERSION)
-MODULE_RELEASE_python34= 2
+MODULE_RELEASE_python34= 1
MODULE_CONFARGS_python34= python --config=python3.4-config
MODULE_MAKEARGS_python34= python3.4
diff --git a/pkg/rpm/Makefile.python35 b/pkg/rpm/Makefile.python35
index 4837fc5d..3f075702 100644
--- a/pkg/rpm/Makefile.python35
+++ b/pkg/rpm/Makefile.python35
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python35= python3.5
MODULE_SUMMARY_python35= Python 3.5 module for NGINX Unit
MODULE_VERSION_python35= $(VERSION)
-MODULE_RELEASE_python35= 2
+MODULE_RELEASE_python35= 1
MODULE_CONFARGS_python35= python --config=python3.5-config
MODULE_MAKEARGS_python35= python3.5
diff --git a/pkg/rpm/Makefile.python36 b/pkg/rpm/Makefile.python36
index 7d80493a..fd55840e 100644
--- a/pkg/rpm/Makefile.python36
+++ b/pkg/rpm/Makefile.python36
@@ -4,7 +4,7 @@ MODULE_SUFFIX_python36= python3.6
MODULE_SUMMARY_python36= Python 3.6 module for NGINX Unit
MODULE_VERSION_python36= $(VERSION)
-MODULE_RELEASE_python36= 2
+MODULE_RELEASE_python36= 1
MODULE_CONFARGS_python36= python --config=python3.6-config
MODULE_MAKEARGS_python36= python3.6
diff --git a/pkg/rpm/Makefile.ruby b/pkg/rpm/Makefile.ruby
index 3816d654..5702fb44 100644
--- a/pkg/rpm/Makefile.ruby
+++ b/pkg/rpm/Makefile.ruby
@@ -4,7 +4,7 @@ MODULE_SUFFIX_ruby= ruby
MODULE_SUMMARY_ruby= Ruby module for NGINX Unit
MODULE_VERSION_ruby= $(VERSION)
-MODULE_RELEASE_ruby= 2
+MODULE_RELEASE_ruby= 1
MODULE_CONFARGS_ruby= ruby
MODULE_MAKEARGS_ruby= ruby
diff --git a/pkg/rpm/rpmbuild/SOURCES/unit.example-go-config b/pkg/rpm/rpmbuild/SOURCES/unit.example-go-config
index d6a2a8a0..079ce0b8 100644
--- a/pkg/rpm/rpmbuild/SOURCES/unit.example-go-config
+++ b/pkg/rpm/rpmbuild/SOURCES/unit.example-go-config
@@ -1,7 +1,7 @@
{
"applications": {
"example_go": {
- "type": "go",
+ "type": "external",
"user": "nobody",
"executable": "/tmp/go-app"
}
diff --git a/pkg/rpm/rpmbuild/SOURCES/unit.example.config b/pkg/rpm/rpmbuild/SOURCES/unit.example.config
index a5f31ced..1715c971 100644
--- a/pkg/rpm/rpmbuild/SOURCES/unit.example.config
+++ b/pkg/rpm/rpmbuild/SOURCES/unit.example.config
@@ -17,7 +17,7 @@
},
"example_go": {
- "type": "go",
+ "type": "external",
"user": "nobody",
"executable": "/tmp/go-app"
},
diff --git a/pkg/rpm/unit.spec.in b/pkg/rpm/unit.spec.in
index cdecaeac..e3523cb3 100644
--- a/pkg/rpm/unit.spec.in
+++ b/pkg/rpm/unit.spec.in
@@ -60,6 +60,14 @@ dynamically via an API.
%debug_package
%endif
+%package devel
+Summary: NGINX Unit (development files)
+Version: %%VERSION%%
+Release: %%RELEASE%%%{?dist}.ngx
+Group: Development/Libraries
+%description devel
+Library and include files required for NGINX Unit modules development.
+
%prep
%setup -q
@@ -67,14 +75,17 @@ dynamically via an API.
./configure \
%{CONFIGURE_ARGS} \
--modules=%{_libdir}/unit/debug-modules \
+ --libdir=%{_libdir} \
--cc-opt="%{CC_OPT}" \
--ld-opt="%{LD_OPT}" \
--debug
%{__make} %{?_smp_mflags}
+%{__make} %{?_smp_mflags} build/libunit.a
%{__mv} build build-debug
./configure \
%{CONFIGURE_ARGS} \
--modules=%{_libdir}/unit/modules \
+ --libdir=%{_libdir} \
--cc-opt="%{CC_OPT}" \
--ld-opt="%{LD_OPT}"
%{__make} %{?_smp_mflags}
@@ -83,9 +94,11 @@ dynamically via an API.
%install
%{__rm} -rf %{buildroot}
%{__ln_s} build-nodebug build
-DESTDIR=%{buildroot} make unitd-install
+DESTDIR=%{buildroot} make unitd-install libunit-install
%{__install} -m755 %{bdir}/build-debug/unitd \
%{buildroot}%{_sbindir}/unitd-debug
+%{__install} -m644 %{bdir}/build-debug/libunit.a \
+ %{buildroot}%{_libdir}/libunit-debug.a
%{__mkdir} -p %{buildroot}%{_libdir}/unit/modules
%{__mkdir} -p %{buildroot}%{_libdir}/unit/debug-modules
%{__mkdir} -p %{buildroot}%{_sharedstatedir}/unit
@@ -184,4 +197,9 @@ fi
%dir %{_libdir}/unit/debug-modules
%dir %{_sharedstatedir}/unit
+%files devel
+%{_libdir}/libunit.a
+%{_libdir}/libunit-debug.a
+%{_includedir}/nxt_*.h
+
%changelog
diff --git a/src/go/unit/nxt_cgo_lib.c b/src/go/unit/nxt_cgo_lib.c
index 9c080730..172bef88 100644
--- a/src/go/unit/nxt_cgo_lib.c
+++ b/src/go/unit/nxt_cgo_lib.c
@@ -203,5 +203,5 @@ nxt_cgo_request_done(uintptr_t req, int res)
void
nxt_cgo_warn(uintptr_t msg, uint32_t msg_len)
{
- nxt_unit_warn(NULL, ".*s", (int) msg_len, (char *) msg);
+ nxt_unit_warn(NULL, "%.*s", (int) msg_len, (char *) msg);
}
diff --git a/src/go/unit/port.go b/src/go/unit/port.go
index f716c9ec..a68cae74 100644
--- a/src/go/unit/port.go
+++ b/src/go/unit/port.go
@@ -163,7 +163,7 @@ func nxt_go_port_recv(pid C.int, id C.int, buf unsafe.Pointer, buf_size C.int,
GoBytes(oob, oob_size))
if err != nil {
- nxt_go_warn("write result %d (%d), %s", n, oobn, err)
+ nxt_go_warn("read result %d (%d), %s", n, oobn, err)
}
return C.ssize_t(n)
diff --git a/src/nodejs/unit-http/README.md b/src/nodejs/unit-http/README.md
new file mode 100644
index 00000000..71a4067a
--- /dev/null
+++ b/src/nodejs/unit-http/README.md
@@ -0,0 +1,21 @@
+# Node.js Package for NGINX Unit
+
+[<img src="https://unit.nginx.org/_static/logo.svg" width=150px>](https://unit.nginx.org)
+Node.js support package for NGINX Unit.
+For details, see [NGINX Unit documentation](https://unit.nginx.org).
+
+## Installation
+
+```bash
+npm i unit-http
+```
+
+## Usage
+
+```javascript
+var http = require('unit-http');
+```
+
+## License
+
+Apache 2.0
diff --git a/src/nodejs/unit-http/addon.cpp b/src/nodejs/unit-http/addon.cpp
new file mode 100644
index 00000000..6ced9538
--- /dev/null
+++ b/src/nodejs/unit-http/addon.cpp
@@ -0,0 +1,15 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include "unit.h"
+
+
+napi_value
+Init(napi_env env, napi_value exports)
+{
+ return Unit::init(env, exports);
+}
+
+NAPI_MODULE(Unit, Init)
diff --git a/src/nodejs/unit-http/binding.gyp b/src/nodejs/unit-http/binding.gyp
new file mode 100644
index 00000000..171c2eb7
--- /dev/null
+++ b/src/nodejs/unit-http/binding.gyp
@@ -0,0 +1,12 @@
+{
+ 'targets': [{
+ 'target_name': "unit-http",
+ 'sources': ["unit.cpp", "addon.cpp"],
+ 'include_dirs': [
+ "<!(echo $UNIT_SRC_PATH)"
+ ],
+ 'libraries': [
+ "<!(echo $UNIT_LIB_STATIC_PATH)"
+ ]
+ }]
+}
diff --git a/src/nodejs/unit-http/binding_pub.gyp b/src/nodejs/unit-http/binding_pub.gyp
new file mode 100644
index 00000000..6fe3d9bc
--- /dev/null
+++ b/src/nodejs/unit-http/binding_pub.gyp
@@ -0,0 +1,7 @@
+{
+ 'targets': [{
+ 'target_name': "unit-http",
+ 'sources': ["unit.cpp", "addon.cpp"],
+ 'libraries': ["-lunit"]
+ }]
+}
diff --git a/src/nodejs/unit-http/http.js b/src/nodejs/unit-http/http.js
new file mode 100755
index 00000000..3a25fa2f
--- /dev/null
+++ b/src/nodejs/unit-http/http.js
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+'use strict';
+
+const server = require('unit-http/http_server');
+
+const { Server } = server;
+
+function createServer (requestHandler) {
+ return new Server(requestHandler);
+}
+
+
+module.exports = {
+ Server,
+ STATUS_CODES: server.STATUS_CODES,
+ createServer,
+ IncomingMessage: server.ServerRequest,
+ ServerResponse: server.ServerResponse
+};
diff --git a/src/nodejs/unit-http/http_server.js b/src/nodejs/unit-http/http_server.js
new file mode 100755
index 00000000..fa7b8e9b
--- /dev/null
+++ b/src/nodejs/unit-http/http_server.js
@@ -0,0 +1,331 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+'use strict';
+
+const EventEmitter = require('events');
+const http = require('http');
+const util = require('util');
+const unit_lib = require('unit-http/build/Release/unit-http.node');
+const unit_socket = require('unit-http/socket');
+
+const { Socket } = unit_socket;
+
+
+function ServerResponse(req) {
+ EventEmitter.call(this);
+
+ this.headers = {};
+}
+util.inherits(ServerResponse, EventEmitter);
+
+ServerResponse.prototype.statusCode = 200;
+ServerResponse.prototype.statusMessage = undefined;
+ServerResponse.prototype.headers_len = 0;
+ServerResponse.prototype.headers_count = 0;
+ServerResponse.prototype.headersSent = false;
+ServerResponse.prototype.finished = false;
+
+ServerResponse.prototype._finish = function _finish() {
+ this.headers = {};
+ this.headers_len = 0;
+ this.headers_count = 0;
+ this.finished = true;
+};
+
+ServerResponse.prototype.assignSocket = function assignSocket(socket) {
+};
+
+ServerResponse.prototype.detachSocket = function detachSocket(socket) {
+};
+
+ServerResponse.prototype.writeContinue = function writeContinue(cb) {
+};
+
+ServerResponse.prototype.writeProcessing = function writeProcessing(cb) {
+};
+
+ServerResponse.prototype.setHeader = function setHeader(key, value) {
+ if (typeof key !== 'string') {
+ throw new TypeError('Key argument must be a string');
+ }
+
+ let header_key_len = Buffer.byteLength(key, 'latin1');
+ let header_len = 0
+ let header_count = 0;
+
+ if (Array.isArray(value)) {
+ header_count = value.length;
+
+ value.forEach(function(val) {
+ if (typeof val !== 'string' && typeof val !== 'number') {
+ throw new TypeError('Array entries must be string or number');
+ }
+
+ header_len += Buffer.byteLength(val + "", 'latin1');
+ });
+
+ } else {
+ if (typeof value !== 'string' && typeof value !== 'number') {
+ throw new TypeError('Value argument must be string, number, or array');
+ }
+
+ header_count = 1;
+ header_len = Buffer.byteLength(value + "", 'latin1');
+ }
+
+ this.removeHeader(key);
+
+ this.headers[key] = value + "";
+ this.headers_len += header_len + (header_key_len * header_count);
+ this.headers_count += header_count;
+};
+
+ServerResponse.prototype.getHeader = function getHeader(name) {
+ return this.headers[name];
+};
+
+ServerResponse.prototype.getHeaderNames = function getHeaderNames() {
+ return Object.keys(this.headers);
+};
+
+ServerResponse.prototype.getHeaders = function getHeaders() {
+ return this.headers;
+};
+
+ServerResponse.prototype.hasHeader = function hasHeader(name) {
+ return name in this.headers;
+};
+
+ServerResponse.prototype.removeHeader = function removeHeader(name) {
+ if (!(name in this.headers)) {
+ return;
+ }
+
+ let name_len = Buffer.byteLength(name + "", 'latin1');
+
+ if (Array.isArray(this.headers[name])) {
+ this.headers_count -= this.headers[name].length;
+ this.headers_len -= this.headers[name].length * name_len;
+
+ this.headers[name].forEach(function(val) {
+ this.headers_len -= Buffer.byteLength(val + "", 'latin1');
+ });
+
+ } else {
+ this.headers_count--;
+ this.headers_len -= name_len + Buffer.byteLength(this.headers[name] + "", 'latin1');
+ }
+
+ delete this.headers[name];
+};
+
+ServerResponse.prototype.sendDate = function sendDate() {
+ throw new Error("Not supported");
+};
+
+ServerResponse.prototype.setTimeout = function setTimeout(msecs, callback) {
+ this.timeout = msecs;
+
+ if (callback) {
+ this.on('timeout', callback);
+ }
+
+ return this;
+};
+
+// for Express
+ServerResponse.prototype._implicitHeader = function _implicitHeader() {
+ this.writeHead(this.statusCode);
+};
+
+ServerResponse.prototype.writeHead = writeHead;
+ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead;
+
+function writeHead(statusCode, reason, obj) {
+ var originalStatusCode = statusCode;
+
+ statusCode |= 0;
+
+ if (statusCode < 100 || statusCode > 999) {
+ throw new ERR_HTTP_INVALID_STATUS_CODE(originalStatusCode);
+ }
+
+ if (typeof reason === 'string') {
+ this.statusMessage = reason;
+
+ } else {
+ if (!this.statusMessage) {
+ this.statusMessage = http.STATUS_CODES[statusCode] || 'unknown';
+ }
+
+ obj = reason;
+ }
+
+ this.statusCode = statusCode;
+
+ if (obj) {
+ var k;
+ var keys = Object.keys(obj);
+
+ for (var i = 0; i < keys.length; i++) {
+ k = keys[i];
+
+ if (k) {
+ this.setHeader(k, obj[k]);
+ }
+ }
+ }
+
+ unit_lib.unit_response_headers(this, statusCode, this.headers, this.headers_count, this.headers_len);
+
+ this.headersSent = true;
+};
+
+ServerResponse.prototype._writeBody = function(chunk, encoding, callback) {
+ var contentLength = 0;
+
+ if (!this.headersSent) {
+ this.writeHead(this.statusCode);
+ }
+
+ if (this.finished) {
+ return this;
+ }
+
+ if (typeof chunk === 'function') {
+ callback = chunk;
+ chunk = null;
+
+ } else if (typeof encoding === 'function') {
+ callback = encoding;
+ encoding = null;
+ }
+
+ if (chunk) {
+ if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) {
+ throw new TypeError('First argument must be a string or Buffer');
+ }
+
+ if (typeof chunk === 'string') {
+ contentLength = Buffer.byteLength(chunk, encoding);
+
+ } else {
+ contentLength = chunk.length;
+ }
+
+ unit_lib.unit_response_write(this, chunk, contentLength);
+ }
+
+ if (typeof callback === 'function') {
+ callback(this);
+ }
+};
+
+ServerResponse.prototype.write = function write(chunk, encoding, callback) {
+ this._writeBody(chunk, encoding, callback);
+
+ return this;
+};
+
+ServerResponse.prototype.end = function end(chunk, encoding, callback) {
+ this._writeBody(chunk, encoding, callback);
+ unit_lib.unit_response_end(this)
+
+ this.finished = true;
+
+ return this;
+};
+
+function ServerRequest(server) {
+ EventEmitter.call(this);
+
+ this.server = server;
+}
+util.inherits(ServerRequest, EventEmitter);
+
+ServerRequest.prototype.unpipe = undefined;
+
+ServerRequest.prototype.setTimeout = function setTimeout(msecs, callback) {
+ this.timeout = msecs;
+
+ if (callback) {
+ this.on('timeout', callback);
+ }
+
+ return this;
+};
+
+ServerRequest.prototype.statusCode = function statusCode() {
+ /* Only valid for response obtained from http.ClientRequest. */
+};
+
+ServerRequest.prototype.statusMessage = function statusMessage() {
+ /* Only valid for response obtained from http.ClientRequest. */
+};
+
+ServerRequest.prototype.trailers = function trailers() {
+ throw new Error("Not supported");
+};
+
+ServerRequest.prototype.METHODS = function METHODS() {
+ return http.METHODS;
+};
+
+ServerRequest.prototype.STATUS_CODES = function STATUS_CODES() {
+ return http.STATUS_CODES;
+};
+
+ServerRequest.prototype.listeners = function listeners() {
+ return [];
+};
+
+ServerRequest.prototype.resume = function resume() {
+ return [];
+};
+
+function Server(requestListener) {
+ EventEmitter.call(this);
+
+ this.unit = new unit_lib.Unit();
+ this.unit.createServer();
+
+ this.unit.server = this;
+
+ this.socket = Socket;
+ this.request = ServerRequest;
+ this.response = ServerResponse;
+
+ if (requestListener) {
+ this.on('request', requestListener);
+ }
+}
+util.inherits(Server, EventEmitter);
+
+Server.prototype.setTimeout = function setTimeout(msecs, callback) {
+ this.timeout = msecs;
+
+ if (callback) {
+ this.on('timeout', callback);
+ }
+
+ return this;
+};
+
+Server.prototype.listen = function () {
+ this.unit.listen();
+};
+
+function connectionListener(socket) {
+}
+
+
+module.exports = {
+ STATUS_CODES: http.STATUS_CODES,
+ Server,
+ ServerResponse,
+ ServerRequest,
+ _connectionListener: connectionListener
+};
diff --git a/src/nodejs/unit-http/package.json b/src/nodejs/unit-http/package.json
new file mode 100644
index 00000000..3a15d573
--- /dev/null
+++ b/src/nodejs/unit-http/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "unit-http",
+ "version": "1.0.0",
+ "description": "HTTP module for NGINX Unit",
+ "main": "http.js",
+ "files": [
+ "addon.cpp",
+ "binding.gyp",
+ "http_server.js",
+ "http.js",
+ "package.json",
+ "socket.js",
+ "unit.cpp",
+ "unit.h",
+ "README.md"
+ ],
+ "scripts": {
+ "clean": "node-gyp clean",
+ "configure": "node-gyp configure",
+ "build": "node-gyp build",
+ "install": "node-gyp configure build"
+ },
+ "author": "Alexander Borisov",
+ "license": "Apache-2.0",
+ "gypfile": true,
+ "dependencies": {
+ "node-addon-api": "1.2.0"
+ }
+}
diff --git a/src/nodejs/unit-http/socket.js b/src/nodejs/unit-http/socket.js
new file mode 100755
index 00000000..89702834
--- /dev/null
+++ b/src/nodejs/unit-http/socket.js
@@ -0,0 +1,99 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+'use strict';
+
+const EventEmitter = require('events');
+const util = require('util');
+const unit_lib = require('unit-http/build/Release/unit-http.node');
+
+function Socket(options) {
+ EventEmitter.call(this);
+
+ if (typeof options === 'number') {
+ options = { fd: options };
+
+ } else if (options === undefined) {
+ options = {};
+ }
+
+ this.readable = options.readable !== false;
+ this.writable = options.writable !== false;
+}
+util.inherits(Socket, EventEmitter);
+
+Socket.prototype.bufferSize = 0;
+Socket.prototype.bytesRead = 0;
+Socket.prototype.bytesWritten = 0;
+Socket.prototype.connecting = false;
+Socket.prototype.destroyed = false;
+Socket.prototype.localAddress = "";
+Socket.prototype.localPort = 0;
+Socket.prototype.remoteAddress = "";
+Socket.prototype.remoteFamily = "";
+Socket.prototype.remotePort = 0;
+
+Socket.prototype.address = function address() {
+};
+
+Socket.prototype.connect = function connect(options, callback) {
+ if (callback !== null) {
+ this.once('connect', cb);
+ }
+
+ this.connecting = true;
+ this.writable = true;
+};
+
+Socket.prototype.address = function address() {
+};
+
+Socket.prototype.destroy = function destroy(exception) {
+ this.connecting = false;
+ this.readable = false;
+ this.writable = false;
+};
+
+Socket.prototype.end = function end(data, encoding) {
+};
+
+Socket.prototype.pause = function pause() {
+};
+
+Socket.prototype.ref = function ref() {
+};
+
+Socket.prototype.resume = function resume() {
+};
+
+Socket.prototype.setEncoding = function setEncoding(encoding) {
+};
+
+Socket.prototype.setKeepAlive = function setKeepAlive(enable, initialDelay) {
+};
+
+Socket.prototype.setNoDelay = function setNoDelay(noDelay) {
+};
+
+Socket.prototype.setTimeout = function setTimeout(msecs, callback) {
+ this.timeout = msecs;
+
+ if (callback) {
+ this.on('timeout', callback);
+ }
+
+ return this;
+};
+
+Socket.prototype.unref = function unref() {
+};
+
+Socket.prototype.write = function write(data, encoding, callback) {
+};
+
+
+module.exports = {
+ Socket
+};
diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp
new file mode 100644
index 00000000..40f641a6
--- /dev/null
+++ b/src/nodejs/unit-http/unit.cpp
@@ -0,0 +1,905 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include "unit.h"
+
+
+napi_ref Unit::constructor_;
+
+
+Unit::Unit(napi_env env):
+ env_(env),
+ wrapper_(nullptr),
+ unit_ctx_(nullptr)
+{
+}
+
+
+Unit::~Unit()
+{
+ napi_delete_reference(env_, wrapper_);
+}
+
+
+napi_value
+Unit::init(napi_env env, napi_value exports)
+{
+ napi_value cons, fn;
+ napi_status status;
+
+ napi_property_descriptor properties[] = {
+ { "createServer", 0, create_server, 0, 0, 0, napi_default, 0 },
+ { "listen", 0, listen, 0, 0, 0, napi_default, 0 }
+ };
+
+ status = napi_define_class(env, "Unit", NAPI_AUTO_LENGTH, create, nullptr,
+ 2, properties, &cons);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_create_reference(env, cons, 1, &constructor_);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_set_named_property(env, exports, "Unit", cons);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_create_function(env, NULL, 0, response_send_headers, NULL,
+ &fn);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_set_named_property(env, exports,
+ "unit_response_headers", fn);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_create_function(env, NULL, 0, response_write, NULL, &fn);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_set_named_property(env, exports, "unit_response_write", fn);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_create_function(env, NULL, 0, response_end, NULL, &fn);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_set_named_property(env, exports, "unit_response_end", fn);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ return exports;
+
+failed:
+
+ napi_throw_error(env, NULL, "Failed to define Unit class");
+
+ return nullptr;
+}
+
+
+void
+Unit::destroy(napi_env env, void *nativeObject, void *finalize_hint)
+{
+ Unit *obj = reinterpret_cast<Unit *>(nativeObject);
+
+ delete obj;
+}
+
+
+napi_value
+Unit::create(napi_env env, napi_callback_info info)
+{
+ Unit *obj;
+ napi_value target, cons, instance, jsthis;
+ napi_status status;
+
+ status = napi_get_new_target(env, info, &target);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ if (target != nullptr) {
+ /* Invoked as constructor: `new Unit(...)` */
+ status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis,
+ nullptr);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ obj = new Unit(env);
+
+ status = napi_wrap(env, jsthis, reinterpret_cast<void *>(obj),
+ destroy, nullptr, &obj->wrapper_);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ return jsthis;
+ }
+
+ /* Invoked as plain function `Unit(...)`, turn into construct call. */
+ status = napi_get_reference_value(env, constructor_, &cons);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_new_instance(env, cons, 0, nullptr, &instance);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ return instance;
+
+failed:
+
+ napi_throw_error(env, NULL, "Failed to create Unit object");
+
+ return nullptr;
+}
+
+
+napi_value
+Unit::create_server(napi_env env, napi_callback_info info)
+{
+ Unit *obj;
+ size_t argc;
+ napi_value jsthis;
+ napi_status status;
+ napi_value argv[1];
+ nxt_unit_init_t unit_init;
+
+ argc = 1;
+
+ status = napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_unwrap(env, jsthis, reinterpret_cast<void **>(&obj));
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ memset(&unit_init, 0, sizeof(nxt_unit_init_t));
+
+ unit_init.data = obj;
+ unit_init.callbacks.request_handler = request_handler;
+
+ obj->unit_ctx_ = nxt_unit_init(&unit_init);
+ if (obj->unit_ctx_ == NULL) {
+ goto failed;
+ }
+
+ return nullptr;
+
+failed:
+
+ napi_throw_error(env, NULL, "Failed to create Unit object");
+
+ return nullptr;
+}
+
+
+napi_value
+Unit::listen(napi_env env, napi_callback_info info)
+{
+ int ret;
+ Unit *obj;
+ napi_value jsthis;
+ napi_status status;
+
+ status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_unwrap(env, jsthis, reinterpret_cast<void **>(&obj));
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ if (obj->unit_ctx_ == NULL) {
+ napi_throw_error(env, NULL, "Unit context was not created");
+ return nullptr;
+ }
+
+ ret = nxt_unit_run(obj->unit_ctx_);
+ if (ret != NXT_UNIT_OK) {
+ napi_throw_error(env, NULL, "Failed to run Unit");
+ return nullptr;
+ }
+
+ nxt_unit_done(obj->unit_ctx_);
+
+ return nullptr;
+
+failed:
+
+ napi_throw_error(env, NULL, "Failed to listen Unit socket");
+
+ return nullptr;
+}
+
+
+void
+Unit::request_handler(nxt_unit_request_info_t *req)
+{
+ Unit *obj;
+ napi_value socket, request, response;
+ napi_value global, server_obj;
+ napi_value req_argv[3];
+ napi_status status;
+
+ obj = reinterpret_cast<Unit *>(req->unit->data);
+
+ napi_handle_scope scope;
+ status = napi_open_handle_scope(obj->env_, &scope);
+ if (status != napi_ok) {
+ napi_throw_error(obj->env_, NULL, "Failed to create handle scope");
+ return;
+ }
+
+ server_obj = obj->get_server_object();
+ if (server_obj == nullptr) {
+ napi_throw_error(obj->env_, NULL, "Failed to get server object");
+ return;
+ }
+
+ status = napi_get_global(obj->env_, &global);
+ if (status != napi_ok) {
+ napi_throw_error(obj->env_, NULL, "Failed to get global variable");
+ return;
+ }
+
+ socket = obj->create_socket(server_obj, req);
+ if (socket == nullptr) {
+ napi_throw_error(obj->env_, NULL, "Failed to create socket object");
+ return;
+ }
+
+ request = obj->create_request(server_obj, socket);
+ if (request == nullptr) {
+ napi_throw_error(obj->env_, NULL, "Failed to create request object");
+ return;
+ }
+
+ response = obj->create_response(server_obj, socket, request, req, obj);
+ if (response == nullptr) {
+ napi_throw_error(obj->env_, NULL, "Failed to create response object");
+ return;
+ }
+
+ req_argv[1] = request;
+ req_argv[2] = response;
+
+ status = obj->create_headers(req, request);
+ if (status != napi_ok) {
+ napi_throw_error(obj->env_, NULL, "Failed to create headers");
+ return;
+ }
+
+ obj->emit(server_obj, "request", sizeof("request") - 1, 3, req_argv);
+ obj->emit_post_data(request, req);
+
+ napi_close_handle_scope(obj->env_, scope);
+}
+
+
+napi_value
+Unit::get_server_object()
+{
+ napi_value unit_obj, server_obj;
+ napi_status status;
+
+ status = napi_get_reference_value(env_, wrapper_, &unit_obj);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_get_named_property(env_, unit_obj, "server", &server_obj);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ return server_obj;
+}
+
+
+napi_value
+Unit::emit(napi_value obj, const char *name, size_t name_len, size_t argc,
+ napi_value *argv)
+{
+ napi_value emitter, return_val, str;
+ napi_status status;
+
+ status = napi_get_named_property(env_, obj, "emit", &emitter);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_create_string_latin1(env_, name, name_len, &str);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ if (argc != 0) {
+ argv[0] = str;
+
+ } else {
+ argc = 1;
+ argv = &str;
+ }
+
+ status = napi_call_function(env_, obj, emitter, argc, argv, &return_val);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ return return_val;
+}
+
+
+napi_status
+Unit::create_headers(nxt_unit_request_info_t *req, napi_value request)
+{
+ uint32_t i;
+ const char *p;
+ napi_value headers, raw_headers, str;
+ napi_status status;
+ nxt_unit_field_t *f;
+ nxt_unit_request_t *r;
+
+ r = req->request;
+
+ status = napi_create_object(env_, &headers);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ status = napi_create_array_with_length(env_, r->fields_count * 2,
+ &raw_headers);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ for (i = 0; i < r->fields_count; i++) {
+ f = r->fields + i;
+
+ status = this->append_header(f, headers, raw_headers, i);
+ if (status != napi_ok) {
+ return status;
+ }
+ }
+
+ status = napi_set_named_property(env_, request, "headers", headers);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ status = napi_set_named_property(env_, request, "raw_headers", raw_headers);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ p = (const char *) nxt_unit_sptr_get(&r->version);
+
+ status = napi_create_string_latin1(env_, p, r->version_length, &str);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ status = napi_set_named_property(env_, request, "httpVersion", str);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ p = (const char *) nxt_unit_sptr_get(&r->method);
+
+ status = napi_create_string_latin1(env_, p, r->method_length, &str);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ status = napi_set_named_property(env_, request, "method", str);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ p = (const char *) nxt_unit_sptr_get(&r->target);
+
+ status = napi_create_string_latin1(env_, p, r->target_length, &str);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ status = napi_set_named_property(env_, request, "url", str);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ return napi_ok;
+}
+
+
+inline napi_status
+Unit::append_header(nxt_unit_field_t *f, napi_value headers,
+ napi_value raw_headers, uint32_t idx)
+{
+ const char *name, *value;
+ napi_value str, vstr;
+ napi_status status;
+
+ value = (const char *) nxt_unit_sptr_get(&f->value);
+
+ status = napi_create_string_latin1(env_, value, f->value_length, &vstr);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ name = (const char *) nxt_unit_sptr_get(&f->name);
+
+ status = napi_set_named_property(env_, headers, name, vstr);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ status = napi_create_string_latin1(env_, name, f->name_length, &str);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ status = napi_set_element(env_, raw_headers, idx * 2, str);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ status = napi_set_element(env_, raw_headers, idx * 2 + 1, vstr);
+ if (status != napi_ok) {
+ return status;
+ }
+
+ return napi_ok;
+}
+
+
+napi_value
+Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req)
+{
+ napi_value constructor, return_val;
+ napi_status status;
+
+ status = napi_get_named_property(env_, server_obj, "socket",
+ &constructor);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_new_instance(env_, constructor, 0, NULL, &return_val);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ return return_val;
+}
+
+
+napi_value
+Unit::create_request(napi_value server_obj, napi_value socket)
+{
+ napi_value constructor, return_val;
+ napi_status status;
+
+ status = napi_get_named_property(env_, server_obj, "request",
+ &constructor);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_new_instance(env_, constructor, 1, &server_obj,
+ &return_val);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_set_named_property(env_, return_val, "socket", socket);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ return return_val;
+}
+
+
+napi_value
+Unit::create_response(napi_value server_obj, napi_value socket,
+ napi_value request, nxt_unit_request_info_t *req,
+ Unit *obj)
+{
+ napi_value constructor, return_val, req_num;
+ napi_status status;
+
+ status = napi_get_named_property(env_, server_obj, "response",
+ &constructor);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_new_instance(env_, constructor, 1, &request, &return_val);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_set_named_property(env_, return_val, "socket", socket);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_create_int64(env_, (int64_t) (uintptr_t) req, &req_num);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ status = napi_set_named_property(env_, return_val, "_req_point", req_num);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ return return_val;
+}
+
+
+void
+Unit::emit_post_data(napi_value request, nxt_unit_request_info_t *req)
+{
+ void *data;
+ napi_value req_argv[2];
+ napi_status status;
+
+ status = napi_create_buffer(env_, (size_t) req->content_length,
+ &data, &req_argv[1]);
+ if (status != napi_ok) {
+ napi_throw_error(env_, NULL, "Failed to create request buffer");
+ return;
+ }
+
+ nxt_unit_request_read(req, data, req->content_length);
+
+ emit(request, "data", sizeof("data") - 1, 2, req_argv);
+ emit(request, "end", sizeof("end") - 1, 0, nullptr);
+}
+
+
+napi_value
+Unit::response_send_headers(napi_env env, napi_callback_info info)
+{
+ int ret;
+ char *ptr, *name_ptr;
+ bool is_array;
+ size_t argc, name_len, value_len;
+ int64_t req_p;
+ uint32_t status_code, header_len, keys_len, array_len;
+ uint32_t keys_count, i, j;
+ uint16_t hash;
+ napi_value this_arg, headers, keys, name, value, array_val;
+ napi_value req_num;
+ napi_status status;
+ nxt_unit_field_t *f;
+ nxt_unit_request_info_t *req;
+ napi_value argv[5];
+
+ argc = 5;
+
+ status = napi_get_cb_info(env, info, &argc, argv, &this_arg, NULL);
+ if (status != napi_ok) {
+ return nullptr;
+ }
+
+ if (argc != 5) {
+ napi_throw_error(env, NULL, "Wrong args count. Need three: "
+ "statusCode, headers, headers count, headers length");
+ return nullptr;
+ }
+
+ status = napi_get_named_property(env, argv[0], "_req_point", &req_num);
+ if (status != napi_ok) {
+ napi_throw_error(env, NULL, "Failed to get request pointer");
+ return nullptr;
+ }
+
+ status = napi_get_value_int64(env, req_num, &req_p);
+ if (status != napi_ok) {
+ napi_throw_error(env, NULL, "Failed to get request pointer");
+ return nullptr;
+ }
+
+ req = (nxt_unit_request_info_t *) (uintptr_t) req_p;
+
+ status = napi_get_value_uint32(env, argv[1], &status_code);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_get_value_uint32(env, argv[3], &keys_count);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_get_value_uint32(env, argv[4], &header_len);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ /* Need to reserve extra byte for C-string 0-termination. */
+ header_len++;
+
+ headers = argv[2];
+
+ ret = nxt_unit_response_init(req, status_code, keys_count, header_len);
+ if (ret != NXT_UNIT_OK) {
+ goto failed;
+ }
+
+ status = napi_get_property_names(env, headers, &keys);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_get_array_length(env, keys, &keys_len);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ ptr = req->response_buf->free;
+
+ for (i = 0; i < keys_len; i++) {
+ status = napi_get_element(env, keys, i, &name);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_get_property(env, headers, name, &value);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_get_value_string_latin1(env, name, ptr, header_len,
+ &name_len);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ name_ptr = ptr;
+
+ ptr += name_len;
+ header_len -= name_len;
+
+ hash = nxt_unit_field_hash(name_ptr, name_len);
+
+ status = napi_is_array(env, value, &is_array);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ if (is_array) {
+ status = napi_get_array_length(env, value, &array_len);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ for (j = 0; j < array_len; j++) {
+ status = napi_get_element(env, value, j, &array_val);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_get_value_string_latin1(env, array_val, ptr,
+ header_len,
+ &value_len);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ f = req->response->fields + req->response->fields_count;
+ f->skip = 0;
+
+ nxt_unit_sptr_set(&f->name, name_ptr);
+
+ f->name_length = name_len;
+ f->hash = hash;
+
+ nxt_unit_sptr_set(&f->value, ptr);
+ f->value_length = (uint32_t) value_len;
+
+ ptr += value_len;
+ header_len -= value_len;
+
+ req->response->fields_count++;
+ }
+
+ } else {
+ status = napi_get_value_string_latin1(env, value, ptr, header_len,
+ &value_len);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ f = req->response->fields + req->response->fields_count;
+ f->skip = 0;
+
+ nxt_unit_sptr_set(&f->name, name_ptr);
+
+ f->name_length = name_len;
+ f->hash = hash;
+
+ nxt_unit_sptr_set(&f->value, ptr);
+ f->value_length = (uint32_t) value_len;
+
+ ptr += value_len;
+ header_len -= value_len;
+
+ req->response->fields_count++;
+ }
+ }
+
+ req->response_buf->free = ptr;
+
+ ret = nxt_unit_response_send(req);
+ if (ret != NXT_UNIT_OK) {
+ goto failed;
+ }
+
+ return this_arg;
+
+failed:
+
+ req->response->fields_count = 0;
+
+ napi_throw_error(env, NULL, "Failed to write headers");
+
+ return nullptr;
+}
+
+
+napi_value
+Unit::response_write(napi_env env, napi_callback_info info)
+{
+ int ret;
+ char *ptr;
+ size_t argc, have_buf_len;
+ int64_t req_p;
+ uint32_t buf_len;
+ napi_value this_arg, req_num;
+ napi_status status;
+ nxt_unit_buf_t *buf;
+ napi_valuetype buf_type;
+ nxt_unit_request_info_t *req;
+ napi_value argv[3];
+
+ argc = 3;
+
+ status = napi_get_cb_info(env, info, &argc, argv, &this_arg, NULL);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ if (argc != 3) {
+ napi_throw_error(env, NULL, "Wrong args count. Need two: "
+ "chunk, chunk length");
+ return nullptr;
+ }
+
+ status = napi_get_named_property(env, argv[0], "_req_point", &req_num);
+ if (status != napi_ok) {
+ napi_throw_error(env, NULL, "Failed to get request pointer");
+ return nullptr;
+ }
+
+ status = napi_get_value_int64(env, req_num, &req_p);
+ if (status != napi_ok) {
+ napi_throw_error(env, NULL, "Failed to get request pointer");
+ return nullptr;
+ }
+
+ req = (nxt_unit_request_info_t *) (uintptr_t) req_p;
+
+ status = napi_get_value_uint32(env, argv[2], &buf_len);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ status = napi_typeof(env, argv[1], &buf_type);
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ buf_len++;
+
+ buf = nxt_unit_response_buf_alloc(req, buf_len);
+ if (buf == NULL) {
+ goto failed;
+ }
+
+ if (buf_type == napi_string) {
+ /* TODO: will work only for utf8 content-type */
+
+ status = napi_get_value_string_utf8(env, argv[1], buf->free,
+ buf_len, &have_buf_len);
+
+ } else {
+ status = napi_get_buffer_info(env, argv[1], (void **) &ptr,
+ &have_buf_len);
+
+ memcpy(buf->free, ptr, have_buf_len);
+ }
+
+ if (status != napi_ok) {
+ goto failed;
+ }
+
+ buf->free += have_buf_len;
+
+ ret = nxt_unit_buf_send(buf);
+ if (ret != NXT_UNIT_OK) {
+ goto failed;
+ }
+
+ return this_arg;
+
+failed:
+
+ napi_throw_error(env, NULL, "Failed to write body");
+
+ return nullptr;
+}
+
+
+napi_value
+Unit::response_end(napi_env env, napi_callback_info info)
+{
+ size_t argc;
+ int64_t req_p;
+ napi_value resp, this_arg, req_num;
+ napi_status status;
+ nxt_unit_request_info_t *req;
+
+ argc = 1;
+
+ status = napi_get_cb_info(env, info, &argc, &resp, &this_arg, NULL);
+ if (status != napi_ok) {
+ napi_throw_error(env, NULL, "Failed to finalize sending body");
+ return nullptr;
+ }
+
+ status = napi_get_named_property(env, resp, "_req_point", &req_num);
+ if (status != napi_ok) {
+ napi_throw_error(env, NULL, "Failed to get request pointer");
+ return nullptr;
+ }
+
+ status = napi_get_value_int64(env, req_num, &req_p);
+ if (status != napi_ok) {
+ napi_throw_error(env, NULL, "Failed to get request pointer");
+ return nullptr;
+ }
+
+ req = (nxt_unit_request_info_t *) (uintptr_t) req_p;
+
+ nxt_unit_request_done(req, NXT_UNIT_OK);
+
+ return this_arg;
+}
diff --git a/src/nodejs/unit-http/unit.h b/src/nodejs/unit-http/unit.h
new file mode 100644
index 00000000..753a14d8
--- /dev/null
+++ b/src/nodejs/unit-http/unit.h
@@ -0,0 +1,77 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_NODEJS_UNIT_H_INCLUDED_
+#define _NXT_NODEJS_UNIT_H_INCLUDED_
+
+
+#include <node_api.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nxt_unit.h>
+#include <nxt_unit_response.h>
+#include <nxt_unit_request.h>
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+class Unit {
+public:
+ static napi_value init(napi_env env, napi_value exports);
+
+private:
+ Unit(napi_env env);
+ ~Unit();
+
+ static napi_value create(napi_env env, napi_callback_info info);
+ static void destroy(napi_env env, void *nativeObject, void *finalize_hint);
+
+ static napi_value create_server(napi_env env, napi_callback_info info);
+ static napi_value listen(napi_env env, napi_callback_info info);
+ static void request_handler(nxt_unit_request_info_t *req);
+
+ napi_value get_server_object();
+
+ napi_value emit(napi_value obj, const char *name, size_t name_len,
+ size_t argc, napi_value *argv);
+
+ napi_value create_socket(napi_value server_obj,
+ nxt_unit_request_info_t *req);
+
+ napi_value create_request(napi_value server_obj, napi_value socket);
+
+ napi_value create_response(napi_value server_obj, napi_value socket,
+ napi_value request,
+ nxt_unit_request_info_t *req, Unit *obj);
+
+ void emit_post_data(napi_value request, nxt_unit_request_info_t *req);
+
+ static napi_value response_send_headers(napi_env env,
+ napi_callback_info info);
+
+ static napi_value response_write(napi_env env, napi_callback_info info);
+ static napi_value response_end(napi_env env, napi_callback_info info);
+
+ napi_status create_headers(nxt_unit_request_info_t *req,
+ napi_value request);
+
+ inline napi_status append_header(nxt_unit_field_t *f, napi_value headers,
+ napi_value raw_headers, uint32_t idx);
+
+ static napi_ref constructor_;
+
+ napi_env env_;
+ napi_ref wrapper_;
+ nxt_unit_ctx_t *unit_ctx_;
+};
+
+
+#endif /* _NXT_NODEJS_H_INCLUDED_ */
diff --git a/src/nxt_app_log.c b/src/nxt_app_log.c
index 83eac371..0ecd9aac 100644
--- a/src/nxt_app_log.c
+++ b/src/nxt_app_log.c
@@ -97,7 +97,7 @@ static nxt_time_string_t nxt_log_error_time_cache = {
"%4d/%02d/%02d %02d:%02d:%02d ",
nxt_length("1970/09/28 12:00:00 "),
NXT_THREAD_TIME_LOCAL,
- NXT_THREAD_TIME_MSEC,
+ NXT_THREAD_TIME_SEC,
};
diff --git a/src/nxt_application.c b/src/nxt_application.c
index 3c62f7d4..acdebe04 100644
--- a/src/nxt_application.c
+++ b/src/nxt_application.c
@@ -507,15 +507,15 @@ nxt_app_parse_type(u_char *p, size_t length)
str.length = length;
str.start = p;
- if (nxt_str_eq(&str, "python", 6)) {
+ if (nxt_str_eq(&str, "external", 8) || nxt_str_eq(&str, "go", 2)) {
+ return NXT_APP_EXTERNAL;
+
+ } else if (nxt_str_eq(&str, "python", 6)) {
return NXT_APP_PYTHON;
} else if (nxt_str_eq(&str, "php", 3)) {
return NXT_APP_PHP;
- } else if (nxt_str_eq(&str, "go", 2)) {
- return NXT_APP_GO;
-
} else if (nxt_str_eq(&str, "perl", 4)) {
return NXT_APP_PERL;
diff --git a/src/nxt_application.h b/src/nxt_application.h
index 35346655..10f5a922 100644
--- a/src/nxt_application.h
+++ b/src/nxt_application.h
@@ -15,9 +15,9 @@
typedef enum {
+ NXT_APP_EXTERNAL,
NXT_APP_PYTHON,
NXT_APP_PHP,
- NXT_APP_GO,
NXT_APP_PERL,
NXT_APP_RUBY,
@@ -40,6 +40,12 @@ typedef struct nxt_common_app_conf_s nxt_common_app_conf_t;
typedef struct {
+ char *executable;
+ nxt_conf_value_t *arguments;
+} nxt_external_app_conf_t;
+
+
+typedef struct {
char *home;
nxt_str_t path;
nxt_str_t module;
@@ -55,12 +61,6 @@ typedef struct {
typedef struct {
- char *executable;
- nxt_conf_value_t *arguments;
-} nxt_go_app_conf_t;
-
-
-typedef struct {
char *script;
} nxt_perl_app_conf_t;
@@ -80,11 +80,11 @@ struct nxt_common_app_conf_s {
nxt_conf_value_t *environment;
union {
- nxt_python_app_conf_t python;
- nxt_php_app_conf_t php;
- nxt_go_app_conf_t go;
- nxt_perl_app_conf_t perl;
- nxt_ruby_app_conf_t ruby;
+ nxt_external_app_conf_t external;
+ nxt_python_app_conf_t python;
+ nxt_php_app_conf_t php;
+ nxt_perl_app_conf_t perl;
+ nxt_ruby_app_conf_t ruby;
} u;
};
@@ -161,7 +161,7 @@ nxt_app_lang_module_t *nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name);
nxt_app_type_t nxt_app_parse_type(u_char *p, size_t length);
NXT_EXPORT extern nxt_str_t nxt_server;
-extern nxt_app_module_t nxt_go_module;
+extern nxt_app_module_t nxt_external_module;
NXT_EXPORT nxt_int_t nxt_unit_default_init(nxt_task_t *task,
nxt_unit_init_t *init);
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c
index ca7107cc..b1e30955 100644
--- a/src/nxt_conf_validation.c
+++ b/src/nxt_conf_validation.c
@@ -256,6 +256,21 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = {
};
+static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = {
+ { nxt_string("executable"),
+ NXT_CONF_VLDT_STRING,
+ NULL,
+ NULL },
+
+ { nxt_string("arguments"),
+ NXT_CONF_VLDT_ARRAY,
+ &nxt_conf_vldt_array_iterator,
+ (void *) &nxt_conf_vldt_argument },
+
+ NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
+};
+
+
static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = {
{ nxt_string("home"),
NXT_CONF_VLDT_STRING,
@@ -321,21 +336,6 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = {
};
-static nxt_conf_vldt_object_t nxt_conf_vldt_go_members[] = {
- { nxt_string("executable"),
- NXT_CONF_VLDT_STRING,
- NULL,
- NULL },
-
- { nxt_string("arguments"),
- NXT_CONF_VLDT_ARRAY,
- &nxt_conf_vldt_array_iterator,
- (void *) &nxt_conf_vldt_argument },
-
- NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
-};
-
-
static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = {
{ nxt_string("script"),
NXT_CONF_VLDT_STRING,
@@ -565,9 +565,9 @@ nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
static nxt_str_t type_str = nxt_string("type");
static void *members[] = {
+ nxt_conf_vldt_external_members,
nxt_conf_vldt_python_members,
nxt_conf_vldt_php_members,
- nxt_conf_vldt_go_members,
nxt_conf_vldt_perl_members,
nxt_conf_vldt_ruby_members,
};
diff --git a/src/nxt_conn.h b/src/nxt_conn.h
index 6f6cae9c..d8b48694 100644
--- a/src/nxt_conn.h
+++ b/src/nxt_conn.h
@@ -175,7 +175,7 @@ struct nxt_conn_s {
do { \
(ev)->work_queue = (wq); \
(ev)->log = &(c)->log; \
- (ev)->precision = NXT_TIMER_DEFAULT_PRECISION; \
+ (ev)->bias = NXT_TIMER_DEFAULT_BIAS; \
} while (0)
diff --git a/src/nxt_conn_read.c b/src/nxt_conn_read.c
index 21086233..e458bf81 100644
--- a/src/nxt_conn_read.c
+++ b/src/nxt_conn_read.c
@@ -105,7 +105,7 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data)
* occured during read operation, it toggled write event
* internally so only read timer should be set.
*/
- if (c->read_timer.state == NXT_TIMER_DISABLED) {
+ if (!c->read_timer.enabled) {
nxt_conn_timer(engine, c, state, &c->read_timer);
}
@@ -117,7 +117,7 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data)
nxt_fd_event_enable_read(engine, &c->socket);
}
- if (state->timer_autoreset || c->read_timer.state == NXT_TIMER_DISABLED) {
+ if (state->timer_autoreset || !c->read_timer.enabled) {
nxt_conn_timer(engine, c, state, &c->read_timer);
}
}
diff --git a/src/nxt_conn_write.c b/src/nxt_conn_write.c
index 73c3fa02..80d6f5cf 100644
--- a/src/nxt_conn_write.c
+++ b/src/nxt_conn_write.c
@@ -127,7 +127,9 @@ nxt_conn_io_write(nxt_task_t *task, void *obj, void *data)
return;
}
- /* ret == NXT_ERROR */
+ if (ret != NXT_ERROR) {
+ return;
+ }
nxt_fd_event_block_write(engine, &c->socket);
diff --git a/src/nxt_epoll_engine.c b/src/nxt_epoll_engine.c
index 68e8d609..9f9c8f62 100644
--- a/src/nxt_epoll_engine.c
+++ b/src/nxt_epoll_engine.c
@@ -67,7 +67,7 @@ static void nxt_epoll_enable_accept(nxt_event_engine_t *engine,
nxt_fd_event_t *ev);
static void nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev,
int op, uint32_t events);
-static nxt_int_t nxt_epoll_commit_changes(nxt_event_engine_t *engine);
+static void nxt_epoll_commit_changes(nxt_event_engine_t *engine);
static void nxt_epoll_error_handler(nxt_task_t *task, void *obj, void *data);
#if (NXT_HAVE_SIGNALFD)
static nxt_int_t nxt_epoll_add_signal(nxt_event_engine_t *engine);
@@ -593,7 +593,7 @@ nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int op,
engine->u.epoll.fd, ev->fd, op, events);
if (engine->u.epoll.nchanges >= engine->u.epoll.mchanges) {
- (void) nxt_epoll_commit_changes(engine);
+ nxt_epoll_commit_changes(engine);
}
ev->changing = 1;
@@ -605,18 +605,16 @@ nxt_epoll_change(nxt_event_engine_t *engine, nxt_fd_event_t *ev, int op,
}
-static nxt_int_t
+static void
nxt_epoll_commit_changes(nxt_event_engine_t *engine)
{
int ret;
- nxt_int_t retval;
nxt_fd_event_t *ev;
nxt_epoll_change_t *change, *end;
nxt_debug(&engine->task, "epoll %d changes:%ui",
engine->u.epoll.fd, engine->u.epoll.nchanges);
- retval = NXT_OK;
change = engine->u.epoll.changes;
end = change + engine->u.epoll.nchanges;
@@ -637,7 +635,7 @@ nxt_epoll_commit_changes(nxt_event_engine_t *engine)
nxt_work_queue_add(&engine->fast_work_queue,
nxt_epoll_error_handler, ev->task, ev, ev->data);
- retval = NXT_ERROR;
+ engine->u.epoll.error = 1;
}
change++;
@@ -645,8 +643,6 @@ nxt_epoll_commit_changes(nxt_event_engine_t *engine)
} while (change < end);
engine->u.epoll.nchanges = 0;
-
- return retval;
}
@@ -884,10 +880,13 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout)
struct epoll_event *event;
if (engine->u.epoll.nchanges != 0) {
- if (nxt_epoll_commit_changes(engine) != NXT_OK) {
- /* Error handlers have been enqueued on failure. */
- timeout = 0;
- }
+ nxt_epoll_commit_changes(engine);
+ }
+
+ if (engine->u.epoll.error) {
+ engine->u.epoll.error = 0;
+ /* Error handlers have been enqueued on failure. */
+ timeout = 0;
}
nxt_debug(&engine->task, "epoll_wait(%d) timeout:%M",
@@ -921,8 +920,8 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout)
ev->fd, events, ev, ev->read, ev->write);
/*
- * On error epoll may set EPOLLERR and EPOLLHUP only without EPOLLIN or
- * EPOLLOUT, so the "error" variable enqueues only one active handler.
+ * On error epoll may set EPOLLERR and EPOLLHUP only without EPOLLIN
+ * or EPOLLOUT, so the "error" variable enqueues only error handler.
*/
error = ((events & (EPOLLERR | EPOLLHUP)) != 0);
ev->epoll_error = error;
@@ -933,7 +932,7 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout)
#endif
- if ((events & EPOLLIN) || error) {
+ if ((events & EPOLLIN) != 0) {
ev->read_ready = 1;
if (ev->read != NXT_EVENT_BLOCKED) {
@@ -942,8 +941,6 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout)
ev->read = NXT_EVENT_DISABLED;
}
- error = 0;
-
nxt_work_queue_add(ev->read_work_queue, ev->read_handler,
ev->task, ev, ev->data);
@@ -951,9 +948,11 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout)
/* Level-triggered mode. */
nxt_epoll_disable_read(engine, ev);
}
+
+ error = 0;
}
- if ((events & EPOLLOUT) || error) {
+ if ((events & EPOLLOUT) != 0) {
ev->write_ready = 1;
if (ev->write != NXT_EVENT_BLOCKED) {
@@ -962,8 +961,6 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout)
ev->write = NXT_EVENT_DISABLED;
}
- error = 0;
-
nxt_work_queue_add(ev->write_work_queue, ev->write_handler,
ev->task, ev, ev->data);
@@ -971,12 +968,29 @@ nxt_epoll_poll(nxt_event_engine_t *engine, nxt_msec_t timeout)
/* Level-triggered mode. */
nxt_epoll_disable_write(engine, ev);
}
+
+ error = 0;
}
- if (error) {
- ev->read_ready = 1;
- ev->write_ready = 1;
+ if (!error) {
+ continue;
+ }
+
+ ev->read_ready = 1;
+ ev->write_ready = 1;
+
+ if (ev->read == NXT_EVENT_BLOCKED && ev->write == NXT_EVENT_BLOCKED) {
+
+ if (engine->u.epoll.mode == 0) {
+ /* Level-triggered mode. */
+ nxt_epoll_disable(engine, ev);
+ }
+
+ continue;
}
+
+ nxt_work_queue_add(&engine->fast_work_queue, nxt_epoll_error_handler,
+ ev->task, ev, ev->data);
}
}
diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h
index 7a7149e6..365d9e89 100644
--- a/src/nxt_event_engine.h
+++ b/src/nxt_event_engine.h
@@ -202,6 +202,8 @@ typedef struct {
nxt_uint_t mchanges;
int mevents;
+ uint8_t error; /* 1 bit */
+
nxt_epoll_change_t *changes;
struct epoll_event *events;
diff --git a/src/nxt_go.c b/src/nxt_external.c
index 4e7d0488..c7aacffc 100644
--- a/src/nxt_go.c
+++ b/src/nxt_external.c
@@ -9,21 +9,24 @@
#include <nxt_unit.h>
-static nxt_int_t nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
+static nxt_int_t nxt_external_init(nxt_task_t *task,
+ nxt_common_app_conf_t *conf);
-nxt_app_module_t nxt_go_module = {
+
+nxt_app_module_t nxt_external_module = {
0,
NULL,
- nxt_string("go"),
+ nxt_string("external"),
"*",
- nxt_go_init,
+ nxt_external_init,
};
extern char **environ;
+
nxt_inline nxt_int_t
-nxt_go_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd)
+nxt_external_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd)
{
int res, flags;
@@ -54,20 +57,20 @@ nxt_go_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd)
static nxt_int_t
-nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
+nxt_external_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
{
- char **argv;
- u_char buf[256];
- u_char *p, *end;
- uint32_t index;
- size_t size;
- nxt_str_t str;
- nxt_int_t rc;
- nxt_uint_t i, argc;
- nxt_port_t *my_port, *main_port;
- nxt_runtime_t *rt;
- nxt_conf_value_t *value;
- nxt_go_app_conf_t *c;
+ char **argv;
+ u_char buf[256];
+ u_char *p, *end;
+ uint32_t index;
+ size_t size;
+ nxt_str_t str;
+ nxt_int_t rc;
+ nxt_uint_t i, argc;
+ nxt_port_t *my_port, *main_port;
+ nxt_runtime_t *rt;
+ nxt_conf_value_t *value;
+ nxt_external_app_conf_t *c;
rt = task->thread->runtime;
@@ -78,12 +81,12 @@ nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
return NXT_ERROR;
}
- rc = nxt_go_fd_no_cloexec(task, main_port->pair[1]);
+ rc = nxt_external_fd_no_cloexec(task, main_port->pair[1]);
if (nxt_slow_path(rc != NXT_OK)) {
return NXT_ERROR;
}
- rc = nxt_go_fd_no_cloexec(task, my_port->pair[0]);
+ rc = nxt_external_fd_no_cloexec(task, my_port->pair[0]);
if (nxt_slow_path(rc != NXT_OK)) {
return NXT_ERROR;
}
@@ -116,7 +119,7 @@ nxt_go_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
return NXT_ERROR;
}
- c = &conf->u.go;
+ c = &conf->u.external;
argc = 2;
size = 0;
diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c
index 3e5044b7..2194e56f 100644
--- a/src/nxt_h1proto.c
+++ b/src/nxt_h1proto.c
@@ -967,11 +967,14 @@ nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r)
http11 = (h1p->parser.version.s.minor != '0');
if (r->resp.content_length == NULL || r->resp.content_length->skip) {
+
if (http11) {
- h1p->chunked = 1;
- size += nxt_length(chunked);
- /* Trailing CRLF will be added by the first chunk header. */
- size -= nxt_length("\r\n");
+ if (n != NXT_HTTP_NOT_MODIFIED && n != NXT_HTTP_NO_CONTENT) {
+ h1p->chunked = 1;
+ size += nxt_length(chunked);
+ /* Trailing CRLF will be added by the first chunk header. */
+ size -= nxt_length("\r\n");
+ }
} else {
h1p->keepalive = 0;
diff --git a/src/nxt_http.h b/src/nxt_http.h
index 1c7ed8bb..b2111f90 100644
--- a/src/nxt_http.h
+++ b/src/nxt_http.h
@@ -12,6 +12,7 @@ typedef enum {
NXT_HTTP_INVALID = 0,
NXT_HTTP_OK = 200,
+ NXT_HTTP_NO_CONTENT = 204,
NXT_HTTP_MULTIPLE_CHOICES = 300,
NXT_HTTP_MOVED_PERMANENTLY = 301,
diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c
index 06d45247..b80998cb 100644
--- a/src/nxt_http_request.c
+++ b/src/nxt_http_request.c
@@ -192,7 +192,7 @@ nxt_http_app_request(nxt_task_t *task, void *obj, void *data)
ar->timer.task = &engine->task;
ar->timer.work_queue = &engine->fast_work_queue;
ar->timer.log = engine->task.log;
- ar->timer.precision = NXT_TIMER_DEFAULT_PRECISION;
+ ar->timer.bias = NXT_TIMER_DEFAULT_BIAS;
ar->r.remote.start = nxt_sockaddr_address(r->remote);
ar->r.remote.length = r->remote->address_length;
diff --git a/src/nxt_main.h b/src/nxt_main.h
index 1bbd9ee5..670010f8 100644
--- a/src/nxt_main.h
+++ b/src/nxt_main.h
@@ -11,8 +11,8 @@
#include <nxt_auto_config.h>
-#define NXT_VERSION "1.4"
-#define NXT_VERNUM 10400
+#define NXT_VERSION "1.5"
+#define NXT_VERNUM 10500
#define NXT_SERVER "Unit/" NXT_VERSION
diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c
index 491b09f3..819ed44c 100644
--- a/src/nxt_main_process.c
+++ b/src/nxt_main_process.c
@@ -134,6 +134,22 @@ static nxt_conf_map_t nxt_common_app_conf[] = {
};
+static nxt_conf_map_t nxt_external_app_conf[] = {
+ {
+ nxt_string("executable"),
+ NXT_CONF_MAP_CSTRZ,
+ offsetof(nxt_common_app_conf_t, u.external.executable),
+ },
+
+ {
+ nxt_string("arguments"),
+ NXT_CONF_MAP_PTR,
+ offsetof(nxt_common_app_conf_t, u.external.arguments),
+ },
+
+};
+
+
static nxt_conf_map_t nxt_python_app_conf[] = {
{
nxt_string("home"),
@@ -182,22 +198,6 @@ static nxt_conf_map_t nxt_php_app_conf[] = {
};
-static nxt_conf_map_t nxt_go_app_conf[] = {
- {
- nxt_string("executable"),
- NXT_CONF_MAP_CSTRZ,
- offsetof(nxt_common_app_conf_t, u.go.executable),
- },
-
- {
- nxt_string("arguments"),
- NXT_CONF_MAP_PTR,
- offsetof(nxt_common_app_conf_t, u.go.arguments),
- },
-
-};
-
-
static nxt_conf_map_t nxt_perl_app_conf[] = {
{
nxt_string("script"),
@@ -217,11 +217,11 @@ static nxt_conf_map_t nxt_ruby_app_conf[] = {
static nxt_conf_app_map_t nxt_app_maps[] = {
- { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf },
- { nxt_nitems(nxt_php_app_conf), nxt_php_app_conf },
- { nxt_nitems(nxt_go_app_conf), nxt_go_app_conf },
- { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf },
- { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf },
+ { nxt_nitems(nxt_external_app_conf), nxt_external_app_conf },
+ { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf },
+ { nxt_nitems(nxt_php_app_conf), nxt_php_app_conf },
+ { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf },
+ { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf },
};
diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c
index 91ba3cb0..441da54b 100644
--- a/src/nxt_openssl.c
+++ b/src/nxt_openssl.c
@@ -404,7 +404,7 @@ nxt_openssl_chain_file(SSL_CTX *ctx, nxt_fd_t fd)
* while the main certificate needs a X509_free() call, since
* its reference count is increased by SSL_CTX_use_certificate().
*/
-#if OPENSSL_VERSION_NUMBER > 0x10002000L
+#ifdef SSL_CTX_add0_chain_cert
if (SSL_CTX_add0_chain_cert(ctx, ca) != 1) {
#else
if (SSL_CTX_add_extra_chain_cert(ctx, ca) != 1) {
diff --git a/src/nxt_port.c b/src/nxt_port.c
index 3d18fa67..30719ad3 100644
--- a/src/nxt_port.c
+++ b/src/nxt_port.c
@@ -276,6 +276,8 @@ nxt_port_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
nxt_process_use(task, process, -1);
+ nxt_fd_nonblocking(task, msg->fd);
+
port->pair[0] = -1;
port->pair[1] = msg->fd;
port->max_size = new_port_msg->max_size;
diff --git a/src/nxt_router.c b/src/nxt_router.c
index 139b2c4c..7ecbca81 100644
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -289,9 +289,9 @@ static const nxt_str_t http_prefix = nxt_string("HTTP_");
static const nxt_str_t empty_prefix = nxt_string("");
static const nxt_str_t *nxt_app_msg_prefix[] = {
+ &empty_prefix,
&http_prefix,
&http_prefix,
- &empty_prefix,
&http_prefix,
&http_prefix,
};
@@ -1578,7 +1578,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
app_joint->use_count = 1;
app_joint->app = app;
- app_joint->idle_timer.precision = NXT_TIMER_DEFAULT_PRECISION;
+ app_joint->idle_timer.bias = NXT_TIMER_DEFAULT_BIAS;
app_joint->idle_timer.work_queue = &engine->fast_work_queue;
app_joint->idle_timer.handler = nxt_router_app_idle_timeout;
app_joint->idle_timer.task = &engine->task;
@@ -4119,7 +4119,7 @@ nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, void *data)
nxt_assert(app->engine == engine);
- threshold = engine->timers.now + app->joint->idle_timer.precision;
+ threshold = engine->timers.now + app->joint->idle_timer.bias;
timeout = 0;
nxt_thread_mutex_lock(&app->mutex);
diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c
index 311c2c08..547c7494 100644
--- a/src/nxt_runtime.c
+++ b/src/nxt_runtime.c
@@ -80,10 +80,10 @@ nxt_runtime_create(nxt_task_t *task)
/* Should not fail. */
lang = nxt_array_add(rt->languages);
- lang->type = NXT_APP_GO;
+ lang->type = NXT_APP_EXTERNAL;
lang->version = (u_char *) "";
lang->file = NULL;
- lang->module = &nxt_go_module;
+ lang->module = &nxt_external_module;
listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t));
if (nxt_slow_path(listen_sockets == NULL)) {
@@ -872,20 +872,6 @@ nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt)
continue;
}
- if (nxt_strcmp(p, "--upstream") == 0) {
- if (*argv == NULL) {
- nxt_alert(task, "no argument for option \"--upstream\"");
- return NXT_ERROR;
- }
-
- p = *argv++;
-
- rt->upstream.length = nxt_strlen(p);
- rt->upstream.start = (u_char *) p;
-
- continue;
- }
-
if (nxt_strcmp(p, "--user") == 0) {
if (*argv == NULL) {
write(STDERR_FILENO, no_user, nxt_length(no_user));
diff --git a/src/nxt_runtime.h b/src/nxt_runtime.h
index e4c9e2a1..496ae478 100644
--- a/src/nxt_runtime.h
+++ b/src/nxt_runtime.h
@@ -74,7 +74,6 @@ struct nxt_runtime_s {
nxt_sockaddr_t *controller_listen;
nxt_listen_socket_t *controller_socket;
- nxt_str_t upstream;
};
diff --git a/src/nxt_timer.c b/src/nxt_timer.c
index f56ddeb6..cba4755b 100644
--- a/src/nxt_timer.c
+++ b/src/nxt_timer.c
@@ -32,6 +32,10 @@ nxt_timers_init(nxt_timers_t *timers, nxt_uint_t mchanges)
{
nxt_rbtree_init(&timers->tree, nxt_timer_rbtree_compare);
+ if (mchanges > NXT_TIMER_MAX_CHANGES) {
+ mchanges = NXT_TIMER_MAX_CHANGES;
+ }
+
timers->mchanges = mchanges;
timers->changes = nxt_malloc(sizeof(nxt_timer_change_t) * mchanges);
@@ -71,66 +75,50 @@ nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer,
time = engine->timers.now + timeout;
- if (timer->state != NXT_TIMER_CHANGING) {
+ nxt_debug(timer->task, "timer add: %M±%d %M:%M",
+ timer->time, timer->bias, timeout, time);
- if (nxt_timer_is_in_tree(timer)) {
+ timer->enabled = 1;
- diff = nxt_msec_diff(time, timer->time);
- /*
- * Use the previous timer if difference between it and the
- * new timer is less than required precision milliseconds: this
- * decreases number of rbtree operations for fast connections.
- */
- if (nxt_abs(diff) < timer->precision) {
- nxt_debug(timer->task, "timer previous: %M:%d",
- time, timer->state);
+ if (nxt_timer_is_in_tree(timer)) {
- timer->state = NXT_TIMER_WAITING;
- return;
- }
+ diff = nxt_msec_diff(time, timer->time);
+ /*
+ * Use the previous timer if difference between it and the
+ * new timer is within bias: this decreases number of rbtree
+ * operations for fast connections.
+ */
+ if (nxt_abs(diff) <= timer->bias) {
+ nxt_debug(timer->task, "timer previous: %M±%d",
+ time, timer->bias);
+
+ nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0);
+ return;
}
}
- nxt_debug(timer->task, "timer add: %M:%d %M:%M",
- timer->time, timer->state, timeout, time);
-
nxt_timer_change(engine, timer, NXT_TIMER_ADD, time);
}
-void
-nxt_timer_disable(nxt_event_engine_t *engine, nxt_timer_t *timer)
-{
- nxt_debug(timer->task, "timer disable: %M:%d", timer->time, timer->state);
-
- if (timer->state != NXT_TIMER_CHANGING) {
- timer->state = NXT_TIMER_DISABLED;
-
- } else {
- nxt_timer_change(engine, timer, NXT_TIMER_DISABLE, 0);
- }
-}
-
-
nxt_bool_t
nxt_timer_delete(nxt_event_engine_t *engine, nxt_timer_t *timer)
{
- nxt_bool_t pending;
+ nxt_debug(timer->task, "timer delete: %M±%d",
+ timer->time, timer->bias);
+
+ timer->enabled = 0;
- if (nxt_timer_is_in_tree(timer) || timer->state == NXT_TIMER_CHANGING) {
- nxt_debug(timer->task, "timer delete: %M:%d",
- timer->time, timer->state);
+ if (nxt_timer_is_in_tree(timer)) {
nxt_timer_change(engine, timer, NXT_TIMER_DELETE, 0);
return 1;
}
- pending = (timer->state == NXT_TIMER_ENQUEUED);
-
- timer->state = NXT_TIMER_DISABLED;
+ nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0);
- return pending;
+ return (timer->queued || timer->change != NXT_TIMER_NO_CHANGE);
}
@@ -143,31 +131,36 @@ nxt_timer_change(nxt_event_engine_t *engine, nxt_timer_t *timer,
timers = &engine->timers;
- if (timers->nchanges >= timers->mchanges) {
- nxt_timer_changes_commit(engine);
- }
+ if (timer->change == NXT_TIMER_NO_CHANGE) {
+
+ if (change == NXT_TIMER_NOPE) {
+ return;
+ }
- nxt_debug(timer->task, "timer change: %M:%d", time, change);
+ if (timers->nchanges >= timers->mchanges) {
+ nxt_timer_changes_commit(engine);
+ }
+
+ timers->nchanges++;
+ timer->change = timers->nchanges;
+ }
- timer->state = NXT_TIMER_CHANGING;
+ nxt_debug(timer->task, "timer change: %M±%d:%d",
+ time, timer->bias, change);
- ch = &timers->changes[timers->nchanges];
+ ch = &timers->changes[timer->change - 1];
ch->change = change;
ch->time = time;
ch->timer = timer;
-
- timers->nchanges++;
}
static void
nxt_timer_changes_commit(nxt_event_engine_t *engine)
{
- int32_t diff;
- nxt_timer_t *timer;
+ nxt_timer_t *timer, **add, **add_end;
nxt_timers_t *timers;
- nxt_timer_state_t state;
nxt_timer_change_t *ch, *end;
timers = &engine->timers;
@@ -177,61 +170,54 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine)
ch = timers->changes;
end = ch + timers->nchanges;
- while (ch < end) {
- state = NXT_TIMER_DISABLED;
+ add = (nxt_timer_t **) ch;
+ add_end = add;
+ while (ch < end) {
timer = ch->timer;
switch (ch->change) {
- case NXT_TIMER_ADD:
- if (nxt_timer_is_in_tree(timer)) {
-
- diff = nxt_msec_diff(ch->time, timer->time);
- /* See the comment in nxt_timer_add(). */
+ case NXT_TIMER_NOPE:
+ break;
- if (nxt_abs(diff) < timer->precision) {
- nxt_debug(timer->task, "timer rbtree previous: %M:%d",
- ch->time, timer->state);
+ case NXT_TIMER_ADD:
- state = NXT_TIMER_WAITING;
- break;
- }
+ timer->time = ch->time;
- nxt_debug(timer->task, "timer rbtree delete: %M:%d",
- timer->time, timer->state);
+ *add_end++ = timer;
- nxt_rbtree_delete(&timers->tree, &timer->node);
+ if (!nxt_timer_is_in_tree(timer)) {
+ break;
}
- timer->time = ch->time;
+ /* Fall through. */
- nxt_debug(timer->task, "timer rbtree insert: %M", timer->time);
+ case NXT_TIMER_DELETE:
+ nxt_debug(timer->task, "timer rbtree delete: %M±%d",
+ timer->time, timer->bias);
- nxt_rbtree_insert(&timers->tree, &timer->node);
- nxt_timer_in_tree_set(timer);
- state = NXT_TIMER_WAITING;
+ nxt_rbtree_delete(&timers->tree, &timer->node);
+ nxt_timer_in_tree_clear(timer);
break;
+ }
- case NXT_TIMER_DELETE:
- if (nxt_timer_is_in_tree(timer)) {
- nxt_debug(timer->task, "timer rbtree delete: %M:%d",
- timer->time, timer->state);
+ timer->change = NXT_TIMER_NO_CHANGE;
- nxt_rbtree_delete(&timers->tree, &timer->node);
- nxt_timer_in_tree_clear(timer);
- }
+ ch++;
+ }
- break;
+ while (add < add_end) {
+ timer = *add;
- case NXT_TIMER_DISABLE:
- break;
- }
+ nxt_debug(timer->task, "timer rbtree insert: %M±%d",
+ timer->time, timer->bias);
- timer->state = state;
+ nxt_rbtree_insert(&timers->tree, &timer->node);
+ nxt_timer_in_tree_set(timer);
- ch++;
+ add++;
}
timers->nchanges = 0;
@@ -270,12 +256,12 @@ nxt_timer_find(nxt_event_engine_t *engine)
* return much earlier and the disabled timer can be reactivated.
*/
- if (timer->state != NXT_TIMER_DISABLED) {
+ if (timer->enabled) {
time = timer->time;
- timers->minimum = time;
+ timers->minimum = time - timer->bias;
- nxt_debug(timer->task, "timer found minimum: %M:%M",
- time, timers->now);
+ nxt_debug(timer->task, "timer found minimum: %M±%d:%M",
+ time, timer->bias, timers->now);
delta = nxt_msec_diff(time, timers->now);
@@ -317,21 +303,21 @@ nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now)
{
timer = (nxt_timer_t *) node;
- /* timer->time > now */
- if (nxt_msec_diff(timer->time , now) > 0) {
+ /* timer->time > now + timer->bias */
+ if (nxt_msec_diff(timer->time , now) > (int32_t) timer->bias) {
return;
}
next = nxt_rbtree_node_successor(tree, node);
- nxt_debug(timer->task, "timer expire delete: %M:%d",
- timer->time, timer->state);
+ nxt_debug(timer->task, "timer expire delete: %M±%d",
+ timer->time, timer->bias);
nxt_rbtree_delete(tree, &timer->node);
nxt_timer_in_tree_clear(timer);
- if (timer->state != NXT_TIMER_DISABLED) {
- timer->state = NXT_TIMER_ENQUEUED;
+ if (timer->enabled) {
+ timer->queued = 1;
nxt_work_queue_add(timer->work_queue, nxt_timer_handler,
timer->task, timer, NULL);
@@ -347,8 +333,10 @@ nxt_timer_handler(nxt_task_t *task, void *obj, void *data)
timer = obj;
- if (timer->state == NXT_TIMER_ENQUEUED) {
- timer->state = NXT_TIMER_DISABLED;
+ timer->queued = 0;
+
+ if (timer->enabled && timer->change == NXT_TIMER_NO_CHANGE) {
+ timer->enabled = 0;
timer->handler(task, timer, NULL);
}
diff --git a/src/nxt_timer.h b/src/nxt_timer.h
index 6531657d..4199f0dd 100644
--- a/src/nxt_timer.h
+++ b/src/nxt_timer.h
@@ -8,25 +8,29 @@
#define _NXT_TIMER_H_INCLUDED_
-/* Valid values are between 1ms to 255ms. */
-#define NXT_TIMER_DEFAULT_PRECISION 100
-//#define NXT_TIMER_DEFAULT_PRECISION 1
+/* Valid values are between 0ms to 255ms. */
+#define NXT_TIMER_DEFAULT_BIAS 50
+//#define NXT_TIMER_DEFAULT_BIAS 0
-typedef enum {
- NXT_TIMER_DISABLED = 0,
- NXT_TIMER_CHANGING,
- NXT_TIMER_WAITING,
- NXT_TIMER_ENQUEUED,
-} nxt_timer_state_t;
+/*
+ * The nxt_timer_t structure can hold up to 14 bits of change index,
+ * but 0 reserved for NXT_TIMER_NO_CHANGE.
+ */
+#define NXT_TIMER_MAX_CHANGES 16383
+#define NXT_TIMER_NO_CHANGE 0
typedef struct {
/* The rbtree node must be the first field. */
NXT_RBTREE_NODE (node);
- nxt_timer_state_t state:8;
- uint8_t precision;
+ uint8_t bias;
+
+ uint16_t change:14;
+ uint16_t enabled:1;
+ uint16_t queued:1;
+
nxt_msec_t time;
nxt_work_queue_t *work_queue;
@@ -37,13 +41,13 @@ typedef struct {
} nxt_timer_t;
-#define NXT_TIMER { NXT_RBTREE_NODE_INIT, NXT_TIMER_DISABLED, \
- 0, 0, NULL, NULL, NULL, NULL }
+#define NXT_TIMER { NXT_RBTREE_NODE_INIT, 0, NXT_TIMER_NO_CHANGE, \
+ 0, 0, 0, NULL, NULL, NULL, NULL }
typedef enum {
- NXT_TIMER_ADD = 0,
- NXT_TIMER_DISABLE,
+ NXT_TIMER_NOPE = 0,
+ NXT_TIMER_ADD,
NXT_TIMER_DELETE,
} nxt_timer_operation_t;
@@ -94,10 +98,16 @@ void nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now);
NXT_EXPORT void nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer,
nxt_msec_t timeout);
-NXT_EXPORT void nxt_timer_disable(nxt_event_engine_t *engine,
- nxt_timer_t *timer);
NXT_EXPORT nxt_bool_t nxt_timer_delete(nxt_event_engine_t *engine,
nxt_timer_t *timer);
+nxt_inline void
+nxt_timer_disable(nxt_event_engine_t *engine, nxt_timer_t *timer)
+{
+ nxt_debug(timer->task, "timer disable: %M", timer->time);
+
+ timer->enabled = 0;
+}
+
#endif /* _NXT_TIMER_H_INCLUDED_ */
diff --git a/src/nxt_unit.c b/src/nxt_unit.c
index 0f46dc7e..0d1be557 100644
--- a/src/nxt_unit.c
+++ b/src/nxt_unit.c
@@ -510,7 +510,7 @@ int
nxt_unit_process_msg(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id,
void *buf, size_t buf_size, void *oob, size_t oob_size)
{
- int fd, rc;
+ int fd, rc, nb;
pid_t pid;
nxt_queue_t incoming_buf;
struct cmsghdr *cm;
@@ -611,6 +611,15 @@ nxt_unit_process_msg(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id,
port_msg->stream, (int) new_port_msg->pid,
(int) new_port_msg->id, fd);
+ nb = 0;
+
+ if (nxt_slow_path(ioctl(fd, FIONBIO, &nb) == -1)) {
+ nxt_unit_alert(ctx, "#%"PRIu32": new_port: ioctl(%d, FIONBIO, 0) "
+ "failed: %s (%d)", fd, strerror(errno), errno);
+
+ goto fail;
+ }
+
nxt_unit_port_id_init(&new_port.id, new_port_msg->pid,
new_port_msg->id);
@@ -2158,9 +2167,12 @@ nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id, int fd)
msg.mf = 0;
msg.tracking = 0;
-#if (NXT_VALGRIND)
+ /*
+ * Fill all padding fields with 0.
+ * Code in Go 1.11 validate cmsghdr using padding field as part of len.
+ * See Cmsghdr definition and socketControlMessageHeaderAndData function.
+ */
memset(&cmsg, 0, sizeof(cmsg));
-#endif
cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
cmsg.cm.cmsg_level = SOL_SOCKET;
@@ -2992,9 +3004,7 @@ nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *dst,
m.new_port.max_size = 16 * 1024;
m.new_port.max_share = 64 * 1024;
-#if (NXT_VALGRIND)
memset(&cmsg, 0, sizeof(cmsg));
-#endif
cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
cmsg.cm.cmsg_level = SOL_SOCKET;
diff --git a/src/nxt_worker_process.c b/src/nxt_worker_process.c
index 8bcfb467..c068cca4 100644
--- a/src/nxt_worker_process.c
+++ b/src/nxt_worker_process.c
@@ -42,8 +42,8 @@ nxt_port_handlers_t nxt_discovery_process_port_handlers = {
const nxt_sig_event_t nxt_worker_process_signals[] = {
nxt_event_signal(SIGHUP, nxt_worker_process_signal_handler),
nxt_event_signal(SIGINT, nxt_worker_process_sigterm_handler),
- nxt_event_signal(SIGQUIT, nxt_worker_process_sigterm_handler),
- nxt_event_signal(SIGTERM, nxt_worker_process_sigquit_handler),
+ nxt_event_signal(SIGQUIT, nxt_worker_process_sigquit_handler),
+ nxt_event_signal(SIGTERM, nxt_worker_process_sigterm_handler),
nxt_event_signal(SIGCHLD, nxt_worker_process_signal_handler),
nxt_event_signal(SIGUSR1, nxt_worker_process_signal_handler),
nxt_event_signal(SIGUSR2, nxt_worker_process_signal_handler),
diff --git a/test/test_python_application.py b/test/test_python_application.py
index f1e2cbf7..e71b6432 100644
--- a/test/test_python_application.py
+++ b/test/test_python_application.py
@@ -60,7 +60,6 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython):
self.assertEqual(self.get()['headers']['Server-Port'], '7080',
'Server-Port header')
- @unittest.expectedFailure
def test_python_application_204_transfer_encoding(self):
self.load('204_no_content')
diff --git a/test/test_tls.py b/test/test_tls.py
index 26bedcb7..aaf939ec 100644
--- a/test/test_tls.py
+++ b/test/test_tls.py
@@ -137,11 +137,14 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
'RSA (1024 bits)', 'certificate key rsa')
def test_tls_certificate_key_ec(self):
+ self.load('empty')
+
subprocess.call(['openssl', 'ecparam', '-noout', '-genkey',
'-out', self.testdir + '/ec.key',
'-name', 'prime256v1'])
subprocess.call(['openssl', 'req', '-x509', '-new',
+ '-config', self.testdir + '/openssl.conf',
'-key', self.testdir + '/ec.key', '-subj', '/CN=ec/',
'-out', self.testdir + '/ec.crt'])
diff --git a/test/unit.py b/test/unit.py
index cec62489..98a0a4db 100644
--- a/test/unit.py
+++ b/test/unit.py
@@ -477,7 +477,7 @@ class TestUnitApplicationGo(TestUnitApplicationProto):
},
"applications": {
script: {
- "type": "go",
+ "type": "external",
"processes": { "spare": 0 },
"working_directory": self.current_dir + '/go/' + script,
"executable": self.testdir + '/go/' + name