diff options
author | Konstantin Pavlov <thresh@nginx.com> | 2022-06-02 16:51:49 +0400 |
---|---|---|
committer | Konstantin Pavlov <thresh@nginx.com> | 2022-06-02 16:51:49 +0400 |
commit | d9fddee1dbfc1f5d49c8f40386289d7188030952 (patch) | |
tree | 842a62b343ac33eba10e7a426a10b55bb1c46aed | |
parent | 420395ee2e7cd464e157c49bea3d74f15bf25f30 (diff) | |
parent | 0d48fe73c4450901622373e35f6ff3a944ec13d6 (diff) | |
download | unit-1.27.0-1.tar.gz unit-1.27.0-1.tar.bz2 |
Merged with the default branch.1.27.0-1
179 files changed, 2736 insertions, 1930 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..91875722 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/build/ +Makefile +*.pyc +__pycache__/ @@ -61,3 +61,4 @@ aa207ced9712132040e6153ceccdaf04c112d02c 1.25.0-1 1613ff17671df2273d48be57115f5fe4827f8cd5 1.26.0-1 1a08f884b24effa8b843d6aeeaf016b6354d1256 1.26.1 069c16dd4ed34d49584028b25f5cba4a4a2eded6 1.26.1-1 +8a9055cbe4ffd450fac4d7a849c00e0db5485ad3 1.27.0 @@ -1,4 +1,40 @@ +Changes with Unit 1.27.0 02 Jun 2022 + + *) Feature: ability to specify a custom index file name when serving + static files. + + *) Feature: variables support in the "location" option of the "return" + action. + + *) Feature: support empty strings in the "location" option of the + "return" action. + + *) Feature: added a new variable, $request_uri, that includes both the + path and the query parts as per RFC 3986, sections 3-4. + + *) Feature: Ruby Rack environment parameter "SCRIPT_NAME" support. + + *) Feature: compatibility with GCC 12. + + *) Bugfix: Ruby Sinatra applications don't work without custom logging. + + *) Bugfix: the controller process could crash when a chain of more than + four certificates was uploaded. + + *) Bugfix: some Perl applications failed to process the request body, + notably with Plack. + + *) Bugfix: some Spring Boot applications failed to start, notably with + Grails. + + *) Bugfix: incorrect Python protocol auto detection (ASGI or WSGI) for + native callable object, notably with Falcon. + + *) Bugfix: ECMAScript modules did not work with the recent Node.js + versions. + + Changes with Unit 1.26.1 02 Dec 2021 *) Bugfix: occasionally, the Unit daemon was unable to fully terminate; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..a7bc357b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,90 @@ +# Contributing Guidelines + +The following is a set of guidelines for contributing to NGINX Unit. We do +appreciate that you are considering contributing! + +## Table Of Contents + +- [Getting Started](#getting-started) +- [Ask a Question](#ask-a-question) +- [Contributing](#contributing) +- [Git Style Guide](#git-style-guide) + + +## Getting Started + +Check out the [Quick Installation](README.md#quick-installation) and +[Howto](https://unit.nginx.org/howto/) guides to get NGINX Unit up and running. + + +## Ask a Question + +Please open an [issue](https://github.com/nginx/unit/issues/new) on GitHub with +the label `question`. You can also ask a question on +[Slack](https://nginxcommunity.slack.com) or the NGINX Unit mailing list, +unit@nginx.org (subscribe +[here](https://mailman.nginx.org/mailman3/lists/unit.nginx.org/)). + + +## Contributing + +### Report a Bug + +Ensure the bug was not already reported by searching on GitHub under +[Issues](https://github.com/nginx/unit/issues). + +If the bug is a potential security vulnerability, please report using our +[security policy](https://unit.nginx.org/troubleshooting/#getting-support). + +To report a non-security bug, open an +[issue](https://github.com/nginx/unit/issues/new) on GitHub with the label +`bug`. Be sure to include a title and clear description, as much relevant +information as possible, and a code sample or an executable test case showing +the expected behavior that doesn't occur. + + +### Suggest an Enhancement + +To suggest an enhancement, open an +[issue](https://github.com/nginx/unit/issues/new) on GitHub with the label +`enhancement`. Please do this before implementing a new feature to discuss the +feature first. + + +### Open a Pull Request + +Before submitting a PR, please read the NGINX Unit code guidelines to know more +about coding conventions and benchmarks. Fork the repo, create a branch, and +submit a PR when your changes are tested and ready for review. Again, if you'd +like to implement a new feature, please consider creating a feature request +issue first to start a discussion about the feature. + + +## Git Style Guide + +- Keep a clean, concise and meaningful `git commit` history on your branch, + rebasing locally and squashing before submitting a PR + +- For any user-visible changes, updates, and bugfixes, add a note to + `docs/changes.xml` under the section for the upcoming release, using `<change + type="feature">` for new functionality, `<change type="change">` for changed + behavior, and `<change type="bugfix">` for bug fixes. + +- In the subject line, use the past tense ("Added feature", not "Add feature"); + also, use past tense to describe past scenarios, and present tense for + current behavior + +- Limit the subject line to 67 characters, and the rest of the commit message + to 80 characters + +- Use subject line prefixes for commits that affect a specific portion of the + code; examples include "Tests:", "Packages:", or "Docker:", and also + individual languages such as "Java:" or "Ruby:" + +- Reference issues and PRs liberally after the subject line; if the commit + remedies a GitHub issue, [name + it](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) + accordingly + +- Don't rely on command-line commit messages with `-m`; use the editor instead + @@ -1,13 +1,15 @@ NGINX Unit. - Copyright 2017-2021 NGINX, Inc. + Copyright 2017-2022 NGINX, Inc. + Copyright 2017-2022 Valentin V. Bartenev + Copyright 2017-2022 Max Romanov + Copyright 2017-2022 Andrei Zeliankou + Copyright 2018-2022 Konstantin Pavlov + Copyright 2021-2022 Zhidao Hong + Copyright 2021-2022 Oisín Canty Copyright 2017-2021 Igor Sysoev - Copyright 2017-2021 Valentin V. Bartenev - Copyright 2017-2021 Max Romanov - Copyright 2017-2021 Andrei Zeliankou Copyright 2017-2021 Andrei Belov - Copyright 2018-2021 Konstantin Pavlov Copyright 2019-2021 Tiago Natel de Moura Copyright 2019-2020 Axel Duch Copyright 2018-2019 Alexander Borisov diff --git a/README b/README deleted file mode 100644 index f0b84a42..00000000 --- a/README +++ /dev/null @@ -1,24 +0,0 @@ - -NGINX Unit ----------- - -The documentation and binary packages are available online: - - http://unit.nginx.org - -The source code is provided under the terms of Apache License 2.0: - - http://hg.nginx.org/unit - -Please ask questions, report issues, and send patches to the mailing list: - - unit@nginx.org (http://mailman.nginx.org/mailman/listinfo/unit) - -or via Github: - - https://github.com/nginx/unit - --- -NGINX, Inc. -http://nginx.com - diff --git a/README.md b/README.md new file mode 100644 index 00000000..2c3b7d1f --- /dev/null +++ b/README.md @@ -0,0 +1,183 @@ +# NGINX Unit + +## Universal Web App Server + +![NGINX Unit Logo](docs/unitlogo.png) + +NGINX Unit is a lightweight and versatile open-source server that has +three core capabilities: + +- it is an HTTP reverse proxy, +- a web server for static media assets, +- and an application server that runs code in seven languages. + +We are building a universal tool that compresses several layers of the modern +application stack into a potent, coherent solution with a focus on performance, +low latency, and scalability. It is intended as a building block for any web +architecture regardless of its complexity, from enterprise-scale deployments to +your pet's homepage. + +Unit's native RESTful JSON API enables dynamic updates with zero interruptions +and flexible configuration, while its out-of-the-box productivity reliably +scales to production-grade workloads. We achieve that with a complex, +asynchronous, multithreading architecture comprising multiple processes to +ensure security and robustness while getting the most out of today's computing +platforms. + + +## Quick Installation + +### macOS + +``` console +$ brew install nginx/unit/unit +``` + +For details and available language packages, see the +[docs](https://unit.nginx.org/installation/#homebrew). + + +### Docker + +``` console +$ docker pull docker.io/nginx/unit +``` + +For a description of image tags, see the +[docs](https://unit.nginx.org/installation/#docker-images). + + +### Amazon Linux, Fedora, RedHat + +``` console +$ curl -sL 'https://unit.nginx.org/_downloads/setup-unit.sh' | sudo -E bash +# yum install unit +``` + +For details and available language packages, see the +[docs](https://unit.nginx.org/installation/#official-packages). + + +### Debian, Ubuntu + +``` console +$ curl -sL 'https://unit.nginx.org/_downloads/setup-unit.sh' | sudo -E bash +# apt install unit +``` + +For details and available language packages, see the +[docs](https://unit.nginx.org/installation/#official-packages). + + +## Running a Hello World App + +Suppose you saved a PHP script as `/www/helloworld/index.php`: +``` php +<?php echo "Hello, PHP on Unit!"; ?> +``` + +To run it on Unit with the `unit-php` module installed, first set up an +application object. Let's store our first config snippet in a file called +`config.json`: + +``` json +{ + "helloworld": { + "type": "php", + "root": "/www/helloworld/" + } +} +``` + +Saving it as a file isn't necessary, but can come in handy with larger objects. + +Now, `PUT` it into the `config/applications` section of Unit's control API, +usually available by default via a Unix domain socket: + +``` console +# curl -X PUT --data-binary @config.json --unix-socket \ + /path/to/control.unit.sock http://localhost/config/applications +``` +``` json + +{ + "success": "Reconfiguration done." +} +``` + +Next, reference the app from a listener object in the `config/listeners` +section of the API. This time, we pass the config snippet straight from the +command line: + +``` console +# curl -X PUT -d '{"127.0.0.1:8000": {"pass": "applications/helloworld"}}' \ + --unix-socket /path/to/control.unit.sock http://localhost/config/listeners +``` +``` json +{ + "success": "Reconfiguration done." +} +``` + +Now Unit accepts requests at the specified IP and port, passing them to the +application process. Your app works! + +``` console +$ curl 127.0.0.1:8080 + + Hello, PHP on Unit! +``` + +Finally, query the entire `/config` section of the control API: + +``` console +# curl --unix-socket /path/to/control.unit.sock http://localhost/config/ +``` + +Unit's output should contain both snippets, neatly organized: + +``` json +{ + "listeners": { + "127.0.0.1:8080": { + "pass": "applications/helloworld" + } + }, + + "applications": { + "helloworld": { + "type": "php", + "root": "/www/helloworld/" + } + } +} +``` + +For full details of configuration management, see the +[docs](https://unit.nginx.org/configuration/#configuration-management). + + +## Community + +- The go-to place to start asking questions and share your thoughts is + our [Slack channel](https://nginxcommunity.slack.com/). + +- Our [GitHub issues page](https://github.com/nginx/unit/issues) offers + space for a more technical discussion at your own pace. + +- The [project map](https://github.com/orgs/nginx/projects/1) on + GitHub sheds some light on our current work and plans for the future. + +- Our [official website](https://unit.nginx.org/) may provide answers + not easily found otherwise. + +- Get involved with the project by contributing! See the + [contributing guide](CONTRIBUTING.md) for details. + +- To reach the team directly, subscribe to the + [mailing list](https://mailman.nginx.org/mailman/listinfo/unit). + +- For security issues, [email us](security-alert@nginx.org), mentioning + NGINX Unit in the subject and following the [CVSS + v3.1](https://www.first.org/cvss/v3.1/specification-document) spec. + @@ -176,3 +176,21 @@ nxt_feature_test="struct s { return 1; }" . auto/feature + + +nxt_feature="GCC __attribute__ unused" +nxt_feature_name=NXT_HAVE_GCC_ATTRIBUTE_UNUSED +nxt_feature_run= +nxt_feature_incs= +nxt_feature_libs= +nxt_feature_test="static void f(void) __attribute__ ((__unused__)); + + static void f(void) + { + return; + } + + int main(void) { + return 0; + }" +. auto/feature diff --git a/auto/modules/go b/auto/modules/go index 7324ffbe..a8596bf3 100644 --- a/auto/modules/go +++ b/auto/modules/go @@ -111,7 +111,8 @@ install: ${NXT_GO}-install ${NXT_GO}: ${NXT_GO}-install: ${NXT_GO}-install-src ${NXT_GO}-install-env - GOPATH=\$(DESTDIR)\$(GOPATH) GO111MODULE=auto ${NXT_GO} build ${NXT_GO_PKG} + cd \$(DESTDIR)\$(NXT_GO_DST)/src/${NXT_GO_PKG} && \ + GOPATH=\$(DESTDIR)\$(GOPATH) ${NXT_GO} build ${NXT_GO_PKG} ${NXT_GO}-install-src: install -d \$(DESTDIR)\$(NXT_GO_DST)/src/${NXT_GO_PKG} diff --git a/auto/modules/ruby b/auto/modules/ruby index 68324b44..dbedfd72 100644 --- a/auto/modules/ruby +++ b/auto/modules/ruby @@ -56,6 +56,7 @@ nxt_found=no if /bin/sh -c "$NXT_RUBY -v" >> $NXT_AUTOCONF_ERR 2>&1; then + NXT_RUBY_CFLAGS= NXT_RUBY_RUBYHDRDIR=`$NXT_RUBY -rrbconfig -e 'print RbConfig::CONFIG["rubyhdrdir"]'` NXT_RUBY_ARCHHDRDIR=`$NXT_RUBY -rrbconfig -e 'print RbConfig::CONFIG["rubyarchhdrdir"]'` NXT_RUBY_SITEDIR=`$NXT_RUBY -rrbconfig -e 'print RbConfig::CONFIG["sitedir"]'` @@ -72,6 +73,31 @@ if /bin/sh -c "$NXT_RUBY -v" >> $NXT_AUTOCONF_ERR 2>&1; then NXT_RUBY_LIBPATH=`$NXT_RUBY -rrbconfig -e 'print RbConfig::CONFIG["libdir"]'` NXT_RUBY_LIBS="-l$NXT_RUBY_LIBNAME $NXT_RUBY_LIBSCONF" + if [ $NXT_CC_NAME = clang ]; then + # Workaround Clang bug + nxt_feature="-fdeclspec" + nxt_feature_name= + nxt_feature_run= + nxt_feature_incs="-fdeclspec" + nxt_feature_libs= + nxt_feature_test="#include <stdlib.h> + + __declspec(noreturn) static void f(void); + + static void f(void) { + exit(0); + } + + int main(void) { + f(); + }" + . auto/feature + + if [ $nxt_found = yes ]; then + NXT_RUBY_CFLAGS="$NXT_RUBY_CFLAGS -fdeclspec" + fi + fi + nxt_feature="Ruby library" nxt_feature_name="" nxt_feature_run=value @@ -205,7 +231,7 @@ for nxt_src in $NXT_RUBY_MODULE_SRCS; do $NXT_BUILD_DIR/$nxt_obj: $nxt_src $NXT_VERSION_H mkdir -p $NXT_BUILD_DIR/src/ruby - \$(CC) -c \$(CFLAGS) -DNXT_RUBY_MOUNTS_H=\"$NXT_RUBY_MOUNTS_HEADER\" \\ + \$(CC) -c \$(CFLAGS) $NXT_RUBY_CFLAGS -DNXT_RUBY_MOUNTS_H=\"$NXT_RUBY_MOUNTS_HEADER\" \\ \$(NXT_INCS) $NXT_RUBY_INCPATH \\ $nxt_dep_flags \\ -o $NXT_BUILD_DIR/$nxt_obj $nxt_src diff --git a/auto/os/test b/auto/os/test index c37700a6..b7e73299 100644 --- a/auto/os/test +++ b/auto/os/test @@ -97,4 +97,5 @@ case "$NXT_SYSTEM" in esac -$echo configuring for $NXT_SYSTEM $NXT_SYSTEM_VERSION $NXT_SYSTEM_PLATFORM +$echo "configuring Unit $NXT_VERSION" \ + "for $NXT_SYSTEM $NXT_SYSTEM_VERSION $NXT_SYSTEM_PLATFORM" @@ -67,6 +67,7 @@ case $nxt_module in esac +. ./version . auto/os/test . auto/options diff --git a/docs/changes.xml b/docs/changes.xml index de96451b..1d8a13c2 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -14,6 +14,110 @@ unit-ruby unit-jsc-common unit-jsc8 unit-jsc10 unit-jsc11 unit-jsc13 unit-jsc14 unit-jsc15 unit-jsc16 unit-jsc17 unit-jsc18" + ver="1.27.0" rev="1" + date="" time="" + packager="Andrei Belov <defan@nginx.com>"> + +<change> +<para> +NGINX Unit updated to 1.27.0. +</para> +</change> + +</changes> + + +<changes apply="unit" ver="1.27.0" rev="1" + date="" time="" + packager="Andrei Belov <defan@nginx.com>"> + +<change type="feature"> +<para> +ability to specify a custom index file name when serving static files. +</para> +</change> + +<change type="feature"> +<para> +variables support in the "location" option of the "return" action. +</para> +</change> + +<change type="feature"> +<para> +support empty strings in the "location" option of the "return" action. +</para> +</change> + +<change type="feature"> +<para> +added a new variable, $request_uri, that includes both the path and the query +parts as per RFC 3986, sections 3-4. +</para> +</change> + +<change type="feature"> +<para> +Ruby Rack environment parameter "SCRIPT_NAME" support. +</para> +</change> + +<change type="feature"> +<para> +compatibility with GCC 12. +</para> +</change> + +<change type="bugfix"> +<para> +Ruby Sinatra applications don't work without custom logging. +</para> +</change> + +<change type="bugfix"> +<para> +the controller process could crash when a chain of more than four +certificates was uploaded. +</para> +</change> + +<change type="bugfix"> +<para> +some Perl applications failed to process the request body, notably with Plack. +</para> +</change> + +<change type="bugfix"> +<para> +some Spring Boot applications failed to start, notably with Grails. +</para> +</change> + +<change type="bugfix"> +<para> +incorrect Python protocol auto detection (ASGI or WSGI) for native callable +object, notably with Falcon. +</para> +</change> + +<change type="bugfix"> +<para> +ECMAScript modules did not work with the recent Node.js versions. +</para> +</change> + +</changes> + + +<changes apply="unit-php + unit-python unit-python2.7 + unit-python3.4 unit-python3.5 unit-python3.6 unit-python3.7 + unit-python3.8 unit-python3.9 unit-python3.10 + unit-go + unit-perl + unit-ruby + unit-jsc-common unit-jsc8 unit-jsc10 unit-jsc11 unit-jsc13 + unit-jsc14 unit-jsc15 unit-jsc16 unit-jsc17 unit-jsc18" ver="1.26.1" rev="1" date="2021-12-02" time="18:00:00 +0300" packager="Andrei Belov <defan@nginx.com>"> diff --git a/docs/unitlogo.png b/docs/unitlogo.png Binary files differnew file mode 100644 index 00000000..dbd87fd8 --- /dev/null +++ b/docs/unitlogo.png diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 00000000..2c0431db --- /dev/null +++ b/go/go.mod @@ -0,0 +1 @@ +module unit.nginx.org/go diff --git a/pkg/deb/Makefile b/pkg/deb/Makefile index 66a5f33a..52813e37 100644 --- a/pkg/deb/Makefile +++ b/pkg/deb/Makefile @@ -19,6 +19,20 @@ BUILD_DEPENDS = $(BUILD_DEPENDS_unit) MODULES= +# Ubuntu 22.04 +ifeq ($(CODENAME),jammy) +include Makefile.php +include Makefile.python27 +include Makefile.python310 +include Makefile.go +include Makefile.perl +include Makefile.ruby +include Makefile.jsc-common +include Makefile.jsc11 +include Makefile.jsc17 +include Makefile.jsc18 +endif + # Ubuntu 21.10 ifeq ($(CODENAME),impish) include Makefile.php @@ -180,7 +194,7 @@ endif debuild/unit_$(VERSION).orig.tar.gz: | debuild/$(SRCDIR)/debian cd ../.. && tar -czf pkg/deb/debuild/$(SRCDIR).tar.gz \ --transform "s#^#$(SRCDIR)/#" \ - LICENSE NOTICE CHANGES README configure auto src test version go docs/man/unitd.8.in + LICENSE NOTICE CHANGES README.md CONTRIBUTING.md configure auto src test version go docs/man/unitd.8.in mv debuild/$(SRCDIR).tar.gz debuild/unit_$(VERSION).orig.tar.gz cd debuild && tar zxf unit_$(VERSION).orig.tar.gz diff --git a/pkg/deb/Makefile.go b/pkg/deb/Makefile.go index cdccb5ed..b9463076 100644 --- a/pkg/deb/Makefile.go +++ b/pkg/deb/Makefile.go @@ -36,7 +36,7 @@ The $(MODULE_SUMMARY_go) has been installed. To check out the sample app, run these commands: - GOPATH=/usr/share/gocode go build -o /tmp/go-app /usr/share/doc/unit-$(MODULE_SUFFIX_go)/examples/go-app/let-my-people.go + GOPATH=/usr/share/gocode GO111MODULE=auto go build -o /tmp/go-app /usr/share/doc/unit-$(MODULE_SUFFIX_go)/examples/go-app/let-my-people.go sudo service unit restart cd /usr/share/doc/unit-$(MODULE_SUFFIX_go)/examples sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/control.unit.sock http://localhost/config diff --git a/pkg/deb/debian.module/copyright.unit-jsc10 b/pkg/deb/debian.module/copyright.unit-jsc10 index dbad728b..42dbd3b9 100644 --- a/pkg/deb/debian.module/copyright.unit-jsc10 +++ b/pkg/deb/debian.module/copyright.unit-jsc10 @@ -1,10 +1,17 @@ NGINX Unit. - Copyright 2017-2019 NGINX, Inc. - Copyright 2017-2019 Igor Sysoev - Copyright 2017-2019 Valentin V. Bartenev - Copyright 2017-2019 Max Romanov + Copyright 2017-2022 NGINX, Inc. + Copyright 2017-2022 Valentin V. Bartenev + Copyright 2017-2022 Max Romanov + Copyright 2017-2022 Andrei Zeliankou + Copyright 2018-2022 Konstantin Pavlov + Copyright 2021-2022 Zhidao Hong + Copyright 2021-2022 Oisín Canty + Copyright 2017-2021 Igor Sysoev + Copyright 2017-2021 Andrei Belov + Copyright 2019-2021 Tiago Natel de Moura + Copyright 2019-2020 Axel Duch Copyright 2018-2019 Alexander Borisov Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/deb/debian.module/copyright.unit-jsc11 b/pkg/deb/debian.module/copyright.unit-jsc11 index 413c0094..b2e4a117 100644 --- a/pkg/deb/debian.module/copyright.unit-jsc11 +++ b/pkg/deb/debian.module/copyright.unit-jsc11 @@ -1,10 +1,17 @@ NGINX Unit. - Copyright 2017-2019 NGINX, Inc. - Copyright 2017-2019 Igor Sysoev - Copyright 2017-2019 Valentin V. Bartenev - Copyright 2017-2019 Max Romanov + Copyright 2017-2022 NGINX, Inc. + Copyright 2017-2022 Valentin V. Bartenev + Copyright 2017-2022 Max Romanov + Copyright 2017-2022 Andrei Zeliankou + Copyright 2018-2022 Konstantin Pavlov + Copyright 2021-2022 Zhidao Hong + Copyright 2021-2022 Oisín Canty + Copyright 2017-2021 Igor Sysoev + Copyright 2017-2021 Andrei Belov + Copyright 2019-2021 Tiago Natel de Moura + Copyright 2019-2020 Axel Duch Copyright 2018-2019 Alexander Borisov Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/deb/debian.module/copyright.unit-jsc8 b/pkg/deb/debian.module/copyright.unit-jsc8 index 96b62102..1dab9cce 100644 --- a/pkg/deb/debian.module/copyright.unit-jsc8 +++ b/pkg/deb/debian.module/copyright.unit-jsc8 @@ -1,10 +1,17 @@ NGINX Unit. - Copyright 2017-2019 NGINX, Inc. - Copyright 2017-2019 Igor Sysoev - Copyright 2017-2019 Valentin V. Bartenev - Copyright 2017-2019 Max Romanov + Copyright 2017-2022 NGINX, Inc. + Copyright 2017-2022 Valentin V. Bartenev + Copyright 2017-2022 Max Romanov + Copyright 2017-2022 Andrei Zeliankou + Copyright 2018-2022 Konstantin Pavlov + Copyright 2021-2022 Zhidao Hong + Copyright 2021-2022 Oisín Canty + Copyright 2017-2021 Igor Sysoev + Copyright 2017-2021 Andrei Belov + Copyright 2019-2021 Tiago Natel de Moura + Copyright 2019-2020 Axel Duch Copyright 2018-2019 Alexander Borisov Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/deb/debian.module/rules-noarch.in b/pkg/deb/debian.module/rules-noarch.in index a24602c4..0f05aaba 100644 --- a/pkg/deb/debian.module/rules-noarch.in +++ b/pkg/deb/debian.module/rules-noarch.in @@ -26,7 +26,8 @@ config.env.%: cp -Pa $(CURDIR)/CHANGES $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/LICENSE $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/NOTICE $(BUILDDIR_$*)/ - cp -Pa $(CURDIR)/README $(BUILDDIR_$*)/ + cp -Pa $(CURDIR)/README.md $(BUILDDIR_$*)/ + cp -Pa $(CURDIR)/CONTRIBUTING.md $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/go $(BUILDDIR_$*)/ touch $@ diff --git a/pkg/deb/debian.module/rules.in b/pkg/deb/debian.module/rules.in index 8ee277b3..f1217553 100755 --- a/pkg/deb/debian.module/rules.in +++ b/pkg/deb/debian.module/rules.in @@ -26,7 +26,8 @@ config.env.%: cp -Pa $(CURDIR)/CHANGES $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/LICENSE $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/NOTICE $(BUILDDIR_$*)/ - cp -Pa $(CURDIR)/README $(BUILDDIR_$*)/ + cp -Pa $(CURDIR)/README.md $(BUILDDIR_$*)/ + cp -Pa $(CURDIR)/CONTRIBUTING.md $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/go $(BUILDDIR_$*)/ touch $@ diff --git a/pkg/deb/debian/copyright b/pkg/deb/debian/copyright index 2a2c5fd0..487c92c5 100644 --- a/pkg/deb/debian/copyright +++ b/pkg/deb/debian/copyright @@ -1,13 +1,15 @@ NGINX Unit. - Copyright 2017-2021 NGINX, Inc. + Copyright 2017-2022 NGINX, Inc. + Copyright 2017-2022 Valentin V. Bartenev + Copyright 2017-2022 Max Romanov + Copyright 2017-2022 Andrei Zeliankou + Copyright 2018-2022 Konstantin Pavlov + Copyright 2021-2022 Zhidao Hong + Copyright 2021-2022 Oisín Canty Copyright 2017-2021 Igor Sysoev - Copyright 2017-2021 Valentin V. Bartenev - Copyright 2017-2021 Max Romanov - Copyright 2017-2021 Andrei Zeliankou Copyright 2017-2021 Andrei Belov - Copyright 2018-2021 Konstantin Pavlov Copyright 2019-2021 Tiago Natel de Moura Copyright 2019-2020 Axel Duch Copyright 2018-2019 Alexander Borisov diff --git a/pkg/deb/debian/rules.in b/pkg/deb/debian/rules.in index fe7d5c7c..d2e34796 100644 --- a/pkg/deb/debian/rules.in +++ b/pkg/deb/debian/rules.in @@ -31,7 +31,8 @@ config.env.%: cp -Pa $(CURDIR)/CHANGES $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/LICENSE $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/NOTICE $(BUILDDIR_$*)/ - cp -Pa $(CURDIR)/README $(BUILDDIR_$*)/ + cp -Pa $(CURDIR)/README.md $(BUILDDIR_$*)/ + cp -Pa $(CURDIR)/CONTRIBUTING.md $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/go $(BUILDDIR_$*)/ mkdir -p $(BUILDDIR_$*)/docs/man cp -Pa $(CURDIR)/docs/man/unitd.8.in $(BUILDDIR_$*)/docs/man/ @@ -109,7 +110,8 @@ install: build do.tests 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/changelog - install -m 644 README $(INSTALLDIR)/usr/share/doc/unit/ + install -m 644 README.md $(INSTALLDIR)/usr/share/doc/unit/ + install -m 644 CONTRIBUTING.md $(INSTALLDIR)/usr/share/doc/unit/ install -m 644 NOTICE $(INSTALLDIR)/usr/share/doc/unit/ binary-indep: build install diff --git a/pkg/docker/Dockerfile.go1.17 b/pkg/docker/Dockerfile.go1.18 index e7443e8c..9162d8cf 100644 --- a/pkg/docker/Dockerfile.go1.17 +++ b/pkg/docker/Dockerfile.go1.18 @@ -1,4 +1,4 @@ -FROM golang:1.17 as BUILDER +FROM golang:1.18 as BUILDER LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>" @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.26.1 \ + && hg up 1.27.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -40,16 +40,20 @@ RUN set -ex \ && make -j $NCPU go-install-src libunit-install \ && ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt -FROM golang:1.17 +FROM golang:1.18 COPY docker-entrypoint.sh /usr/local/bin/ COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt -COPY --from=BUILDER /usr/lib/x86_64-linux-gnu/libunit.a /usr/lib/x86_64-linux-gnu/ +COPY --from=BUILDER /usr/lib/*-linux-gnu/libunit.a /tmp/ COPY --from=BUILDER /usr/include/nxt_* /usr/include/ COPY --from=BUILDER /go/src/ /go/src/ RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/docker/Dockerfile.jsc11 b/pkg/docker/Dockerfile.jsc11 index 8e89fc22..69fc72ad 100644 --- a/pkg/docker/Dockerfile.jsc11 +++ b/pkg/docker/Dockerfile.jsc11 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.26.1 \ + && hg up 1.27.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -48,6 +48,10 @@ COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt COPY --from=BUILDER /usr/share/unit-jsc-common/ /usr/share/unit-jsc-common/ RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/docker/Dockerfile.minimal b/pkg/docker/Dockerfile.minimal index 36c9af1c..730e1893 100644 --- a/pkg/docker/Dockerfile.minimal +++ b/pkg/docker/Dockerfile.minimal @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.26.1 \ + && hg up 1.27.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -48,6 +48,10 @@ COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/docker/Dockerfile.node16 b/pkg/docker/Dockerfile.node16 index 3b4a98e2..246105d8 100644 --- a/pkg/docker/Dockerfile.node16 +++ b/pkg/docker/Dockerfile.node16 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.26.1 \ + && hg up 1.27.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -46,10 +46,14 @@ COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt -COPY --from=BUILDER /usr/lib/x86_64-linux-gnu/libunit.a /usr/lib/x86_64-linux-gnu/ +COPY --from=BUILDER /usr/lib/*-linux-gnu/libunit.a /tmp/ COPY --from=BUILDER /usr/include/nxt_* /usr/include/ COPY --from=BUILDER /usr/local/lib/node_modules/unit-http/ /usr/local/lib/node_modules/unit-http/ RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/docker/Dockerfile.perl5.34 b/pkg/docker/Dockerfile.perl5.34 index cee1a829..db87d209 100644 --- a/pkg/docker/Dockerfile.perl5.34 +++ b/pkg/docker/Dockerfile.perl5.34 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.26.1 \ + && hg up 1.27.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -48,6 +48,10 @@ COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/docker/Dockerfile.php8.1 b/pkg/docker/Dockerfile.php8.1 index 43f4bb03..5c18a9bc 100644 --- a/pkg/docker/Dockerfile.php8.1 +++ b/pkg/docker/Dockerfile.php8.1 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.26.1 \ + && hg up 1.27.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -48,6 +48,10 @@ COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt RUN ldconfig RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/docker/Dockerfile.python3.10 b/pkg/docker/Dockerfile.python3.10 index 17c1d9b0..09e7f42a 100644 --- a/pkg/docker/Dockerfile.python3.10 +++ b/pkg/docker/Dockerfile.python3.10 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.26.1 \ + && hg up 1.27.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -48,6 +48,10 @@ COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/docker/Dockerfile.ruby3.0 b/pkg/docker/Dockerfile.ruby3.1 index 8da13e20..0baedc32 100644 --- a/pkg/docker/Dockerfile.ruby3.0 +++ b/pkg/docker/Dockerfile.ruby3.1 @@ -1,4 +1,4 @@ -FROM ruby:3.0 as BUILDER +FROM ruby:3.1 as BUILDER LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>" @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.26.1 \ + && hg up 1.27.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ @@ -40,7 +40,7 @@ RUN set -ex \ && make -j $NCPU ruby-install \ && ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt -FROM ruby:3.0 +FROM ruby:3.1 COPY docker-entrypoint.sh /usr/local/bin/ COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug @@ -48,6 +48,10 @@ COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt RUN gem install rack RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/docker/Makefile b/pkg/docker/Makefile index f8578986..5c48f925 100644 --- a/pkg/docker/Makefile +++ b/pkg/docker/Makefile @@ -18,12 +18,12 @@ INSTALL_minimal ?= version define COPY_minimal endef -VERSION_go ?= 1.17 +VERSION_go ?= 1.18 CONTAINER_go ?= golang:$(VERSION_go) CONFIGURE_go ?= go --go-path=$$GOPATH INSTALL_go ?= go-install-src libunit-install define COPY_go -COPY --from=BUILDER /usr/lib/x86_64-linux-gnu/libunit.a /usr/lib/x86_64-linux-gnu/\n\$ +COPY --from=BUILDER /usr/lib/\*-linux-gnu/libunit.a /tmp/\n\$ COPY --from=BUILDER /usr/include/nxt_* /usr/include/\n\$ COPY --from=BUILDER /go/src/ /go/src/ endef @@ -39,7 +39,7 @@ CONTAINER_node ?= node:$(VERSION_node) CONFIGURE_node ?= nodejs --node-gyp=/usr/local/lib/node_modules/npm/bin/node-gyp-bin/node-gyp INSTALL_node ?= node node-install libunit-install define COPY_node -COPY --from=BUILDER /usr/lib/x86_64-linux-gnu/libunit.a /usr/lib/x86_64-linux-gnu/\n\$ +COPY --from=BUILDER /usr/lib/\*-linux-gnu/libunit.a /tmp/\n\$ COPY --from=BUILDER /usr/include/nxt_* /usr/include/\n\$ COPY --from=BUILDER /usr/local/lib/node_modules/unit-http/ /usr/local/lib/node_modules/unit-http/ endef @@ -62,7 +62,7 @@ CONFIGURE_python ?= python --config=/usr/local/bin/python3-config INSTALL_python ?= python3-install COPY_python = -VERSION_ruby ?= 3.0 +VERSION_ruby ?= 3.1 CONTAINER_ruby ?= ruby:$(VERSION_ruby) CONFIGURE_ruby ?= ruby INSTALL_ruby ?= ruby-install diff --git a/pkg/docker/template.Dockerfile b/pkg/docker/template.Dockerfile index 55feecc6..2d964eb6 100644 --- a/pkg/docker/template.Dockerfile +++ b/pkg/docker/template.Dockerfile @@ -48,6 +48,10 @@ COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ COPY --from=BUILDER /requirements.apt /requirements.apt @@COPY@@ RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ && mkdir -p /var/lib/unit/ \ && mkdir /docker-entrypoint.d/ \ && addgroup --system unit \ diff --git a/pkg/rpm/Makefile b/pkg/rpm/Makefile index 011eba5b..a360b36e 100644 --- a/pkg/rpm/Makefile +++ b/pkg/rpm/Makefile @@ -16,6 +16,8 @@ else ifeq ($(shell test `rpm --eval '0%{?rhel} -eq 7 -a 0%{?amzn} -eq 0'`; echo OSVER = centos7 else ifeq ($(shell rpm --eval "%{?rhel}"), 8) OSVER = centos8 +else ifeq ($(shell rpm --eval "%{?rhel}"), 9) +OSVER = centos9 else ifeq ($(shell rpm --eval "%{?amzn}"), 1) OSVER = amazonlinux1 else ifeq ($(shell rpm --eval "%{?amzn}"), 2) @@ -84,6 +86,16 @@ include Makefile.jsc8 include Makefile.jsc11 endif +ifeq ($(OSVER), centos9) +include Makefile.php +include Makefile.python39 +include Makefile.go +include Makefile.perl +include Makefile.jsc-common +include Makefile.jsc8 +include Makefile.jsc11 +endif + ifeq ($(OSVER), amazonlinux1) include Makefile.php include Makefile.python27 @@ -223,7 +235,7 @@ endif rpmbuild/SOURCES/unit-$(VERSION).tar.gz: cd ../.. && tar -czf pkg/rpm/rpmbuild/SOURCES/unit-$(VERSION).tar.gz \ --transform "s#^#unit-$(VERSION)/#" \ - LICENSE NOTICE CHANGES README configure auto src test version go docs/man/unitd.8.in + LICENSE NOTICE CHANGES README.md CONTRIBUTING.md configure auto src test version go docs/man/unitd.8.in unit: check-build-depends-unit rpmbuild/SPECS/unit.spec rpmbuild/SOURCES/unit-$(VERSION).tar.gz @echo "===> Building $@ package" ; \ diff --git a/pkg/rpm/Makefile.go b/pkg/rpm/Makefile.go index e3891ab4..a1421bee 100644 --- a/pkg/rpm/Makefile.go +++ b/pkg/rpm/Makefile.go @@ -65,7 +65,7 @@ The $(MODULE_SUMMARY_go) has been installed. To check the sample app, run these commands: - GOPATH=%{gopath} go build -o /tmp/go-app /usr/share/doc/unit-go/examples/go-app/let-my-people.go + GOPATH=%{gopath} GO111MODULE=auto go build -o /tmp/go-app /usr/share/doc/unit-go/examples/go-app/let-my-people.go sudo service unit start cd /usr/share/doc/%{name}/examples sudo curl -X PUT --data-binary @unit.config --unix-socket /var/run/unit/control.sock http://localhost/config diff --git a/pkg/rpm/Makefile.python39 b/pkg/rpm/Makefile.python39 index 8e444e56..3f791111 100644 --- a/pkg/rpm/Makefile.python39 +++ b/pkg/rpm/Makefile.python39 @@ -13,7 +13,7 @@ MODULE_INSTARGS_python39= python3.9-install MODULE_SOURCES_python39= unit.example-python-app \ unit.example-python39-config -ifneq (,$(findstring $(OSVER),opensuse-tumbleweed sles fedora amazonlinux2)) +ifneq (,$(findstring $(OSVER),opensuse-tumbleweed sles fedora amazonlinux2 centos9)) BUILD_DEPENDS_python39= python3-devel else BUILD_DEPENDS_python39= python39-devel diff --git a/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10 b/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10 index 665785b2..c7860e4b 100644 --- a/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10 +++ b/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10 @@ -1,10 +1,17 @@ NGINX Unit. - Copyright 2017-2019 NGINX, Inc. - Copyright 2017-2019 Igor Sysoev - Copyright 2017-2019 Valentin V. Bartenev - Copyright 2017-2019 Max Romanov + Copyright 2017-2022 NGINX, Inc. + Copyright 2017-2022 Valentin V. Bartenev + Copyright 2017-2022 Max Romanov + Copyright 2017-2022 Andrei Zeliankou + Copyright 2018-2022 Konstantin Pavlov + Copyright 2021-2022 Zhidao Hong + Copyright 2021-2022 Oisín Canty + Copyright 2017-2021 Igor Sysoev + Copyright 2017-2021 Andrei Belov + Copyright 2019-2021 Tiago Natel de Moura + Copyright 2019-2020 Axel Duch Copyright 2018-2019 Alexander Borisov Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc11 b/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc11 index e92a8245..b08fcc34 100644 --- a/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc11 +++ b/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc11 @@ -1,10 +1,17 @@ NGINX Unit. - Copyright 2017-2019 NGINX, Inc. - Copyright 2017-2019 Igor Sysoev - Copyright 2017-2019 Valentin V. Bartenev - Copyright 2017-2019 Max Romanov + Copyright 2017-2022 NGINX, Inc. + Copyright 2017-2022 Valentin V. Bartenev + Copyright 2017-2022 Max Romanov + Copyright 2017-2022 Andrei Zeliankou + Copyright 2018-2022 Konstantin Pavlov + Copyright 2021-2022 Zhidao Hong + Copyright 2021-2022 Oisín Canty + Copyright 2017-2021 Igor Sysoev + Copyright 2017-2021 Andrei Belov + Copyright 2019-2021 Tiago Natel de Moura + Copyright 2019-2020 Axel Duch Copyright 2018-2019 Alexander Borisov Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc8 b/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc8 index 1e7dbff6..5e31863d 100644 --- a/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc8 +++ b/pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc8 @@ -1,10 +1,17 @@ NGINX Unit. - Copyright 2017-2019 NGINX, Inc. - Copyright 2017-2019 Igor Sysoev - Copyright 2017-2019 Valentin V. Bartenev - Copyright 2017-2019 Max Romanov + Copyright 2017-2022 NGINX, Inc. + Copyright 2017-2022 Valentin V. Bartenev + Copyright 2017-2022 Max Romanov + Copyright 2017-2022 Andrei Zeliankou + Copyright 2018-2022 Konstantin Pavlov + Copyright 2021-2022 Zhidao Hong + Copyright 2021-2022 Oisín Canty + Copyright 2017-2021 Igor Sysoev + Copyright 2017-2021 Andrei Belov + Copyright 2019-2021 Tiago Natel de Moura + Copyright 2019-2020 Axel Duch Copyright 2018-2019 Alexander Borisov Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/pkg/rpm/unit.spec.in b/pkg/rpm/unit.spec.in index f643b77f..4cbc7358 100644 --- a/pkg/rpm/unit.spec.in +++ b/pkg/rpm/unit.spec.in @@ -123,7 +123,9 @@ DESTDIR=%{buildroot} make unitd-install libunit-install manpage-install %{buildroot}%{_datadir}/doc/unit/ %{__install} -m 644 -p NOTICE \ %{buildroot}%{_datadir}/doc/unit/COPYRIGHT -%{__install} -m 644 -p README \ +%{__install} -m 644 -p README.md \ + %{buildroot}%{_datadir}/doc/unit/ +%{__install} -m 644 -p CONTRIBUTING.md \ %{buildroot}%{_datadir}/doc/unit/ %{__rm} -rf %{buildroot}%{_initrddir}/ diff --git a/src/java/nginx/unit/Context.java b/src/java/nginx/unit/Context.java index 0197858b..e1245e1f 100644 --- a/src/java/nginx/unit/Context.java +++ b/src/java/nginx/unit/Context.java @@ -422,7 +422,7 @@ public class Context implements ServletContext, InitParams processWebXml(root); - loader_ = new AppClassLoader(urls, + loader_ = new UnitClassLoader(urls, Context.class.getClassLoader().getParent()); Class wsSession_class = WsSession.class; @@ -531,7 +531,7 @@ public class Context implements ServletContext, InitParams } } - private static class AppClassLoader extends URLClassLoader + private static class UnitClassLoader extends URLClassLoader { static { ClassLoader.registerAsParallelCapable(); @@ -547,7 +547,7 @@ public class Context implements ServletContext, InitParams private ClassLoader system_loader; - public AppClassLoader(URL[] urls, ClassLoader parent) + public UnitClassLoader(URL[] urls, ClassLoader parent) { super(urls, parent); @@ -1514,6 +1514,18 @@ public class Context implements ServletContext, InitParams { trace("loadInitializer: initializer: " + sci.getClass().getName()); + /* + Unit WebSocket container is a copy of Tomcat WsSci with own + transport implementation. Tomcat implementation will not work in + Unit and should be ignored here. + */ + if (sci.getClass().getName() + .equals("org.apache.tomcat.websocket.server.WsSci")) + { + trace("loadInitializer: ignore"); + return; + } + HandlesTypes ann = sci.getClass().getAnnotation(HandlesTypes.class); if (ann == null) { trace("loadInitializer: no HandlesTypes annotation"); @@ -1558,7 +1570,6 @@ public class Context implements ServletContext, InitParams try { sci.onStartup(handles_classes, this); - metadata_complete_ = true; } catch(Exception e) { System.err.println("loadInitializer: exception caught: " + e.toString()); } diff --git a/src/java/nginx/unit/websocket/WsRemoteEndpointImplBase.java b/src/java/nginx/unit/websocket/WsRemoteEndpointImplBase.java index 776124fd..d451db7d 100644 --- a/src/java/nginx/unit/websocket/WsRemoteEndpointImplBase.java +++ b/src/java/nginx/unit/websocket/WsRemoteEndpointImplBase.java @@ -1175,7 +1175,7 @@ public abstract class WsRemoteEndpointImplBase implements RemoteEndpoint { } else if (state == State.WRITER_WRITING) { // NO-OP. Leave state as is. } else if (state == State.STREAM_WRITING) { - // NO-OP. Leave state as is. + // NO-OP. Leave state as is. } else { // Should never happen // The if ... else ... blocks above should cover all states diff --git a/src/nodejs/unit-http/loader.mjs b/src/nodejs/unit-http/loader.mjs index 067d63d4..546548f5 100644 --- a/src/nodejs/unit-http/loader.mjs +++ b/src/nodejs/unit-http/loader.mjs @@ -4,13 +4,13 @@ export async function resolve(specifier, context, defaultResolver) { case "websocket": return { url: new URL("./websocket.js", import.meta.url).href, - format: "cjs" + format: "commonjs" } case "http": return { url: new URL("./http.js", import.meta.url).href, - format: "cjs" + format: "commonjs" } } diff --git a/src/nxt_application.c b/src/nxt_application.c index 82385ec4..594574b1 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -1052,6 +1052,9 @@ nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init, init->read_port.in_fd = my_port->pair[0]; init->read_port.out_fd = my_port->pair[1]; + init->shared_port_fd = conf->shared_port_fd; + init->shared_queue_fd = conf->shared_queue_fd; + init->log_fd = 2; init->shm_limit = conf->shm_limit; diff --git a/src/nxt_application.h b/src/nxt_application.h index 4612f072..30a1a12f 100644 --- a/src/nxt_application.h +++ b/src/nxt_application.h @@ -103,6 +103,9 @@ struct nxt_common_app_conf_s { size_t shm_limit; uint32_t request_limit; + nxt_fd_t shared_port_fd; + nxt_fd_t shared_queue_fd; + union { nxt_external_app_conf_t external; nxt_python_app_conf_t python; diff --git a/src/nxt_array.h b/src/nxt_array.h index 8318fccd..f06ff14c 100644 --- a/src/nxt_array.h +++ b/src/nxt_array.h @@ -35,18 +35,15 @@ NXT_EXPORT void nxt_array_remove(nxt_array_t *array, void *elt); NXT_EXPORT nxt_array_t *nxt_array_copy(nxt_mp_t *mp, nxt_array_t *dst, nxt_array_t *src); -#define \ -nxt_array_last(array) \ +#define nxt_array_last(array) \ nxt_pointer_to((array)->elts, (array)->size * ((array)->nelts - 1)) -#define \ -nxt_array_reset(array) \ +#define nxt_array_reset(array) \ (array)->nelts = 0; -#define \ -nxt_array_is_empty(array) \ +#define nxt_array_is_empty(array) \ ((array)->nelts == 0) diff --git a/src/nxt_atomic.h b/src/nxt_atomic.h index 9e2e5ec1..cd2e7253 100644 --- a/src/nxt_atomic.h +++ b/src/nxt_atomic.h @@ -26,28 +26,23 @@ typedef volatile nxt_atomic_uint_t nxt_atomic_t; * __sync_lock_release() is a release barrier. */ -#define \ -nxt_atomic_cmp_set(lock, cmp, set) \ +#define nxt_atomic_cmp_set(lock, cmp, set) \ __sync_bool_compare_and_swap(lock, cmp, set) -#define \ -nxt_atomic_xchg(lock, set) \ +#define nxt_atomic_xchg(lock, set) \ __sync_lock_test_and_set(lock, set) -#define \ -nxt_atomic_fetch_add(value, add) \ +#define nxt_atomic_fetch_add(value, add) \ __sync_fetch_and_add(value, add) -#define \ -nxt_atomic_try_lock(lock) \ +#define nxt_atomic_try_lock(lock) \ nxt_atomic_cmp_set(lock, 0, 1) -#define \ -nxt_atomic_release(lock) \ +#define nxt_atomic_release(lock) \ __sync_lock_release(lock) @@ -60,13 +55,11 @@ nxt_atomic_release(lock) \ #if (__i386__ || __i386 || __amd64__ || __amd64) -#define \ -nxt_cpu_pause() \ +#define nxt_cpu_pause() \ __asm__ ("pause") #else -#define \ -nxt_cpu_pause() +#define nxt_cpu_pause() #endif @@ -79,18 +72,15 @@ typedef ulong_t nxt_atomic_uint_t; typedef volatile nxt_atomic_uint_t nxt_atomic_t; -#define \ -nxt_atomic_cmp_set(lock, cmp, set) \ +#define nxt_atomic_cmp_set(lock, cmp, set) \ (atomic_cas_ulong(lock, cmp, set) == (ulong_t) cmp) -#define \ -nxt_atomic_xchg(lock, set) \ +#define nxt_atomic_xchg(lock, set) \ atomic_add_swap(lock, set) -#define \ -nxt_atomic_fetch_add(value, add) \ +#define nxt_atomic_fetch_add(value, add) \ (atomic_add_long_nv(value, add) - add) @@ -124,13 +114,11 @@ nxt_atomic_fetch_add(value, add) \ * barrier. */ -#define \ -nxt_atomic_try_lock(lock) \ +#define nxt_atomic_try_lock(lock) \ nxt_atomic_cmp_set(lock, 0, 1) -#define \ -nxt_atomic_release(lock) \ +#define nxt_atomic_release(lock) \ *lock = 0; @@ -142,13 +130,11 @@ nxt_atomic_release(lock) \ */ #if (__i386__ || __i386 || __amd64__ || __amd64) -#define \ -nxt_cpu_pause() \ +#define nxt_cpu_pause() \ __asm__ ("rep; nop") #else -#define \ -nxt_cpu_pause() +#define nxt_cpu_pause() #endif @@ -192,13 +178,11 @@ nxt_atomic_cmp_set(nxt_atomic_t *lock, nxt_atomic_int_t cmp, } -#define \ -nxt_atomic_xchg(lock, set) \ +#define nxt_atomic_xchg(lock, set) \ __fetch_and_swaplp(lock, set) -#define \ -nxt_atomic_fetch_add(value, add) \ +#define nxt_atomic_fetch_add(value, add) \ __fetch_and_addlp(value, add) @@ -221,13 +205,11 @@ nxt_atomic_cmp_set(nxt_atomic_t *lock, nxt_atomic_int_t cmp, } -#define \ -nxt_atomic_xchg(lock, set) \ +#define nxt_atomic_xchg(lock, set) \ __fetch_and_swap(lock, set) -#define \ -nxt_atomic_fetch_add(value, add) \ +#define nxt_atomic_fetch_add(value, add) \ __fetch_and_add(value, add) @@ -270,13 +252,11 @@ nxt_atomic_try_lock(nxt_atomic_t *lock) } -#define \ -nxt_atomic_release(lock) \ +#define nxt_atomic_release(lock) \ do { __lwsync(); *lock = 0; } while (0) -#define \ -nxt_cpu_pause() +#define nxt_cpu_pause() #endif /* NXT_HAVE_XLC_ATOMIC */ diff --git a/src/nxt_buf.h b/src/nxt_buf.h index 5121d659..f1e2879f 100644 --- a/src/nxt_buf.h +++ b/src/nxt_buf.h @@ -113,127 +113,100 @@ struct nxt_buf_s { #define NXT_BUF_SYNC_LAST 4 -#define \ -nxt_buf_is_mem(b) \ +#define nxt_buf_is_mem(b) \ ((b)->mem.pos != NULL) -#define \ -nxt_buf_is_file(b) \ +#define nxt_buf_is_file(b) \ ((b)->is_file) -#define \ -nxt_buf_set_file(b) \ +#define nxt_buf_set_file(b) \ (b)->is_file = 1 -#define \ -nxt_buf_clear_file(b) \ +#define nxt_buf_clear_file(b) \ (b)->is_file = 0 -#define \ -nxt_buf_is_mmap(b) \ +#define nxt_buf_is_mmap(b) \ ((b)->is_mmap) -#define \ -nxt_buf_set_mmap(b) \ +#define nxt_buf_set_mmap(b) \ (b)->is_mmap = 1 -#define \ -nxt_buf_clear_mmap(b) \ +#define nxt_buf_clear_mmap(b) \ (b)->is_mmap = 0 -#define \ -nxt_buf_is_port_mmap(b) \ +#define nxt_buf_is_port_mmap(b) \ ((b)->is_port_mmap) -#define \ -nxt_buf_set_port_mmap(b) \ +#define nxt_buf_set_port_mmap(b) \ (b)->is_port_mmap = 1 -#define \ -nxt_buf_clear_port_mmap(b) \ +#define nxt_buf_clear_port_mmap(b) \ (b)->is_port_mmap = 0 -#define \ -nxt_buf_is_sync(b) \ +#define nxt_buf_is_sync(b) \ ((b)->is_sync) -#define \ -nxt_buf_set_sync(b) \ +#define nxt_buf_set_sync(b) \ (b)->is_sync = 1 -#define \ -nxt_buf_clear_sync(b) \ +#define nxt_buf_clear_sync(b) \ (b)->is_sync = 0 -#define \ -nxt_buf_is_nobuf(b) \ +#define nxt_buf_is_nobuf(b) \ ((b)->is_nobuf) -#define \ -nxt_buf_set_nobuf(b) \ +#define nxt_buf_set_nobuf(b) \ (b)->is_nobuf = 1 -#define \ -nxt_buf_clear_nobuf(b) \ +#define nxt_buf_clear_nobuf(b) \ (b)->is_nobuf = 0 -#define \ -nxt_buf_is_flush(b) \ +#define nxt_buf_is_flush(b) \ ((b)->is_flush) -#define \ -nxt_buf_set_flush(b) \ +#define nxt_buf_set_flush(b) \ (b)->is_flush = 1 -#define \ -nxt_buf_clear_flush(b) \ +#define nxt_buf_clear_flush(b) \ (b)->is_flush = 0 -#define \ -nxt_buf_is_last(b) \ +#define nxt_buf_is_last(b) \ ((b)->is_last) -#define \ -nxt_buf_set_last(b) \ +#define nxt_buf_set_last(b) \ (b)->is_last = 1 -#define \ -nxt_buf_clear_last(b) \ +#define nxt_buf_clear_last(b) \ (b)->is_last = 0 -#define \ -nxt_buf_mem_set_size(bm, size) \ +#define nxt_buf_mem_set_size(bm, size) \ do { \ (bm)->start = 0; \ (bm)->end = (void *) size; \ } while (0) -#define \ -nxt_buf_mem_size(bm) \ +#define nxt_buf_mem_size(bm) \ ((bm)->end - (bm)->start) -#define \ -nxt_buf_mem_used_size(bm) \ +#define nxt_buf_mem_used_size(bm) \ ((bm)->free - (bm)->pos) -#define \ -nxt_buf_mem_free_size(bm) \ +#define nxt_buf_mem_free_size(bm) \ ((bm)->end - (bm)->free) -#define \ -nxt_buf_used_size(b) \ +#define nxt_buf_used_size(b) \ (nxt_buf_is_file(b) ? (b)->file_end - (b)->file_pos: \ nxt_buf_mem_used_size(&(b)->mem)) @@ -264,8 +237,7 @@ nxt_buf_chk_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) return src; } -#define \ -nxt_buf_free(mp, b) \ +#define nxt_buf_free(mp, b) \ nxt_mp_free((mp), (b)) diff --git a/src/nxt_buf_pool.h b/src/nxt_buf_pool.h index 6a04fd7e..3d22d7fa 100644 --- a/src/nxt_buf_pool.h +++ b/src/nxt_buf_pool.h @@ -42,8 +42,7 @@ NXT_EXPORT void nxt_buf_pool_destroy(nxt_buf_pool_t *bp); /* There is ready free buffer. */ -#define \ -nxt_buf_pool_ready(bp) \ +#define nxt_buf_pool_ready(bp) \ ((bp)->free != NULL \ || ((bp)->current != NULL \ && (bp)->current->mem.free < (bp)->current->mem.end)) @@ -51,29 +50,25 @@ nxt_buf_pool_ready(bp) \ /* A free buffer is allowed to be allocated. */ -#define \ -nxt_buf_pool_obtainable(bp) \ +#define nxt_buf_pool_obtainable(bp) \ ((bp)->num < (bp)->max) /* There is ready free buffer or it is allowed to be allocated. */ -#define \ -nxt_buf_pool_available(bp) \ +#define nxt_buf_pool_available(bp) \ (nxt_buf_pool_obtainable(bp) || nxt_buf_pool_ready(bp)) /* Reserve allocation of "n" free buffers as they were allocated. */ -#define \ -nxt_buf_pool_reserve(bp, n) \ +#define nxt_buf_pool_reserve(bp, n) \ (bp)->num += (n) /* Release a reservation. */ -#define \ -nxt_buf_pool_release(bp, n) \ +#define nxt_buf_pool_release(bp, n) \ (bp)->num -= (n) diff --git a/src/nxt_cache.c b/src/nxt_cache.c index 409ba301..e81d63dc 100644 --- a/src/nxt_cache.c +++ b/src/nxt_cache.c @@ -8,8 +8,7 @@ /* A cache time resolution is 10ms. */ -#define \ -nxt_cache_time(thr) \ +#define nxt_cache_time(thr) \ (uint64_t) (nxt_thread_time(thr) * 100) diff --git a/src/nxt_cert.c b/src/nxt_cert.c index 01d413e0..4a1f1496 100644 --- a/src/nxt_cert.c +++ b/src/nxt_cert.c @@ -241,7 +241,6 @@ nxt_cert_bio(nxt_task_t *task, BIO *bio) goto fail; } - nxt_free(cert); cert = new_cert; } diff --git a/src/nxt_clang.h b/src/nxt_clang.h index a10de08a..94638346 100644 --- a/src/nxt_clang.h +++ b/src/nxt_clang.h @@ -16,45 +16,37 @@ #if (NXT_CLANG) /* Any __asm__ directive disables loop vectorization in GCC and Clang. */ -#define \ -nxt_pragma_loop_disable_vectorization \ +#define nxt_pragma_loop_disable_vectorization \ __asm__("") #else -#define \ -nxt_pragma_loop_disable_vectorization +#define nxt_pragma_loop_disable_vectorization #endif #if (NXT_HAVE_BUILTIN_EXPECT) -#define \ -nxt_expect(c, x) \ +#define nxt_expect(c, x) \ __builtin_expect((long) (x), (c)) -#define \ -nxt_fast_path(x) \ +#define nxt_fast_path(x) \ nxt_expect(1, x) -#define \ -nxt_slow_path(x) \ +#define nxt_slow_path(x) \ nxt_expect(0, x) #else -#define \ -nxt_expect(c, x) \ +#define nxt_expect(c, x) \ (x) -#define \ -nxt_fast_path(x) \ +#define nxt_fast_path(x) \ (x) -#define \ -nxt_slow_path(x) \ +#define nxt_slow_path(x) \ (x) #endif @@ -62,28 +54,24 @@ nxt_slow_path(x) \ #if (NXT_HAVE_BUILTIN_UNREACHABLE) -#define \ -nxt_unreachable() \ +#define nxt_unreachable() \ __builtin_unreachable() #else -#define \ -nxt_unreachable() +#define nxt_unreachable() #endif #if (NXT_HAVE_BUILTIN_PREFETCH) -#define \ -nxt_prefetch(a) \ +#define nxt_prefetch(a) \ __builtin_prefetch(a) #else -#define \ -nxt_prefetch(a) +#define nxt_prefetch(a) #endif @@ -132,6 +120,17 @@ nxt_prefetch(a) #endif +#if (NXT_HAVE_GCC_ATTRIBUTE_UNUSED) + +#define NXT_MAYBE_UNUSED __attribute__((__unused__)) + +#else + +#define NXT_MAYBE_UNUSED + +#endif + + #if (NXT_HAVE_BUILTIN_POPCOUNT) #define nxt_popcount __builtin_popcount @@ -195,13 +194,11 @@ nxt_popcount(unsigned int x) #endif -#define \ -nxt_alloca(size) \ +#define nxt_alloca(size) \ alloca(size) -#define \ -nxt_container_of(p, type, field) \ +#define nxt_container_of(p, type, field) \ (type *) ((u_char *) (p) - offsetof(type, field)) @@ -213,30 +210,25 @@ nxt_container_of(p, type, field) \ *(type *) ((u_char *) p + offset) -#define \ -nxt_nitems(x) \ +#define nxt_nitems(x) \ (sizeof(x) / sizeof((x)[0])) /* GCC and Clang use __builtin_abs() instead of libc abs(). */ -#define \ -nxt_abs(val) \ +#define nxt_abs(val) \ abs(val) -#define \ -nxt_max(val1, val2) \ +#define nxt_max(val1, val2) \ ((val1 < val2) ? (val2) : (val1)) -#define \ -nxt_min(val1, val2) \ +#define nxt_min(val1, val2) \ ((val1 > val2) ? (val2) : (val1)) -#define \ -nxt_bswap32(val) \ +#define nxt_bswap32(val) \ ( ((val) >> 24) \ | (((val) & 0x00FF0000) >> 8) \ | (((val) & 0x0000FF00) << 8) \ @@ -247,18 +239,15 @@ nxt_bswap32(val) \ ((((value) - 1) & (value)) == 0) -#define \ -nxt_align_size(d, a) \ +#define nxt_align_size(d, a) \ (((d) + ((size_t) (a) - 1)) & ~((size_t) (a) - 1)) -#define \ -nxt_align_ptr(p, a) \ +#define nxt_align_ptr(p, a) \ (u_char *) (((uintptr_t) (p) + ((uintptr_t) (a) - 1)) \ & ~((uintptr_t) (a) - 1)) -#define \ -nxt_trunc_ptr(p, a) \ +#define nxt_trunc_ptr(p, a) \ (u_char *) ((uintptr_t) (p) & ~((uintptr_t) (a) - 1)) diff --git a/src/nxt_clone.c b/src/nxt_clone.c index 9ee3c012..aa952a54 100644 --- a/src/nxt_clone.c +++ b/src/nxt_clone.c @@ -384,7 +384,7 @@ nxt_clone_vldt_credential_gidmap(nxt_task_t *task, } return NXT_OK; - } + } base_ok = 0; gids_ok = 0; diff --git a/src/nxt_conf.c b/src/nxt_conf.c index 1aca0a7e..79e776a0 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -192,7 +192,8 @@ nxt_conf_set_string(nxt_conf_value_t *value, nxt_str_t *str) nxt_int_t -nxt_conf_set_string_dup(nxt_conf_value_t *value, nxt_mp_t *mp, nxt_str_t *str) +nxt_conf_set_string_dup(nxt_conf_value_t *value, nxt_mp_t *mp, + const nxt_str_t *str) { nxt_str_t tmp, *ptr; @@ -392,6 +393,13 @@ nxt_conf_array_elements_count(nxt_conf_value_t *value) nxt_uint_t +nxt_conf_array_elements_count_or_1(nxt_conf_value_t *value) +{ + return (value->type == NXT_CONF_VALUE_ARRAY) ? value->u.array->count : 1; +} + + +nxt_uint_t nxt_conf_type(nxt_conf_value_t *value) { switch (value->type) { @@ -749,6 +757,25 @@ nxt_conf_get_array_element(nxt_conf_value_t *value, uint32_t index) } +nxt_conf_value_t * +nxt_conf_get_array_element_or_itself(nxt_conf_value_t *value, uint32_t index) +{ + nxt_conf_array_t *array; + + if (value->type != NXT_CONF_VALUE_ARRAY) { + return (index == 0) ? value : NULL; + } + + array = value->u.array; + + if (index >= array->count) { + return NULL; + } + + return &array->elements[index]; +} + + void nxt_conf_array_qsort(nxt_conf_value_t *value, int (*compare)(const void *, const void *)) diff --git a/src/nxt_conf.h b/src/nxt_conf.h index 8b3565fd..cfbc5991 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -87,6 +87,8 @@ NXT_EXPORT nxt_conf_value_t *nxt_conf_next_object_member( nxt_conf_value_t *value, nxt_str_t *name, uint32_t *next); NXT_EXPORT nxt_conf_value_t *nxt_conf_get_array_element(nxt_conf_value_t *value, uint32_t index); +NXT_EXPORT nxt_conf_value_t *nxt_conf_get_array_element_or_itself( + nxt_conf_value_t *value, uint32_t index); NXT_EXPORT nxt_int_t nxt_conf_map_object(nxt_mp_t *mp, nxt_conf_value_t *value, nxt_conf_map_t *map, nxt_uint_t n, void *data); @@ -115,7 +117,7 @@ nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt); NXT_EXPORT void nxt_conf_get_string(nxt_conf_value_t *value, nxt_str_t *str); NXT_EXPORT void nxt_conf_set_string(nxt_conf_value_t *value, nxt_str_t *str); NXT_EXPORT nxt_int_t nxt_conf_set_string_dup(nxt_conf_value_t *value, - nxt_mp_t *mp, nxt_str_t *str); + nxt_mp_t *mp, const nxt_str_t *str); NXT_EXPORT double nxt_conf_get_number(nxt_conf_value_t *value); NXT_EXPORT uint8_t nxt_conf_get_boolean(nxt_conf_value_t *value); @@ -139,6 +141,8 @@ void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp, nxt_uint_t index, nxt_str_t *value); NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count(nxt_conf_value_t *value); +NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count_or_1( + nxt_conf_value_t *value); void nxt_conf_array_qsort(nxt_conf_value_t *value, int (*compare)(const void *, const void *)); diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 3f068bbb..ee7ebe44 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -77,7 +77,8 @@ static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt, static nxt_int_t nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_str_t *value); nxt_inline nxt_int_t nxt_conf_vldt_unsupported(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data) + NXT_MAYBE_UNUSED; static nxt_int_t nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); @@ -114,7 +115,7 @@ static nxt_int_t nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, static nxt_int_t nxt_conf_vldt_return(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_share(nxt_conf_validation_t *vldt, - nxt_conf_value_t *value, void *data); + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, @@ -194,7 +195,7 @@ static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, - nxt_str_t *name, nxt_conf_value_t *value); + nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, @@ -634,6 +635,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = { }, { .name = nxt_string("location"), .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_VAR, }, NXT_CONF_VLDT_END @@ -646,6 +648,9 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, .validator = nxt_conf_vldt_share, }, { + .name = nxt_string("index"), + .type = NXT_CONF_VLDT_STRING, + }, { .name = nxt_string("types"), .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, .validator = nxt_conf_vldt_match_patterns, @@ -2448,7 +2453,7 @@ nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, break; } - } + } ret = nxt_conf_vldt_type(vldt, &name, member, vals->type); if (ret != NXT_OK) { diff --git a/src/nxt_djb_hash.h b/src/nxt_djb_hash.h index c7ba6fdb..43395e6a 100644 --- a/src/nxt_djb_hash.h +++ b/src/nxt_djb_hash.h @@ -18,8 +18,7 @@ NXT_EXPORT uint32_t nxt_djb_hash_lowcase(const void *data, size_t len); #define NXT_DJB_HASH_INIT 5381 -#define \ -nxt_djb_hash_add(hash, val) \ +#define nxt_djb_hash_add(hash, val) \ ((uint32_t) ((((hash) << 5) + (hash)) ^ (uint32_t) (val))) diff --git a/src/nxt_dyld.h b/src/nxt_dyld.h index a0cbeda3..65ce1874 100644 --- a/src/nxt_dyld.h +++ b/src/nxt_dyld.h @@ -17,8 +17,7 @@ typedef struct { #define NXT_DYLD_ANY RTLD_DEFAULT -#define \ -nxt_dyld_is_valid(dyld) \ +#define nxt_dyld_is_valid(dyld) \ ((dyld)->handle != NULL) diff --git a/src/nxt_errno.h b/src/nxt_errno.h index ec700537..f19d50ba 100644 --- a/src/nxt_errno.h +++ b/src/nxt_errno.h @@ -65,20 +65,16 @@ typedef int nxt_err_t; #define NXT_DONE (-4) -#define \ -nxt_errno \ +#define nxt_errno \ errno -#define \ -nxt_socket_errno \ +#define nxt_socket_errno \ errno -#define \ -nxt_set_errno(err) \ +#define nxt_set_errno(err) \ errno = err -#define \ -nxt_set_socket_errno(err) \ +#define nxt_set_socket_errno(err) \ errno = err diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 6b05d510..91cfc0aa 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -351,43 +351,35 @@ void nxt_fd_event_hash_delete(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, void nxt_fd_event_hash_destroy(nxt_lvlhsh_t *lvlhsh); -#define \ -nxt_fd_event_disable(engine, ev) \ +#define nxt_fd_event_disable(engine, ev) \ (engine)->event.disable(engine, ev) -#define \ -nxt_fd_event_delete(engine, ev) \ +#define nxt_fd_event_delete(engine, ev) \ (engine)->event.delete(engine, ev) -#define \ -nxt_fd_event_close(engine, ev) \ +#define nxt_fd_event_close(engine, ev) \ (engine)->event.close(engine, ev) -#define \ -nxt_fd_event_enable_read(engine, ev) \ +#define nxt_fd_event_enable_read(engine, ev) \ (engine)->event.enable_read(engine, ev) -#define \ -nxt_fd_event_enable_write(engine, ev) \ +#define nxt_fd_event_enable_write(engine, ev) \ (engine)->event.enable_write(engine, ev) -#define \ -nxt_fd_event_disable_read(engine, ev) \ +#define nxt_fd_event_disable_read(engine, ev) \ (engine)->event.disable_read(engine, ev) -#define \ -nxt_fd_event_disable_write(engine, ev) \ +#define nxt_fd_event_disable_write(engine, ev) \ (engine)->event.disable_write(engine, ev) -#define \ -nxt_fd_event_block_read(engine, ev) \ +#define nxt_fd_event_block_read(engine, ev) \ do { \ if (nxt_fd_event_is_active((ev)->read)) { \ (engine)->event.block_read(engine, ev); \ @@ -395,8 +387,7 @@ nxt_fd_event_block_read(engine, ev) \ } while (0) -#define \ -nxt_fd_event_block_write(engine, ev) \ +#define nxt_fd_event_block_write(engine, ev) \ do { \ if (nxt_fd_event_is_active((ev)->write)) { \ (engine)->event.block_write(engine, ev); \ @@ -404,18 +395,15 @@ nxt_fd_event_block_write(engine, ev) \ } while (0) -#define \ -nxt_fd_event_oneshot_read(engine, ev) \ +#define nxt_fd_event_oneshot_read(engine, ev) \ (engine)->event.oneshot_read(engine, ev) -#define \ -nxt_fd_event_oneshot_write(engine, ev) \ +#define nxt_fd_event_oneshot_write(engine, ev) \ (engine)->event.oneshot_write(engine, ev) -#define \ -nxt_fd_event_enable_accept(engine, ev) \ +#define nxt_fd_event_enable_accept(engine, ev) \ (engine)->event.enable_accept(engine, ev) diff --git a/src/nxt_external.c b/src/nxt_external.c index b41ca51b..c724b9bd 100644 --- a/src/nxt_external.c +++ b/src/nxt_external.c @@ -106,6 +106,16 @@ nxt_external_start(nxt_task_t *task, nxt_process_data_t *data) return NXT_ERROR; } + rc = nxt_external_fd_no_cloexec(task, conf->shared_port_fd); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } + + rc = nxt_external_fd_no_cloexec(task, conf->shared_queue_fd); + if (nxt_slow_path(rc != NXT_OK)) { + return NXT_ERROR; + } + end = buf + sizeof(buf); p = nxt_sprintf(buf, end, @@ -113,12 +123,14 @@ nxt_external_start(nxt_task_t *task, nxt_process_data_t *data) "%PI,%ud,%d;" "%PI,%ud,%d;" "%PI,%ud,%d,%d;" + "%d,%d;" "%d,%z,%uD,%Z", NXT_VERSION, my_port->process->stream, proto_port->pid, proto_port->id, proto_port->pair[1], router_port->pid, router_port->id, router_port->pair[1], my_port->pid, my_port->id, my_port->pair[0], my_port->pair[1], + conf->shared_port_fd, conf->shared_queue_fd, 2, conf->shm_limit, conf->request_limit); if (nxt_slow_path(p == end)) { diff --git a/src/nxt_fastcgi_source.c b/src/nxt_fastcgi_source.c index b1be3303..b2424292 100644 --- a/src/nxt_fastcgi_source.c +++ b/src/nxt_fastcgi_source.c @@ -18,8 +18,7 @@ typedef struct { } nxt_fastcgi_param_t; -#define \ -nxt_fastcgi_set_record_length(p, length) \ +#define nxt_fastcgi_set_record_length(p, length) \ do { \ uint32_t len = length; \ \ diff --git a/src/nxt_fd_event.h b/src/nxt_fd_event.h index 762fdf25..3a8d9460 100644 --- a/src/nxt_fd_event.h +++ b/src/nxt_fd_event.h @@ -44,13 +44,11 @@ typedef enum { } nxt_fd_event_state_t; -#define \ -nxt_fd_event_is_disabled(state) \ +#define nxt_fd_event_is_disabled(state) \ ((state) < NXT_EVENT_ONESHOT) -#define \ -nxt_fd_event_is_active(state) \ +#define nxt_fd_event_is_active(state) \ ((state) >= NXT_EVENT_ONESHOT) diff --git a/src/nxt_fiber.c b/src/nxt_fiber.c index 2312c855..d6cac893 100644 --- a/src/nxt_fiber.c +++ b/src/nxt_fiber.c @@ -14,8 +14,7 @@ static void nxt_fiber_switch(nxt_task_t *task, nxt_fiber_t *fib); static void nxt_fiber_timer_handler(nxt_task_t *task, void *obj, void *data); -#define \ -nxt_fiber_enqueue(thr, task, fib) \ +#define nxt_fiber_enqueue(thr, task, fib) \ nxt_work_queue_add(&(thr)->engine->fast_work_queue, \ nxt_fiber_switch_handler, task, fib, NULL) diff --git a/src/nxt_file.h b/src/nxt_file.h index 4846305b..07c7a22b 100644 --- a/src/nxt_file.h +++ b/src/nxt_file.h @@ -27,23 +27,19 @@ typedef struct { } nxt_file_name_str_t; -#define \ -nxt_file_name_str_set(file_name, mem_pool, name) \ +#define nxt_file_name_str_set(file_name, mem_pool, name) \ ((file_name) = (nxt_file_name_t *) (name), NXT_OK) -#define \ -nxt_file_name_alloc(mem_pool, len) \ +#define nxt_file_name_alloc(mem_pool, len) \ nxt_mp_nget(mem_pool, len) -#define \ -nxt_file_name_copy(dst, src, len) \ +#define nxt_file_name_copy(dst, src, len) \ nxt_cpymem(dst, src, len) -#define \ -nxt_file_name_add(dst, src, len) \ +#define nxt_file_name_add(dst, src, len) \ nxt_cpymem(dst, src, len) @@ -51,21 +47,18 @@ nxt_file_name_add(dst, src, len) \ /* MacOSX, Cygwin. */ -#define \ -nxt_file_name_eq(fn1, fn2) \ +#define nxt_file_name_eq(fn1, fn2) \ (nxt_strcasecmp(fn1, fn2) == 0) #else -#define \ -nxt_file_name_eq(fn1, fn2) \ +#define nxt_file_name_eq(fn1, fn2) \ (nxt_strcmp(fn1, fn2) == 0) #endif -#define \ -nxt_file_name_is_absolute(name) \ +#define nxt_file_name_is_absolute(name) \ (name[0] == '/') @@ -168,20 +161,16 @@ NXT_EXPORT void nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, NXT_EXPORT nxt_int_t nxt_file_info(nxt_file_t *file, nxt_file_info_t *fi); -#define \ -nxt_is_dir(fi) \ +#define nxt_is_dir(fi) \ (S_ISDIR((fi)->st_mode)) -#define \ -nxt_is_file(fi) \ +#define nxt_is_file(fi) \ (S_ISREG((fi)->st_mode)) -#define \ -nxt_file_size(fi) \ +#define nxt_file_size(fi) \ (fi)->st_size -#define \ -nxt_file_mtime(fi) \ +#define nxt_file_mtime(fi) \ (fi)->st_mtime @@ -206,12 +195,10 @@ NXT_EXPORT nxt_int_t nxt_stderr_start(void); #define nxt_stderr STDERR_FILENO -#define \ -nxt_write_console(fd, buf, size) \ +#define nxt_write_console(fd, buf, size) \ write(fd, buf, size) -#define \ -nxt_write_syslog(priority, message) \ +#define nxt_write_syslog(priority, message) \ syslog(priority, "%s", message) diff --git a/src/nxt_gnutls.c b/src/nxt_gnutls.c index 4618dce9..aab4699c 100644 --- a/src/nxt_gnutls.c +++ b/src/nxt_gnutls.c @@ -708,11 +708,11 @@ nxt_gnutls_log_error_level(nxt_event_conn_t *c, ssize_t err) case GNUTLS_E_UNKNOWN_CIPHER_SUITE: /* -21 */ - /* Disable gnutls_bye(), because it returns GNUTLS_E_INTERNAL_ERROR. */ + /* Disable gnutls_bye(), because it returns GNUTLS_E_INTERNAL_ERROR. */ ssltls = c->u.ssltls; ssltls->no_shutdown = 1; - /* Fall through. */ + /* Fall through. */ case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: /* -9 */ c->socket.error = 1000; /* Nonexistent errno code. */ diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index b683cb22..d3340774 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -1881,11 +1881,11 @@ nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data) #define NXT_H1P_IDLE_TIMEOUT \ - "HTTP/1.1 408 Request Timeout\r\n" \ - "Server: " NXT_SERVER "\r\n" \ - "Connection: close\r\n" \ - "Content-Length: 0\r\n" \ - "Date: " + "HTTP/1.1 408 Request Timeout\r\n" \ + "Server: " NXT_SERVER "\r\n" \ + "Connection: close\r\n" \ + "Content-Length: 0\r\n" \ + "Date: " static void diff --git a/src/nxt_http.h b/src/nxt_http.h index 02d66f58..d299fdd4 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -90,17 +90,17 @@ typedef union { #define nxt_http_field_name_set(_field, _name) \ do { \ - (_field)->name_length = nxt_length(_name); \ - (_field)->name = (u_char *) _name; \ + (_field)->name_length = nxt_length(_name); \ + (_field)->name = (u_char *) _name; \ } while (0) #define nxt_http_field_set(_field, _name, _value) \ do { \ - (_field)->name_length = nxt_length(_name); \ - (_field)->value_length = nxt_length(_value); \ - (_field)->name = (u_char *) _name; \ - (_field)->value = (u_char *) _value; \ + (_field)->name_length = nxt_length(_name); \ + (_field)->value_length = nxt_length(_value); \ + (_field)->name = (u_char *) _name; \ + (_field)->value = (u_char *) _value; \ } while (0) @@ -198,6 +198,15 @@ struct nxt_http_request_s { }; +typedef struct { + uint16_t hash; + uint16_t name_length; + uint32_t value_length; + u_char *name; + u_char *value; +} nxt_http_name_value_t; + + typedef struct nxt_http_route_s nxt_http_route_t; typedef struct nxt_http_route_rule_s nxt_http_route_rule_t; typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t; @@ -206,9 +215,10 @@ typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t; typedef struct { nxt_conf_value_t *pass; nxt_conf_value_t *ret; - nxt_str_t location; + nxt_conf_value_t *location; nxt_conf_value_t *proxy; nxt_conf_value_t *share; + nxt_conf_value_t *index; nxt_str_t chroot; nxt_conf_value_t *follow_symlinks; nxt_conf_value_t *traverse_mounts; @@ -238,7 +248,7 @@ typedef struct { void (*body_read)(nxt_task_t *task, nxt_http_request_t *r); void (*local_addr)(nxt_task_t *task, nxt_http_request_t *r); void (*header_send)(nxt_task_t *task, nxt_http_request_t *r, - nxt_work_handler_t body_handler, void *data); + nxt_work_handler_t body_handler, void *data); void (*send)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out); nxt_off_t (*body_bytes_sent)(nxt_task_t *task, nxt_http_proto_t proto); void (*discard)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *last); @@ -311,6 +321,9 @@ nxt_int_t nxt_http_request_field(void *ctx, nxt_http_field_t *field, nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, uintptr_t data); +nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r); +nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r); + nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf); nxt_http_action_t *nxt_http_action_create(nxt_task_t *task, diff --git a/src/nxt_http_chunk_parse.c b/src/nxt_http_chunk_parse.c index deab116d..b60bc801 100644 --- a/src/nxt_http_chunk_parse.c +++ b/src/nxt_http_chunk_parse.c @@ -12,8 +12,7 @@ #define NXT_HTTP_CHUNK_END 2 -#define \ -nxt_size_is_sufficient(cs) \ +#define nxt_size_is_sufficient(cs) \ (cs < ((__typeof__(cs)) 1 << (sizeof(cs) * 8 - 4))) diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 338b0a90..1ab6cc90 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -827,8 +827,7 @@ nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos, } -#define \ -nxt_http_is_normal(c) \ +#define nxt_http_is_normal(c) \ (nxt_fast_path((nxt_http_normal[c / 8] & (1 << (c & 7))) != 0)) diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index ac614df6..04a6f7f3 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -24,6 +24,25 @@ static void nxt_http_request_done(nxt_task_t *task, void *obj, void *data); static u_char *nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now, struct tm *tm, size_t size, const char *format); +static nxt_http_name_value_t *nxt_http_argument(nxt_array_t *array, + u_char *name, size_t name_length, uint32_t hash, u_char *start, + u_char *end); +static nxt_int_t nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, + u_char *end); +static nxt_http_name_value_t *nxt_http_cookie(nxt_array_t *array, u_char *name, + size_t name_length, u_char *start, u_char *end); + + +#define NXT_HTTP_COOKIE_HASH \ + (nxt_http_field_hash_end( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char( \ + nxt_http_field_hash_char(NXT_HTTP_FIELD_HASH_INIT, \ + 'c'), 'o'), 'o'), 'k'), 'i'), 'e')) & 0xFFFF) + static const nxt_http_request_state_t nxt_http_request_init_state; static const nxt_http_request_state_t nxt_http_request_body_state; @@ -748,3 +767,260 @@ nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now, struct tm *tm, { return nxt_http_date(buf, tm); } + + +nxt_array_t * +nxt_http_arguments_parse(nxt_http_request_t *r) +{ + size_t name_length; + u_char *p, *dst, *dst_start, *start, *end, *name; + uint8_t d0, d1; + uint32_t hash; + nxt_array_t *args; + nxt_http_name_value_t *nv; + + if (r->arguments != NULL) { + return r->arguments; + } + + args = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); + if (nxt_slow_path(args == NULL)) { + return NULL; + } + + hash = NXT_HTTP_FIELD_HASH_INIT; + name = NULL; + name_length = 0; + + dst_start = nxt_mp_nget(r->mem_pool, r->args->length); + if (nxt_slow_path(dst_start == NULL)) { + return NULL; + } + + r->args_decoded.start = dst_start; + + start = r->args->start; + end = start + r->args->length; + + for (p = start, dst = dst_start; p < end; p++, dst++) { + *dst = *p; + + switch (*p) { + case '=': + if (name == NULL) { + name_length = dst - dst_start; + name = dst_start; + dst_start = dst + 1; + } + + continue; + + case '&': + if (name_length != 0 || dst != dst_start) { + nv = nxt_http_argument(args, name, name_length, hash, dst_start, + dst); + if (nxt_slow_path(nv == NULL)) { + return NULL; + } + } + + hash = NXT_HTTP_FIELD_HASH_INIT; + name_length = 0; + name = NULL; + dst_start = dst + 1; + + continue; + + case '+': + *dst = ' '; + + break; + + case '%': + if (nxt_slow_path(end - p <= 2)) { + break; + } + + d0 = nxt_hex2int[p[1]]; + d1 = nxt_hex2int[p[2]]; + + if (nxt_slow_path((d0 | d1) >= 16)) { + break; + } + + p += 2; + *dst = (d0 << 4) + d1; + + break; + } + + if (name == NULL) { + hash = nxt_http_field_hash_char(hash, *dst); + } + } + + r->args_decoded.length = dst - r->args_decoded.start; + + if (name_length != 0 || dst != dst_start) { + nv = nxt_http_argument(args, name, name_length, hash, dst_start, dst); + if (nxt_slow_path(nv == NULL)) { + return NULL; + } + } + + r->arguments = args; + + return args; +} + + +static nxt_http_name_value_t * +nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length, + uint32_t hash, u_char *start, u_char *end) +{ + size_t length; + nxt_http_name_value_t *nv; + + nv = nxt_array_add(array); + if (nxt_slow_path(nv == NULL)) { + return NULL; + } + + nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; + + length = end - start; + + if (name == NULL) { + name_length = length; + name = start; + length = 0; + } + + nv->name_length = name_length; + nv->value_length = length; + nv->name = name; + nv->value = start; + + return nv; +} + + +nxt_array_t * +nxt_http_cookies_parse(nxt_http_request_t *r) +{ + nxt_int_t ret; + nxt_array_t *cookies; + nxt_http_field_t *f; + + if (r->cookies != NULL) { + return r->cookies; + } + + cookies = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); + if (nxt_slow_path(cookies == NULL)) { + return NULL; + } + + nxt_list_each(f, r->fields) { + + if (f->hash != NXT_HTTP_COOKIE_HASH + || f->name_length != 6 + || nxt_strncasecmp(f->name, (u_char *) "Cookie", 6) != 0) + { + continue; + } + + ret = nxt_http_cookie_parse(cookies, f->value, + f->value + f->value_length); + if (ret != NXT_OK) { + return NULL; + } + + } nxt_list_loop; + + r->cookies = cookies; + + return cookies; +} + + +static nxt_int_t +nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) +{ + size_t name_length; + u_char c, *p, *name; + nxt_http_name_value_t *nv; + + name = NULL; + name_length = 0; + + for (p = start; p < end; p++) { + c = *p; + + if (c == '=') { + while (start[0] == ' ') { start++; } + + name_length = p - start; + + if (name_length != 0) { + name = start; + } + + start = p + 1; + + } else if (c == ';') { + if (name != NULL) { + nv = nxt_http_cookie(cookies, name, name_length, start, p); + if (nxt_slow_path(nv == NULL)) { + return NXT_ERROR; + } + } + + name = NULL; + start = p + 1; + } + } + + if (name != NULL) { + nv = nxt_http_cookie(cookies, name, name_length, start, p); + if (nxt_slow_path(nv == NULL)) { + return NXT_ERROR; + } + } + + return NXT_OK; +} + + +static nxt_http_name_value_t * +nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length, + u_char *start, u_char *end) +{ + u_char c, *p; + uint32_t hash; + nxt_http_name_value_t *nv; + + nv = nxt_array_add(array); + if (nxt_slow_path(nv == NULL)) { + return NULL; + } + + nv->name_length = name_length; + nv->name = name; + + hash = NXT_HTTP_FIELD_HASH_INIT; + + for (p = name; p < name + name_length; p++) { + c = *p; + hash = nxt_http_field_hash_char(hash, c); + } + + nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; + + while (start < end && end[-1] == ' ') { end--; } + + nv->value_length = end - start; + nv->value = start; + + return nv; +} diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c index 18fd490d..82c91568 100644 --- a/src/nxt_http_return.c +++ b/src/nxt_http_return.c @@ -8,13 +8,24 @@ typedef struct { - nxt_http_status_t status; - nxt_str_t location; + nxt_http_status_t status; + nxt_var_t *location; + nxt_str_t encoded; } nxt_http_return_conf_t; +typedef struct { + nxt_str_t location; + nxt_str_t encoded; +} nxt_http_return_ctx_t; + + static nxt_http_action_t *nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action); +static nxt_int_t nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, + const nxt_str_t *location); +static void nxt_http_return_send_ready(nxt_task_t *task, void *obj, void *data); +static void nxt_http_return_var_error(nxt_task_t *task, void *obj, void *data); static const nxt_http_request_state_t nxt_http_return_send_state; @@ -24,8 +35,7 @@ nxt_int_t nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, nxt_http_action_conf_t *acf) { - nxt_str_t *loc; - nxt_uint_t encode; + nxt_str_t str; nxt_http_return_conf_t *conf; conf = nxt_mp_zget(mp, sizeof(nxt_http_return_conf_t)); @@ -38,30 +48,20 @@ nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, conf->status = nxt_conf_get_number(acf->ret); - if (acf->location.length > 0) { - if (nxt_is_complex_uri_encoded(acf->location.start, - acf->location.length)) - { - loc = nxt_str_dup(mp, &conf->location, &acf->location); - if (nxt_slow_path(loc == NULL)) { - return NXT_ERROR; - } - - } else { - loc = &conf->location; + if (acf->location == NULL) { + return NXT_OK; + } - encode = nxt_encode_complex_uri(NULL, acf->location.start, - acf->location.length); - loc->length = acf->location.length + encode * 2; + nxt_conf_get_string(acf->location, &str); - loc->start = nxt_mp_nget(mp, loc->length); - if (nxt_slow_path(loc->start == NULL)) { - return NXT_ERROR; - } + conf->location = nxt_var_compile(&str, mp, 0); + if (nxt_slow_path(conf->location == NULL)) { + return NXT_ERROR; + } - nxt_encode_complex_uri(loc->start, acf->location.start, - acf->location.length); - } + if (nxt_var_is_const(conf->location)) { + nxt_var_raw(conf->location, &str); + return nxt_http_return_encode(mp, &conf->encoded, &str); } return NXT_OK; @@ -72,13 +72,24 @@ nxt_http_action_t * nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { - nxt_http_field_t *field; + nxt_int_t ret; + nxt_http_return_ctx_t *ctx; nxt_http_return_conf_t *conf; conf = action->u.conf; - nxt_debug(task, "http return: %d (loc: \"%V\")", - conf->status, &conf->location); +#if (NXT_DEBUG) + nxt_str_t loc; + + if (conf->location == NULL) { + nxt_str_set(&loc, ""); + + } else { + nxt_var_raw(conf->location, &loc); + } + + nxt_debug(task, "http return: %d (loc: \"%V\")", conf->status, &loc); +#endif if (conf->status >= NXT_HTTP_BAD_REQUEST && conf->status <= NXT_HTTP_SERVER_ERROR_MAX) @@ -87,27 +98,125 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, return NULL; } + if (conf->location == NULL) { + ctx = NULL; + + } else { + ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_return_ctx_t)); + if (nxt_slow_path(ctx == NULL)) { + goto fail; + } + } + r->status = conf->status; r->resp.content_length_n = 0; - if (conf->location.length > 0) { + if (ctx == NULL || nxt_var_is_const(conf->location)) { + if (ctx != NULL) { + ctx->encoded = conf->encoded; + } + + nxt_http_return_send_ready(task, r, ctx); + + } else { + ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + nxt_var_query(task, r->var_query, conf->location, &ctx->location); + + nxt_var_query_resolve(task, r->var_query, ctx, + nxt_http_return_send_ready, + nxt_http_return_var_error); + } + + return NULL; + +fail: + + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return NULL; +} + + +static nxt_int_t +nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, + const nxt_str_t *location) +{ + nxt_uint_t encode; + + if (nxt_is_complex_uri_encoded(location->start, location->length)) { + *encoded = *location; + + return NXT_OK; + } + + encode = nxt_encode_complex_uri(NULL, location->start, location->length); + encoded->length = location->length + encode * 2; + + encoded->start = nxt_mp_nget(mp, encoded->length); + if (nxt_slow_path(encoded->start == NULL)) { + return NXT_ERROR; + } + + nxt_encode_complex_uri(encoded->start, location->start, location->length); + + return NXT_OK; +} + + +static void +nxt_http_return_send_ready(nxt_task_t *task, void *obj, void *data) +{ + nxt_int_t ret; + nxt_http_field_t *field; + nxt_http_request_t *r; + nxt_http_return_ctx_t *ctx; + + r = obj; + ctx = data; + + if (ctx != NULL) { + if (ctx->location.length > 0) { + ret = nxt_http_return_encode(r->mem_pool, &ctx->encoded, + &ctx->location); + if (nxt_slow_path(ret == NXT_ERROR)) { + goto fail; + } + } + field = nxt_list_zero_add(r->resp.fields); if (nxt_slow_path(field == NULL)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return NULL; + goto fail; } nxt_http_field_name_set(field, "Location"); - field->value = conf->location.start; - field->value_length = conf->location.length; + field->value = ctx->encoded.start; + field->value_length = ctx->encoded.length; } r->state = &nxt_http_return_send_state; nxt_http_request_header_send(task, r, NULL, NULL); - return NULL; + return; + +fail: + + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); +} + + +static void +nxt_http_return_var_error(nxt_task_t *task, void *obj, void *data) +{ + nxt_http_request_t *r; + + r = obj; + + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 606bf266..9200dc52 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -92,15 +92,6 @@ typedef struct { uint32_t value_length; u_char *name; u_char *value; -} nxt_http_name_value_t; - - -typedef struct { - uint16_t hash; - uint16_t name_length; - uint32_t value_length; - u_char *name; - u_char *value; } nxt_http_cookie_t; @@ -172,17 +163,6 @@ struct nxt_http_routes_s { }; -#define NXT_COOKIE_HASH \ - (nxt_http_field_hash_end( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char( \ - nxt_http_field_hash_char(NXT_HTTP_FIELD_HASH_INIT, \ - 'c'), 'o'), 'o'), 'k'), 'i'), 'e')) & 0xFFFF) - - static nxt_http_route_t *nxt_http_route_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task, @@ -241,10 +221,6 @@ static nxt_int_t nxt_http_route_header(nxt_http_request_t *r, nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule); -static nxt_array_t *nxt_http_route_arguments_parse(nxt_http_request_t *r); -static nxt_http_name_value_t *nxt_http_route_argument(nxt_array_t *array, - u_char *name, size_t name_length, uint32_t hash, u_char *start, - u_char *end); static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r, nxt_http_route_rule_t *rule, nxt_array_t *array); static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, @@ -253,11 +229,6 @@ static nxt_int_t nxt_http_route_query(nxt_http_request_t *r, nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule); -static nxt_array_t *nxt_http_route_cookies_parse(nxt_http_request_t *r); -static nxt_int_t nxt_http_route_cookie_parse(nxt_array_t *cookies, - u_char *start, u_char *end); -static nxt_http_name_value_t *nxt_http_route_cookie(nxt_array_t *array, - u_char *name, size_t name_length, u_char *start, u_char *end); static nxt_int_t nxt_http_route_test_cookie(nxt_http_request_t *r, nxt_http_route_rule_t *rule, nxt_array_t *array); static nxt_int_t nxt_http_route_pattern(nxt_http_request_t *r, @@ -626,7 +597,7 @@ static nxt_conf_map_t nxt_http_route_action_conf[] = { }, { nxt_string("location"), - NXT_CONF_MAP_STR, + NXT_CONF_MAP_PTR, offsetof(nxt_http_action_conf_t, location) }, { @@ -640,6 +611,11 @@ static nxt_conf_map_t nxt_http_route_action_conf[] = { offsetof(nxt_http_action_conf_t, share) }, { + nxt_string("index"), + NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, index) + }, + { nxt_string("chroot"), NXT_CONF_MAP_STR, offsetof(nxt_http_action_conf_t, chroot) @@ -718,13 +694,11 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, { size_t size; uint32_t i, n; - nxt_bool_t array; nxt_conf_value_t *ruleset_cv; nxt_http_route_table_t *table; nxt_http_route_ruleset_t *ruleset; - array = (nxt_conf_type(table_cv) == NXT_CONF_ARRAY); - n = array ? nxt_conf_array_elements_count(table_cv) : 1; + n = nxt_conf_array_elements_count_or_1(table_cv); size = sizeof(nxt_http_route_table_t) + n * sizeof(nxt_http_route_ruleset_t *); @@ -736,20 +710,8 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, table->items = n; table->object = NXT_HTTP_ROUTE_TABLE; - if (!array) { - ruleset = nxt_http_route_ruleset_create(task, mp, table_cv, object, - case_sensitive, encoding); - if (nxt_slow_path(ruleset == NULL)) { - return NULL; - } - - table->ruleset[0] = ruleset; - - return table; - } - for (i = 0; i < n; i++) { - ruleset_cv = nxt_conf_get_array_element(table_cv, i); + ruleset_cv = nxt_conf_get_array_element_or_itself(table_cv, i); ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, object, case_sensitive, encoding); @@ -911,13 +873,11 @@ nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, size_t size; uint32_t i, n; nxt_int_t ret; - nxt_bool_t string; nxt_conf_value_t *value; nxt_http_route_rule_t *rule; nxt_http_route_pattern_t *pattern; - string = (nxt_conf_type(cv) != NXT_CONF_ARRAY); - n = string ? 1 : nxt_conf_array_elements_count(cv); + n = nxt_conf_array_elements_count_or_1(cv); size = sizeof(nxt_http_route_rule_t) + n * sizeof(nxt_http_route_pattern_t); rule = nxt_mp_alloc(mp, size); @@ -929,22 +889,11 @@ nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, pattern = &rule->pattern[0]; - if (string) { - pattern[0].case_sensitive = case_sensitive; - ret = nxt_http_route_pattern_create(task, mp, cv, &pattern[0], - pattern_case, encoding); - if (nxt_slow_path(ret != NXT_OK)) { - return NULL; - } - - return rule; - } - nxt_conf_array_qsort(cv, nxt_http_pattern_compare); for (i = 0; i < n; i++) { pattern[i].case_sensitive = case_sensitive; - value = nxt_conf_get_array_element(cv, i); + value = nxt_conf_get_array_element_or_itself(cv, i); ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i], pattern_case, encoding); @@ -959,17 +908,15 @@ nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, nxt_http_route_addr_rule_t * nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp, - nxt_conf_value_t *cv) + nxt_conf_value_t *cv) { size_t size; uint32_t i, n; - nxt_bool_t array; nxt_conf_value_t *value; nxt_http_route_addr_rule_t *addr_rule; nxt_http_route_addr_pattern_t *pattern; - array = (nxt_conf_type(cv) == NXT_CONF_ARRAY); - n = array ? nxt_conf_array_elements_count(cv) : 1; + n = nxt_conf_array_elements_count_or_1(cv); size = sizeof(nxt_http_route_addr_rule_t) + n * sizeof(nxt_http_route_addr_pattern_t); @@ -981,19 +928,9 @@ nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp, addr_rule->items = n; - if (!array) { - pattern = &addr_rule->addr_pattern[0]; - - if (nxt_http_route_addr_pattern_parse(mp, pattern, cv) != NXT_OK) { - return NULL; - } - - return addr_rule; - } - for (i = 0; i < n; i++) { pattern = &addr_rule->addr_pattern[i]; - value = nxt_conf_get_array_element(cv, i); + value = nxt_conf_get_array_element_or_itself(cv, i); if (nxt_http_route_addr_pattern_parse(mp, pattern, value) != NXT_OK) { return NULL; @@ -2034,7 +1971,7 @@ nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule) { nxt_array_t *arguments; - arguments = nxt_http_route_arguments_parse(r); + arguments = nxt_http_arguments_parse(r); if (nxt_slow_path(arguments == NULL)) { return -1; } @@ -2043,143 +1980,6 @@ nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule) } -static nxt_array_t * -nxt_http_route_arguments_parse(nxt_http_request_t *r) -{ - size_t name_length; - u_char *p, *dst, *dst_start, *start, *end, *name; - uint8_t d0, d1; - uint32_t hash; - nxt_array_t *args; - nxt_http_name_value_t *nv; - - if (r->arguments != NULL) { - return r->arguments; - } - - args = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); - if (nxt_slow_path(args == NULL)) { - return NULL; - } - - hash = NXT_HTTP_FIELD_HASH_INIT; - name = NULL; - name_length = 0; - - dst_start = nxt_mp_nget(r->mem_pool, r->args->length); - if (nxt_slow_path(dst_start == NULL)) { - return NULL; - } - - r->args_decoded.start = dst_start; - - start = r->args->start; - end = start + r->args->length; - - for (p = start, dst = dst_start; p < end; p++, dst++) { - *dst = *p; - - switch (*p) { - case '=': - if (name == NULL) { - name_length = dst - dst_start; - name = dst_start; - dst_start = dst + 1; - } - - continue; - - case '&': - if (name_length != 0 || dst != dst_start) { - nv = nxt_http_route_argument(args, name, name_length, hash, - dst_start, dst); - if (nxt_slow_path(nv == NULL)) { - return NULL; - } - } - - hash = NXT_HTTP_FIELD_HASH_INIT; - name_length = 0; - name = NULL; - dst_start = dst + 1; - - continue; - - case '+': - *dst = ' '; - - break; - - case '%': - if (nxt_slow_path(end - p <= 2)) { - break; - } - - d0 = nxt_hex2int[p[1]]; - d1 = nxt_hex2int[p[2]]; - - if (nxt_slow_path((d0 | d1) >= 16)) { - break; - } - - p += 2; - *dst = (d0 << 4) + d1; - - break; - } - - if (name == NULL) { - hash = nxt_http_field_hash_char(hash, *dst); - } - } - - r->args_decoded.length = dst - r->args_decoded.start; - - if (name_length != 0 || dst != dst_start) { - nv = nxt_http_route_argument(args, name, name_length, hash, dst_start, - dst); - if (nxt_slow_path(nv == NULL)) { - return NULL; - } - } - - r->arguments = args; - - return args; -} - - -static nxt_http_name_value_t * -nxt_http_route_argument(nxt_array_t *array, u_char *name, size_t name_length, - uint32_t hash, u_char *start, u_char *end) -{ - size_t length; - nxt_http_name_value_t *nv; - - nv = nxt_array_add(array); - if (nxt_slow_path(nv == NULL)) { - return NULL; - } - - nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; - - length = end - start; - - if (name == NULL) { - name_length = length; - name = start; - length = 0; - } - - nv->name_length = name_length; - nv->value_length = length; - nv->name = name; - nv->value = start; - - return nv; -} - - static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r, nxt_http_route_rule_t *rule, nxt_array_t *array) @@ -2235,7 +2035,7 @@ nxt_http_route_query(nxt_http_request_t *r, nxt_http_route_rule_t *rule) { nxt_array_t *arguments; - arguments = nxt_http_route_arguments_parse(r); + arguments = nxt_http_arguments_parse(r); if (nxt_slow_path(arguments == NULL)) { return -1; } @@ -2250,7 +2050,7 @@ nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule) { nxt_array_t *cookies; - cookies = nxt_http_route_cookies_parse(r); + cookies = nxt_http_cookies_parse(r); if (nxt_slow_path(cookies == NULL)) { return -1; } @@ -2259,128 +2059,6 @@ nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule) } -static nxt_array_t * -nxt_http_route_cookies_parse(nxt_http_request_t *r) -{ - nxt_int_t ret; - nxt_array_t *cookies; - nxt_http_field_t *f; - - if (r->cookies != NULL) { - return r->cookies; - } - - cookies = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); - if (nxt_slow_path(cookies == NULL)) { - return NULL; - } - - nxt_list_each(f, r->fields) { - - if (f->hash != NXT_COOKIE_HASH - || f->name_length != 6 - || nxt_strncasecmp(f->name, (u_char *) "Cookie", 6) != 0) - { - continue; - } - - ret = nxt_http_route_cookie_parse(cookies, f->value, - f->value + f->value_length); - if (ret != NXT_OK) { - return NULL; - } - - } nxt_list_loop; - - r->cookies = cookies; - - return cookies; -} - - -static nxt_int_t -nxt_http_route_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) -{ - size_t name_length; - u_char c, *p, *name; - nxt_http_name_value_t *nv; - - name = NULL; - name_length = 0; - - for (p = start; p < end; p++) { - c = *p; - - if (c == '=') { - while (start[0] == ' ') { start++; } - - name_length = p - start; - - if (name_length != 0) { - name = start; - } - - start = p + 1; - - } else if (c == ';') { - if (name != NULL) { - nv = nxt_http_route_cookie(cookies, name, name_length, - start, p); - if (nxt_slow_path(nv == NULL)) { - return NXT_ERROR; - } - } - - name = NULL; - start = p + 1; - } - } - - if (name != NULL) { - nv = nxt_http_route_cookie(cookies, name, name_length, start, p); - if (nxt_slow_path(nv == NULL)) { - return NXT_ERROR; - } - } - - return NXT_OK; -} - - -static nxt_http_name_value_t * -nxt_http_route_cookie(nxt_array_t *array, u_char *name, size_t name_length, - u_char *start, u_char *end) -{ - u_char c, *p; - uint32_t hash; - nxt_http_name_value_t *nv; - - nv = nxt_array_add(array); - if (nxt_slow_path(nv == NULL)) { - return NULL; - } - - nv->name_length = name_length; - nv->name = name; - - hash = NXT_HTTP_FIELD_HASH_INIT; - - for (p = name; p < name + name_length; p++) { - c = *p; - hash = nxt_http_field_hash_char(hash, c); - } - - nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; - - while (start < end && end[-1] == ' ') { end--; } - - nv->value_length = end - start; - nv->value = start; - - return nv; -} - - static nxt_int_t nxt_http_route_test_cookie(nxt_http_request_t *r, nxt_http_route_rule_t *rule, nxt_array_t *array) diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 36c1ebc9..61dd0cb3 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -19,6 +19,7 @@ typedef struct { typedef struct { nxt_uint_t nshares; nxt_http_static_share_t *shares; + nxt_str_t index; #if (NXT_HAVE_OPENAT2) nxt_var_t *chroot; nxt_uint_t resolve; @@ -33,7 +34,7 @@ typedef struct { #if (NXT_HAVE_OPENAT2) nxt_str_t chroot; #endif - uint32_t index; + uint32_t share_idx; uint8_t need_body; /* 1 bit */ } nxt_http_static_ctx_t; @@ -75,9 +76,8 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, { uint32_t i; nxt_mp_t *mp; - nxt_str_t str; + nxt_str_t str, *ret; nxt_var_t *var; - nxt_bool_t array; nxt_conf_value_t *cv; nxt_http_static_conf_t *conf; @@ -91,39 +91,36 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, action->handler = nxt_http_static; action->u.conf = conf; - array = (nxt_conf_type(acf->share) == NXT_CONF_ARRAY); - conf->nshares = array ? nxt_conf_array_elements_count(acf->share) : 1; - + conf->nshares = nxt_conf_array_elements_count_or_1(acf->share); conf->shares = nxt_mp_zget(mp, sizeof(nxt_http_static_share_t) * conf->nshares); if (nxt_slow_path(conf->shares == NULL)) { return NXT_ERROR; } - if (array) { - for (i = 0; i < conf->nshares; i++) { - cv = nxt_conf_get_array_element(acf->share, i); - nxt_conf_get_string(cv, &str); - - var = nxt_var_compile(&str, mp, 1); - if (nxt_slow_path(var == NULL)) { - return NXT_ERROR; - } + for (i = 0; i < conf->nshares; i++) { + cv = nxt_conf_get_array_element_or_itself(acf->share, i); + nxt_conf_get_string(cv, &str); - conf->shares[i].var = var; - conf->shares[i].is_const = nxt_var_is_const(var); + var = nxt_var_compile(&str, mp, 1); + if (nxt_slow_path(var == NULL)) { + return NXT_ERROR; } + conf->shares[i].var = var; + conf->shares[i].is_const = nxt_var_is_const(var); + } + + if (acf->index == NULL) { + nxt_str_set(&conf->index, "index.html"); + } else { - nxt_conf_get_string(acf->share, &str); + nxt_conf_get_string(acf->index, &str); - var = nxt_var_compile(&str, mp, 1); - if (nxt_slow_path(var == NULL)) { + ret = nxt_str_dup(mp, &conf->index, &str); + if (nxt_slow_path(ret == NULL)) { return NXT_ERROR; } - - conf->shares[0].var = var; - conf->shares[0].is_const = nxt_var_is_const(var); } #if (NXT_HAVE_OPENAT2) @@ -234,12 +231,14 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, conf = ctx->action->u.conf; - share = &conf->shares[ctx->index]; + share = &conf->shares[ctx->share_idx]; #if (NXT_DEBUG) nxt_str_t shr; + nxt_str_t idx; nxt_var_raw(share->var, &shr); + idx = conf->index; #if (NXT_HAVE_OPENAT2) nxt_str_t chr; @@ -251,9 +250,10 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_str_set(&chr, ""); } - nxt_debug(task, "http static: \"%V\" (chroot: \"%V\")", &shr, &chr); + nxt_debug(task, "http static: \"%V\", index: \"%V\" (chroot: \"%V\")", + &shr, &idx, &chr); #else - nxt_debug(task, "http static: \"%V\"", &shr); + nxt_debug(task, "http static: \"%V\", index: \"%V\"", &shr, &idx); #endif #endif /* NXT_DEBUG */ @@ -261,7 +261,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_var_raw(share->var, &ctx->share); #if (NXT_HAVE_OPENAT2) - if (conf->chroot != NULL && ctx->index == 0) { + if (conf->chroot != NULL && ctx->share_idx == 0) { nxt_var_raw(conf->chroot, &ctx->chroot); } #endif @@ -278,7 +278,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_var_query(task, r->var_query, share->var, &ctx->share); #if (NXT_HAVE_OPENAT2) - if (conf->chroot != NULL && ctx->index == 0) { + if (conf->chroot != NULL && ctx->share_idx == 0) { nxt_var_query(task, r->var_query, conf->chroot, &ctx->chroot); } #endif @@ -298,7 +298,7 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) struct tm tm; nxt_buf_t *fb; nxt_int_t ret; - nxt_str_t *shr, exten, *mtype; + nxt_str_t *shr, *index, exten, *mtype; nxt_uint_t level; nxt_file_t *f, file; nxt_file_info_t fi; @@ -311,8 +311,6 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) nxt_http_static_ctx_t *ctx; nxt_http_static_conf_t *conf; - static const nxt_str_t index = nxt_string("index.html"); - r = obj; ctx = data; action = ctx->action; @@ -323,12 +321,12 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) mtype = NULL; shr = &ctx->share; + index = &conf->index; if (shr->start[shr->length - 1] == '/') { - /* TODO: dynamic index setting. */ - nxt_str_set(&exten, ".html"); + nxt_http_static_extract_extension(index, &exten); - length = shr->length + index.length; + length = shr->length + index->length; fname = nxt_mp_nget(r->mem_pool, length + 1); if (nxt_slow_path(fname == NULL)) { @@ -337,7 +335,7 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) p = fname; p = nxt_cpymem(p, shr->start, shr->length); - p = nxt_cpymem(p, index.start, index.length); + p = nxt_cpymem(p, index->start, index->length); *p = '\0'; } else { @@ -373,7 +371,7 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) nxt_uint_t resolve; nxt_http_static_share_t *share; - share = &conf->shares[ctx->index]; + share = &conf->shares[ctx->share_idx]; resolve = conf->resolve; chr = &ctx->chroot; @@ -587,7 +585,9 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) /* Not a file. */ nxt_file_close(task, f); - if (nxt_slow_path(!nxt_is_dir(&fi))) { + if (nxt_slow_path(!nxt_is_dir(&fi) + || shr->start[shr->length - 1] == '/')) + { nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file", f->name); @@ -675,9 +675,9 @@ nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, action = ctx->action; conf = action->u.conf; - ctx->index++; + ctx->share_idx++; - if (ctx->index < conf->nshares) { + if (ctx->share_idx < conf->nshares) { nxt_http_static_iterate(task, r, ctx); return; } diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index 1c0b561d..b765e177 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -9,6 +9,8 @@ static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, void *ctx); +static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, + nxt_var_query_t *query, nxt_str_t *str, void *ctx); static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, void *ctx); static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, @@ -20,6 +22,10 @@ static nxt_var_decl_t nxt_http_vars[] = { &nxt_http_var_method, 0 }, + { nxt_string("request_uri"), + &nxt_http_var_request_uri, + 0 }, + { nxt_string("uri"), &nxt_http_var_uri, 0 }, @@ -52,6 +58,20 @@ nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, static nxt_int_t +nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query, + nxt_str_t *str, void *ctx) +{ + nxt_http_request_t *r; + + r = ctx; + + *str = r->target; + + return NXT_OK; +} + + +static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, void *ctx) { diff --git a/src/nxt_job.h b/src/nxt_job.h index d308c35d..0495c484 100644 --- a/src/nxt_job.h +++ b/src/nxt_job.h @@ -67,21 +67,18 @@ NXT_EXPORT void nxt_job_return(nxt_task_t *task, nxt_job_t *job, nxt_work_handler_t handler); -#define \ -nxt_job_cancel(job) \ +#define nxt_job_cancel(job) \ (job)->cancel = 1 #if (NXT_DEBUG) -#define \ -nxt_job_set_name(job, text) \ +#define nxt_job_set_name(job, text) \ (job)->name = text #else -#define \ -nxt_job_set_name(job, text) +#define nxt_job_set_name(job, text) #endif diff --git a/src/nxt_list.h b/src/nxt_list.h index ecbb67a9..dc948e03 100644 --- a/src/nxt_list.h +++ b/src/nxt_list.h @@ -37,18 +37,15 @@ typedef struct { } nxt_list_next_t; -#define \ -nxt_list_part(list) \ +#define nxt_list_part(list) \ (&(list)->part) -#define \ -nxt_list_data(part) \ +#define nxt_list_data(part) \ ((void *) part->data) -#define \ -nxt_list_first(list) \ +#define nxt_list_first(list) \ nxt_list_data(nxt_list_part(list)) @@ -102,8 +99,7 @@ NXT_EXPORT void *nxt_list_zero_add(nxt_list_t *list); NXT_EXPORT void *nxt_list_next(nxt_list_t *list, nxt_list_next_t *next); -#define \ -nxt_list_next_value(list, next) \ +#define nxt_list_next_value(list, next) \ (nxt_pointer_to(nxt_list_data((next)->part), (next)->elt * (list)->size)) diff --git a/src/nxt_log.h b/src/nxt_log.h index 0cf10b5c..aa2fe673 100644 --- a/src/nxt_log.h +++ b/src/nxt_log.h @@ -41,8 +41,7 @@ NXT_EXPORT void nxt_cdecl nxt_log_handler(nxt_uint_t level, nxt_log_t *log, const char *fmt, ...); -#define \ -nxt_log_level_enough(log, level) \ +#define nxt_log_level_enough(log, level) \ ((log)->level >= (level)) @@ -83,8 +82,7 @@ nxt_log_level_enough(log, level) \ } while (0) -#define \ -nxt_log_error(_level, _log, ...) \ +#define nxt_log_error(_level, _log, ...) \ do { \ nxt_log_t *_log_ = (_log); \ nxt_uint_t _level_ = (_level); \ @@ -107,8 +105,7 @@ nxt_log_error(_level, _log, ...) \ } while (0) -#define \ -nxt_log_debug(_log, ...) \ +#define nxt_log_debug(_log, ...) \ do { \ nxt_log_t *_log_ = (_log); \ \ @@ -131,8 +128,7 @@ nxt_log_debug(_log, ...) \ #define nxt_debug(...) -#define \ -nxt_log_debug(...) +#define nxt_log_debug(...) #define nxt_assert(c) @@ -151,18 +147,15 @@ nxt_log_debug(...) #endif -#define \ -nxt_main_log_alert(...) \ +#define nxt_main_log_alert(...) \ nxt_log_alert(&nxt_main_log, __VA_ARGS__) -#define \ -nxt_main_log_error(level, ...) \ +#define nxt_main_log_error(level, ...) \ nxt_log_error(level, &nxt_main_log, __VA_ARGS__) -#define \ -nxt_main_log_debug(...) \ +#define nxt_main_log_debug(...) \ nxt_log_debug(&nxt_main_log, __VA_ARGS__) diff --git a/src/nxt_log_moderation.h b/src/nxt_log_moderation.h index 0a53594d..c6033201 100644 --- a/src/nxt_log_moderation.h +++ b/src/nxt_log_moderation.h @@ -23,8 +23,7 @@ typedef struct { #define NXT_LOG_MODERATION 0, -1, 0, 0, NXT_TIMER -#define \ -nxt_log_alert_moderate(_mod, _log, ...) \ +#define nxt_log_alert_moderate(_mod, _log, ...) \ do { \ nxt_log_t *_log_ = _log; \ \ @@ -34,8 +33,7 @@ nxt_log_alert_moderate(_mod, _log, ...) \ } while (0) -#define \ -nxt_log_moderate(_mod, _level, _log, ...) \ +#define nxt_log_moderate(_mod, _level, _log, ...) \ do { \ nxt_log_t *_log_ = _log; \ \ diff --git a/src/nxt_lvlhsh.c b/src/nxt_lvlhsh.c index d10dbc58..7a8b3dda 100644 --- a/src/nxt_lvlhsh.c +++ b/src/nxt_lvlhsh.c @@ -43,121 +43,98 @@ * several levels. */ -#define \ -nxt_lvlhsh_is_bucket(p) \ +#define nxt_lvlhsh_is_bucket(p) \ ((uintptr_t) (p) & 1) -#define \ -nxt_lvlhsh_count_inc(n) \ +#define nxt_lvlhsh_count_inc(n) \ n = (void *) ((uintptr_t) (n) + 2) -#define \ -nxt_lvlhsh_count_dec(n) \ +#define nxt_lvlhsh_count_dec(n) \ n = (void *) ((uintptr_t) (n) - 2) -#define \ -nxt_lvlhsh_level_size(proto, nlvl) \ +#define nxt_lvlhsh_level_size(proto, nlvl) \ ((uintptr_t) 1 << proto->shift[nlvl]) -#define \ -nxt_lvlhsh_level(lvl, mask) \ +#define nxt_lvlhsh_level(lvl, mask) \ (void **) ((uintptr_t) lvl & (~mask << 2)) -#define \ -nxt_lvlhsh_level_entries(lvl, mask) \ +#define nxt_lvlhsh_level_entries(lvl, mask) \ ((uintptr_t) lvl & (mask << 1)) -#define \ -nxt_lvlhsh_store_bucket(slot, bkt) \ +#define nxt_lvlhsh_store_bucket(slot, bkt) \ slot = (void **) ((uintptr_t) bkt | 2 | 1) -#define \ -nxt_lvlhsh_bucket_size(proto) \ +#define nxt_lvlhsh_bucket_size(proto) \ proto->bucket_size -#define \ -nxt_lvlhsh_bucket(proto, bkt) \ +#define nxt_lvlhsh_bucket(proto, bkt) \ (uint32_t *) ((uintptr_t) bkt & ~(uintptr_t) proto->bucket_mask) -#define \ -nxt_lvlhsh_bucket_entries(proto, bkt) \ +#define nxt_lvlhsh_bucket_entries(proto, bkt) \ (((uintptr_t) bkt & (uintptr_t) proto->bucket_mask) >> 1) -#define \ -nxt_lvlhsh_bucket_end(proto, bkt) \ +#define nxt_lvlhsh_bucket_end(proto, bkt) \ &bkt[proto->bucket_end] -#define \ -nxt_lvlhsh_free_entry(e) \ +#define nxt_lvlhsh_free_entry(e) \ (!(nxt_lvlhsh_valid_entry(e))) -#define \ -nxt_lvlhsh_next_bucket(proto, bkt) \ +#define nxt_lvlhsh_next_bucket(proto, bkt) \ ((void **) &bkt[proto->bucket_end]) #if (NXT_64BIT) -#define \ -nxt_lvlhsh_valid_entry(e) \ +#define nxt_lvlhsh_valid_entry(e) \ (((e)[0] | (e)[1]) != 0) -#define \ -nxt_lvlhsh_entry_value(e) \ +#define nxt_lvlhsh_entry_value(e) \ (void *) (((uintptr_t) (e)[1] << 32) + (e)[0]) -#define \ -nxt_lvlhsh_set_entry_value(e, n) \ +#define nxt_lvlhsh_set_entry_value(e, n) \ (e)[0] = (uint32_t) (uintptr_t) n; \ (e)[1] = (uint32_t) ((uintptr_t) n >> 32) -#define \ -nxt_lvlhsh_entry_key(e) \ +#define nxt_lvlhsh_entry_key(e) \ (e)[2] -#define \ -nxt_lvlhsh_set_entry_key(e, n) \ +#define nxt_lvlhsh_set_entry_key(e, n) \ (e)[2] = n #else -#define \ -nxt_lvlhsh_valid_entry(e) \ +#define nxt_lvlhsh_valid_entry(e) \ ((e)[0] != 0) -#define \ -nxt_lvlhsh_entry_value(e) \ +#define nxt_lvlhsh_entry_value(e) \ (void *) (e)[0] -#define \ -nxt_lvlhsh_set_entry_value(e, n) \ +#define nxt_lvlhsh_set_entry_value(e, n) \ (e)[0] = (uint32_t) n -#define \ -nxt_lvlhsh_entry_key(e) \ +#define nxt_lvlhsh_entry_key(e) \ (e)[1] -#define \ -nxt_lvlhsh_set_entry_key(e, n) \ +#define nxt_lvlhsh_set_entry_key(e, n) \ (e)[1] = n #endif diff --git a/src/nxt_lvlhsh.h b/src/nxt_lvlhsh.h index 7127c0d0..c051081c 100644 --- a/src/nxt_lvlhsh.h +++ b/src/nxt_lvlhsh.h @@ -114,13 +114,11 @@ typedef struct { } nxt_lvlhsh_each_t; -#define \ -nxt_lvlhsh_is_empty(lh) \ +#define nxt_lvlhsh_is_empty(lh) \ ((lh)->slot == NULL) -#define \ -nxt_lvlhsh_init(lh) \ +#define nxt_lvlhsh_init(lh) \ (lh)->slot = NULL /* diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 61521854..03761a10 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -382,25 +382,25 @@ nxt_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) port = rt->port_by_type[NXT_PROCESS_ROUTER]; if (nxt_slow_path(port == NULL)) { nxt_alert(task, "router port not found"); - return; + goto close_fds; } if (nxt_slow_path(port->pid != nxt_recv_msg_cmsg_pid(msg))) { nxt_alert(task, "process %PI cannot start processes", nxt_recv_msg_cmsg_pid(msg)); - return; + goto close_fds; } process = nxt_process_new(rt); if (nxt_slow_path(process == NULL)) { - return; + goto close_fds; } process->mem_pool = nxt_mp_create(1024, 128, 256, 32); if (process->mem_pool == NULL) { nxt_process_use(task, process, -1); - return; + goto close_fds; } process->parent_port = rt->port_by_type[NXT_PROCESS_MAIN]; @@ -422,6 +422,9 @@ nxt_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) goto failed; } + app_conf->shared_port_fd = msg->fd[0]; + app_conf->shared_queue_fd = msg->fd[1]; + start = b->mem.pos; app_conf->name.start = start; @@ -509,6 +512,17 @@ nxt_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) ret = nxt_process_start(task, process); if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) { + + /* Close shared port fds only in main process. */ + if (ret == NXT_OK) { + nxt_fd_close(app_conf->shared_port_fd); + nxt_fd_close(app_conf->shared_queue_fd); + } + + /* Avoid fds close in caller. */ + msg->fd[0] = -1; + msg->fd[1] = -1; + return; } @@ -523,6 +537,14 @@ failed: nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, msg->port_msg.stream, 0, NULL); } + +close_fds: + + nxt_fd_close(msg->fd[0]); + msg->fd[0] = -1; + + nxt_fd_close(msg->fd[1]); + msg->fd[1] = -1; } @@ -557,7 +579,7 @@ nxt_main_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -1, msg->port_msg.stream, 0, NULL); return; } - } + } #endif diff --git a/src/nxt_malloc.c b/src/nxt_malloc.c index fed58e96..5ea7322f 100644 --- a/src/nxt_malloc.c +++ b/src/nxt_malloc.c @@ -64,17 +64,24 @@ nxt_zalloc(size_t size) void * nxt_realloc(void *p, size_t size) { - void *n; + void *n; + uintptr_t ptr; + + /* + * Workaround for a warning on GCC 12 about using "p" pointer in debug log + * after realloc(). + */ + ptr = (uintptr_t) p; n = realloc(p, size); if (nxt_fast_path(n != NULL)) { - nxt_log_debug(nxt_malloc_log(), "realloc(%p, %uz): %p", p, size, n); + nxt_log_debug(nxt_malloc_log(), "realloc(%p, %uz): %p", ptr, size, n); } else { nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), "realloc(%p, %uz) failed %E", - p, size, nxt_errno); + ptr, size, nxt_errno); } return n; diff --git a/src/nxt_malloc.h b/src/nxt_malloc.h index ccc3e1ef..fd5493a5 100644 --- a/src/nxt_malloc.h +++ b/src/nxt_malloc.h @@ -24,8 +24,7 @@ NXT_EXPORT void nxt_free(void *p); #else -#define \ -nxt_free(p) \ +#define nxt_free(p) \ free(p) #endif @@ -54,12 +53,10 @@ nxt_free(p) \ * Glibc malloc_usable_size() is fast operation. */ -#define \ -nxt_malloc_usable_size(p, size) \ +#define nxt_malloc_usable_size(p, size) \ size = malloc_usable_size(p) -#define \ -nxt_malloc_cutback(cutback, size) \ +#define nxt_malloc_cutback(cutback, size) \ size = ((cutback) && size > 127 * 1024) ? size - 32 : size #elif (NXT_FREEBSD) @@ -81,12 +78,10 @@ nxt_malloc_cutback(cutback, size) \ * are lesser than 1M. Larger allocations require mutex acquiring. */ -#define \ -nxt_malloc_usable_size(p, size) \ +#define nxt_malloc_usable_size(p, size) \ size = malloc_usable_size(p) -#define \ -nxt_malloc_cutback(cutback, size) +#define nxt_malloc_cutback(cutback, size) #endif @@ -103,20 +98,16 @@ nxt_malloc_cutback(cutback, size) * malloc_good_size() is faster than malloc_size() */ -#define \ -nxt_malloc_usable_size(p, size) \ +#define nxt_malloc_usable_size(p, size) \ size = malloc_good_size(size) -#define \ -nxt_malloc_cutback(cutback, size) +#define nxt_malloc_cutback(cutback, size) #else -#define \ -nxt_malloc_usable_size(p, size) +#define nxt_malloc_usable_size(p, size) -#define \ -nxt_malloc_cutback(cutback, size) +#define nxt_malloc_cutback(cutback, size) #endif diff --git a/src/nxt_mem_map.h b/src/nxt_mem_map.h index a4a10cc4..e529aff8 100644 --- a/src/nxt_mem_map.h +++ b/src/nxt_mem_map.h @@ -43,17 +43,14 @@ #define NXT_MEM_MAP_FILE (MAP_SHARED | NXT_MEM_MAP_PREFAULT) -#define \ - nxt_mem_map_file_ctx_t(ctx) +#define nxt_mem_map_file_ctx_t(ctx) -#define \ -nxt_mem_map(addr, ctx, len, protection, flags, fd, offset) \ +#define nxt_mem_map(addr, ctx, len, protection, flags, fd, offset) \ nxt_mem_mmap(addr, len, protection, flags, fd, offset) -#define \ -nxt_mem_unmap(addr, ctx, len) \ +#define nxt_mem_unmap(addr, ctx, len) \ nxt_mem_munmap(addr, len) diff --git a/src/nxt_mem_zone.c b/src/nxt_mem_zone.c index 67c6d746..f8ab09d9 100644 --- a/src/nxt_mem_zone.c +++ b/src/nxt_mem_zone.c @@ -87,48 +87,39 @@ struct nxt_mem_zone_s { }; -#define \ -nxt_mem_zone_page_addr(zone, page) \ +#define nxt_mem_zone_page_addr(zone, page) \ (void *) (zone->start + ((page - zone->pages) << zone->page_size_shift)) -#define \ -nxt_mem_zone_addr_page(zone, addr) \ +#define nxt_mem_zone_addr_page(zone, addr) \ &zone->pages[((u_char *) addr - zone->start) >> zone->page_size_shift] -#define \ -nxt_mem_zone_page_is_free(page) \ +#define nxt_mem_zone_page_is_free(page) \ (page->size < NXT_MEM_ZONE_PAGE_USED) -#define \ -nxt_mem_zone_page_is_chunked(page) \ +#define nxt_mem_zone_page_is_chunked(page) \ (page->size >= 16) -#define \ -nxt_mem_zone_page_bitmap(zone, slot) \ +#define nxt_mem_zone_page_bitmap(zone, slot) \ (slot->size < zone->small_bitmap_min_size) -#define \ -nxt_mem_zone_set_chunk_free(map, chunk) \ +#define nxt_mem_zone_set_chunk_free(map, chunk) \ map[chunk / 8] &= ~(0x80 >> (chunk & 7)) -#define \ -nxt_mem_zone_chunk_is_free(map, chunk) \ +#define nxt_mem_zone_chunk_is_free(map, chunk) \ ((map[chunk / 8] & (0x80 >> (chunk & 7))) == 0) -#define \ -nxt_mem_zone_fresh_junk(p, size) \ +#define nxt_mem_zone_fresh_junk(p, size) \ nxt_memset((p), 0xA5, size) -#define \ -nxt_mem_zone_free_junk(p, size) \ +#define nxt_mem_zone_free_junk(p, size) \ nxt_memset((p), 0x5A, size) diff --git a/src/nxt_mem_zone.h b/src/nxt_mem_zone.h index 3f078c2d..89d73ca2 100644 --- a/src/nxt_mem_zone.h +++ b/src/nxt_mem_zone.h @@ -14,8 +14,7 @@ typedef struct nxt_mem_zone_s nxt_mem_zone_t; NXT_EXPORT nxt_mem_zone_t *nxt_mem_zone_init(u_char *start, size_t zone_size, nxt_uint_t page_size); -#define \ -nxt_mem_zone_alloc(zone, size) \ +#define nxt_mem_zone_alloc(zone, size) \ nxt_mem_zone_align((zone), 1, (size)) NXT_EXPORT void *nxt_mem_zone_align(nxt_mem_zone_t *zone, size_t alignment, diff --git a/src/nxt_mp.c b/src/nxt_mp.c index 4eaa16d0..d0de2c0e 100644 --- a/src/nxt_mp.c +++ b/src/nxt_mp.c @@ -939,12 +939,12 @@ nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster, u_char *p) page = cluster->pages; do { - if (page->size != 0) { - return NULL; - } + if (page->size != 0) { + return NULL; + } - page++; - n--; + page++; + n--; } while (n != 0); /* Free cluster. */ @@ -953,9 +953,9 @@ nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster, u_char *p) page = cluster->pages; do { - nxt_queue_remove(&page->link); - page++; - n--; + nxt_queue_remove(&page->link); + page++; + n--; } while (n != 0); nxt_rbtree_delete(&mp->blocks, &cluster->node); diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index 1e08015e..e19b1381 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -6,6 +6,9 @@ #include <nxt_main.h> #include <nxt_conf.h> + +#define OPENSSL_SUPPRESS_DEPRECATED + #include <openssl/ssl.h> #include <openssl/conf.h> #include <openssl/err.h> @@ -323,6 +326,11 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp, SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); #endif +#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF + /* Request SSL_ERROR_ZERO_RETURN on EOF. */ + SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); +#endif + #ifdef SSL_MODE_RELEASE_BUFFERS if (nxt_openssl_version >= 10001078) { @@ -644,16 +652,10 @@ nxt_tls_ticket_keys(nxt_task_t *task, SSL_CTX *ctx, nxt_tls_init_t *tls_init, return NXT_OK; } - if (nxt_conf_type(tickets_conf) == NXT_CONF_ARRAY) { - count = nxt_conf_array_elements_count(tickets_conf); - - if (count == 0) { - goto no_ticket; - } + count = nxt_conf_array_elements_count_or_1(tickets_conf); - } else { - /* nxt_conf_type(tickets_conf) == NXT_CONF_STRING */ - count = 1; + if (count == 0) { + goto no_ticket; } #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB @@ -673,15 +675,9 @@ nxt_tls_ticket_keys(nxt_task_t *task, SSL_CTX *ctx, nxt_tls_init_t *tls_init, i++; - if (nxt_conf_type(tickets_conf) == NXT_CONF_ARRAY) { - member = nxt_conf_get_array_element(tickets_conf, count - i); - if (member == NULL) { - break; - } - - } else { - /* nxt_conf_type(tickets_conf) == NXT_CONF_STRING */ - member = tickets_conf; + member = nxt_conf_get_array_element_or_itself(tickets_conf, count - i); + if (member == NULL) { + break; } nxt_conf_get_string(member, &value); diff --git a/src/nxt_port.c b/src/nxt_port.c index a5b64695..ed7050f3 100644 --- a/src/nxt_port.c +++ b/src/nxt_port.c @@ -176,8 +176,9 @@ nxt_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) if (nxt_fast_path(msg->port_msg.type < NXT_PORT_MSG_MAX)) { - nxt_debug(task, "port %d: message type:%uD", - msg->port->socket.fd, msg->port_msg.type); + nxt_debug(task, "port %d: message type:%uD fds:%d,%d", + msg->port->socket.fd, msg->port_msg.type, + msg->fd[0], msg->fd[1]); handlers = msg->port->data; handlers[msg->port_msg.type](task, msg); diff --git a/src/nxt_queue.h b/src/nxt_queue.h index 44e9ad61..6b7f5d57 100644 --- a/src/nxt_queue.h +++ b/src/nxt_queue.h @@ -21,16 +21,14 @@ typedef struct { } nxt_queue_t; -#define \ -nxt_queue_init(queue) \ +#define nxt_queue_init(queue) \ do { \ (queue)->head.prev = &(queue)->head; \ (queue)->head.next = &(queue)->head; \ } while (0) -#define \ -nxt_queue_sentinel(link) \ +#define nxt_queue_sentinel(link) \ do { \ (link)->prev = (link); \ (link)->next = (link); \ @@ -42,13 +40,11 @@ nxt_queue_sentinel(link) \ * using nxt_queue_remove(). */ -#define \ -nxt_queue_self(link) \ +#define nxt_queue_self(link) \ nxt_queue_sentinel(link) -#define \ -nxt_queue_is_empty(queue) \ +#define nxt_queue_is_empty(queue) \ (&(queue)->head == (queue)->head.prev) /* @@ -73,38 +69,31 @@ nxt_queue_is_empty(queue) \ * tp = nxt_queue_link_data(lnk, nxt_type_t, link); */ -#define \ -nxt_queue_first(queue) \ +#define nxt_queue_first(queue) \ (queue)->head.next -#define \ -nxt_queue_last(queue) \ +#define nxt_queue_last(queue) \ (queue)->head.prev -#define \ -nxt_queue_head(queue) \ +#define nxt_queue_head(queue) \ (&(queue)->head) -#define \ -nxt_queue_tail(queue) \ +#define nxt_queue_tail(queue) \ (&(queue)->head) -#define \ -nxt_queue_next(link) \ +#define nxt_queue_next(link) \ (link)->next -#define \ -nxt_queue_prev(link) \ +#define nxt_queue_prev(link) \ (link)->prev -#define \ -nxt_queue_insert_head(queue, link) \ +#define nxt_queue_insert_head(queue, link) \ do { \ (link)->next = (queue)->head.next; \ (link)->next->prev = (link); \ @@ -113,8 +102,7 @@ nxt_queue_insert_head(queue, link) \ } while (0) -#define \ -nxt_queue_insert_tail(queue, link) \ +#define nxt_queue_insert_tail(queue, link) \ do { \ (link)->prev = (queue)->head.prev; \ (link)->prev->next = (link); \ @@ -123,8 +111,7 @@ nxt_queue_insert_tail(queue, link) \ } while (0) -#define \ -nxt_queue_insert_after(target, link) \ +#define nxt_queue_insert_after(target, link) \ do { \ (link)->next = (target)->next; \ (link)->next->prev = (link); \ @@ -133,8 +120,7 @@ nxt_queue_insert_after(target, link) \ } while (0) -#define \ -nxt_queue_insert_before(target, link) \ +#define nxt_queue_insert_before(target, link) \ do { \ (link)->next = (target); \ (link)->prev = (target)->prev; \ @@ -145,8 +131,7 @@ nxt_queue_insert_before(target, link) \ #if (NXT_DEBUG) -#define \ -nxt_queue_remove(link) \ +#define nxt_queue_remove(link) \ do { \ (link)->next->prev = (link)->prev; \ (link)->prev->next = (link)->next; \ @@ -156,8 +141,7 @@ nxt_queue_remove(link) \ #else -#define \ -nxt_queue_remove(link) \ +#define nxt_queue_remove(link) \ do { \ (link)->next->prev = (link)->prev; \ (link)->prev->next = (link)->next; \ @@ -171,8 +155,7 @@ nxt_queue_remove(link) \ * the "tail" is the new tail queue. */ -#define \ -nxt_queue_split(queue, link, tail) \ +#define nxt_queue_split(queue, link, tail) \ do { \ (tail)->head.prev = (queue)->head.prev; \ (tail)->head.prev->next = &(tail)->head; \ @@ -185,8 +168,7 @@ nxt_queue_split(queue, link, tail) \ /* Truncate the queue "queue" starting at element "link". */ -#define \ -nxt_queue_truncate(queue, link) \ +#define nxt_queue_truncate(queue, link) \ do { \ (queue)->head.prev = (link)->prev; \ (queue)->head.prev->next = &(queue)->head; \ @@ -199,8 +181,7 @@ nxt_queue_truncate(queue, link) \ * it must be initiated with nxt_queue_init(tail). */ -#define \ -nxt_queue_add(queue, tail) \ +#define nxt_queue_add(queue, tail) \ do { \ (queue)->head.prev->next = (tail)->head.next; \ (tail)->head.next->prev = (queue)->head.prev; \ @@ -209,8 +190,7 @@ nxt_queue_add(queue, tail) \ } while (0) -#define \ -nxt_queue_link_data(lnk, type, link) \ +#define nxt_queue_link_data(lnk, type, link) \ nxt_container_of(lnk, type, link) diff --git a/src/nxt_router.c b/src/nxt_router.c index 85556a72..3a32a363 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -223,8 +223,6 @@ static void nxt_router_access_log_reopen_error(nxt_task_t *task, static void nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); -static nxt_int_t nxt_router_app_shared_port_send(nxt_task_t *task, - nxt_port_t *app_port); static void nxt_router_app_port_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); @@ -396,6 +394,7 @@ nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, { size_t size; uint32_t stream; + nxt_fd_t port_fd, queue_fd; nxt_int_t ret; nxt_app_t *app; nxt_buf_t *b; @@ -415,6 +414,8 @@ nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, nxt_debug(task, "app '%V' %p start process", &app->name, app); b = NULL; + port_fd = -1; + queue_fd = -1; } else { if (app->proto_port_requests > 0) { @@ -441,6 +442,9 @@ nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, nxt_buf_cpystr(b, &app->name); *b->mem.free++ = '\0'; nxt_buf_cpystr(b, &app->conf); + + port_fd = app->shared_port->pair[0]; + queue_fd = app->shared_port->queue_fd; } app_joint_rpc = nxt_port_rpc_register_handler_ex(task, port, @@ -453,8 +457,8 @@ nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, stream = nxt_port_rpc_ex_stream(app_joint_rpc); - ret = nxt_port_socket_write(task, dport, NXT_PORT_MSG_START_PROCESS, - -1, stream, port->id, b); + ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS, + port_fd, queue_fd, stream, port->id, b); if (nxt_slow_path(ret != NXT_OK)) { nxt_port_rpc_cancel(task, port, stream); @@ -1920,25 +1924,15 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, tls_init->tickets_conf = nxt_conf_get_path(listener, &conf_tickets); - if (nxt_conf_type(certificate) == NXT_CONF_ARRAY) { - n = nxt_conf_array_elements_count(certificate); - - for (i = 0; i < n; i++) { - value = nxt_conf_get_array_element(certificate, i); - - nxt_assert(value != NULL); + n = nxt_conf_array_elements_count_or_1(certificate); - ret = nxt_router_conf_tls_insert(tmcf, value, skcf, - tls_init, i == 0); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } - } + for (i = 0; i < n; i++) { + value = nxt_conf_get_array_element_or_itself(certificate, + i); + nxt_assert(value != NULL); - } else { - /* NXT_CONF_STRING */ - ret = nxt_router_conf_tls_insert(tmcf, certificate, skcf, - tls_init, 1); + ret = nxt_router_conf_tls_insert(tmcf, value, skcf, + tls_init, i == 0); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } @@ -2779,6 +2773,7 @@ nxt_router_app_rpc_create(nxt_task_t *task, { size_t size; uint32_t stream; + nxt_fd_t port_fd, queue_fd; nxt_int_t ret; nxt_buf_t *b; nxt_port_t *router_port, *dport; @@ -2807,10 +2802,15 @@ nxt_router_app_rpc_create(nxt_task_t *task, dport = rt->port_by_type[NXT_PROCESS_MAIN]; + port_fd = app->shared_port->pair[0]; + queue_fd = app->shared_port->queue_fd; + } else { nxt_debug(task, "app '%V' prefork", &app->name); b = NULL; + port_fd = -1; + queue_fd = -1; } router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; @@ -2829,9 +2829,8 @@ nxt_router_app_rpc_create(nxt_task_t *task, stream = nxt_port_rpc_ex_stream(rpc); - ret = nxt_port_socket_write(task, dport, - NXT_PORT_MSG_START_PROCESS, - -1, stream, router_port->id, b); + ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS, + port_fd, queue_fd, stream, router_port->id, b); if (nxt_slow_path(ret != NXT_OK)) { nxt_port_rpc_cancel(task, router_port, stream); goto fail; @@ -2906,7 +2905,7 @@ nxt_router_app_prefork_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, nxt_port_inc_use(port); - nxt_router_app_shared_port_send(task, port); + nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); nxt_work_queue_add(&engine->fast_work_queue, nxt_router_conf_apply, task, rpc->temp_conf, NULL); @@ -4618,46 +4617,12 @@ nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, nxt_debug(task, "app '%V' new port ready, pid %PI, %d/%d", &app->name, port->pid, app->processes, app->pending_processes); - nxt_router_app_shared_port_send(task, port); + nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); nxt_router_app_port_release(task, app, port, NXT_APR_NEW_PORT); } -static nxt_int_t -nxt_router_app_shared_port_send(nxt_task_t *task, nxt_port_t *app_port) -{ - nxt_buf_t *b; - nxt_port_t *port; - nxt_port_msg_new_port_t *msg; - - b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, - sizeof(nxt_port_data_t)); - if (nxt_slow_path(b == NULL)) { - return NXT_ERROR; - } - - port = app_port->app->shared_port; - - nxt_debug(task, "send port %FD to process %PI", - port->pair[0], app_port->pid); - - b->mem.free += sizeof(nxt_port_msg_new_port_t); - msg = (nxt_port_msg_new_port_t *) b->mem.pos; - - msg->id = port->id; - msg->pid = port->pid; - msg->max_size = port->max_size; - msg->max_share = port->max_share; - msg->type = port->type; - - return nxt_port_socket_write2(task, app_port, - NXT_PORT_MSG_NEW_PORT, - port->pair[0], port->queue_fd, - 0, 0, b); -} - - static void nxt_router_app_port_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) diff --git a/src/nxt_service.h b/src/nxt_service.h index 55d98351..c43d5394 100644 --- a/src/nxt_service.h +++ b/src/nxt_service.h @@ -15,8 +15,7 @@ typedef struct { } nxt_service_t; -#define \ -nxt_service_is_module(s) \ +#define nxt_service_is_module(s) \ ((s)->type == NULL) diff --git a/src/nxt_signal.h b/src/nxt_signal.h index 900a9e16..bc61eb2f 100644 --- a/src/nxt_signal.h +++ b/src/nxt_signal.h @@ -36,12 +36,10 @@ typedef struct { nxt_event_signals_t *nxt_event_engine_signals(const nxt_sig_event_t *sigev); -#define \ -nxt_event_engine_signals_start(engine) \ +#define nxt_event_engine_signals_start(engine) \ nxt_signal_thread_start(engine) -#define \ -nxt_event_engine_signals_stop(engine) \ +#define nxt_event_engine_signals_stop(engine) \ nxt_signal_thread_stop(engine) diff --git a/src/nxt_socket.h b/src/nxt_socket.h index ec21d779..69b09039 100644 --- a/src/nxt_socket.h +++ b/src/nxt_socket.h @@ -118,12 +118,10 @@ NXT_EXPORT ssize_t nxt_socketpair_recv(nxt_fd_event_t *ev, nxt_iobuf_t *iob, nxt_uint_t niob, void *oob); -#define \ -nxt_socket_nonblocking(task, fd) \ +#define nxt_socket_nonblocking(task, fd) \ nxt_fd_nonblocking(task, fd) -#define \ -nxt_socket_blocking(task, fd) \ +#define nxt_socket_blocking(task, fd) \ nxt_fd_blocking(task, fd) diff --git a/src/nxt_source.h b/src/nxt_source.h index 976cc8f9..0b4658dd 100644 --- a/src/nxt_source.h +++ b/src/nxt_source.h @@ -22,8 +22,7 @@ typedef void (*nxt_source_handler_t)(void *source_context, nxt_source_hook_t *query); -#define \ -nxt_source_filter(thr, wq, task, next, out) \ +#define nxt_source_filter(thr, wq, task, next, out) \ do { \ if (thr->engine->batch != 0) { \ nxt_thread_work_queue_add(thr, wq, nxt_source_filter_handler, \ diff --git a/src/nxt_sprintf.c b/src/nxt_sprintf.c index 9557b327..9c8e27ed 100644 --- a/src/nxt_sprintf.c +++ b/src/nxt_sprintf.c @@ -90,15 +90,13 @@ static u_char *nxt_number(nxt_sprintf_t *spf, u_char *buf, double n); /* A right way of "f == 0.0". */ -#define \ -nxt_double_is_zero(f) \ +#define nxt_double_is_zero(f) \ (fabs(f) <= FLT_EPSILON) u_char * nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args) { - u_char *p; int d; double f, i; size_t length; @@ -110,12 +108,14 @@ nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args) nxt_msec_t ms; nxt_nsec_t ns; nxt_bool_t sign; + const u_char *p; nxt_sprintf_t spf; nxt_file_name_t *fn; static const u_char hexadecimal[16] = "0123456789abcdef"; static const u_char HEXADECIMAL[16] = "0123456789ABCDEF"; static const u_char nan[] = "[nan]"; + static const u_char null[] = "[null]"; static const u_char infinity[] = "[infinity]"; spf.end = end; @@ -151,15 +151,18 @@ nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args) continue; case 's': - p = va_arg(args, u_char *); + fmt++; - if (nxt_fast_path(p != NULL)) { - while (*p != '\0' && buf < end) { - *buf++ = *p++; - } + p = va_arg(args, const u_char *); + + if (nxt_slow_path(p == NULL)) { + goto copy; + } + + while (*p != '\0' && buf < end) { + *buf++ = *p++; } - fmt++; continue; case '*': @@ -169,11 +172,9 @@ nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args) if (*fmt == 's') { fmt++; - p = va_arg(args, u_char *); + p = va_arg(args, const u_char *); - if (nxt_fast_path(p != NULL)) { - goto copy; - } + goto copy; } continue; @@ -379,13 +380,13 @@ nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args) } if (nxt_slow_path(isnan(f))) { - p = (u_char *) nan; + p = nan; length = nxt_length(nan); goto copy; } else if (nxt_slow_path(isinf(f))) { - p = (u_char *) infinity; + p = infinity; length = nxt_length(infinity); goto copy; @@ -555,7 +556,15 @@ nxt_vsprintf(u_char *buf, u_char *end, const char *fmt, va_list args) copy: - buf = nxt_cpymem(buf, p, nxt_min((size_t) (end - buf), length)); + if (nxt_slow_path(p == NULL)) { + p = null; + length = nxt_length(null); + + } else { + length = nxt_min((size_t) (end - buf), length); + } + + buf = nxt_cpymem(buf, p, length); continue; } diff --git a/src/nxt_string.h b/src/nxt_string.h index 4d565e87..80cdbb59 100644 --- a/src/nxt_string.h +++ b/src/nxt_string.h @@ -8,50 +8,40 @@ #define _NXT_STRING_H_INCLUDED_ -#define \ -nxt_lowcase(c) \ +#define nxt_lowcase(c) \ (u_char) ((c >= 'A' && c <= 'Z') ? c | 0x20 : c) -#define \ -nxt_upcase(c) \ +#define nxt_upcase(c) \ (u_char) ((c >= 'a' && c <= 'z') ? c & ~0x20 : c) -#define \ -nxt_isdigit(c) \ +#define nxt_isdigit(c) \ ((u_char) ((c) - '0') <= 9) -#define \ -nxt_strtod(s, endptr) \ +#define nxt_strtod(s, endptr) \ strtod((char *) s, (char **) endptr) -#define \ -nxt_strlen(s) \ +#define nxt_strlen(s) \ strlen((char *) s) -#define \ -nxt_strdup(s) \ +#define nxt_strdup(s) \ strdup((char *) s) -#define \ -nxt_strchr(buf, delim) \ +#define nxt_strchr(buf, delim) \ (u_char *) strchr((char *) buf, delim) -#define \ -nxt_memzero(buf, length) \ +#define nxt_memzero(buf, length) \ (void) memset(buf, 0, length) -#define \ -nxt_memset(buf, c, length) \ +#define nxt_memset(buf, c, length) \ (void) memset(buf, c, length) -#define \ -nxt_memcpy(dst, src, length) \ +#define nxt_memcpy(dst, src, length) \ (void) memcpy(dst, src, length) @@ -72,28 +62,23 @@ nxt_cpymem(void *dst, const void *src, size_t length) } -#define \ -nxt_memmove(dst, src, length) \ +#define nxt_memmove(dst, src, length) \ (void) memmove(dst, src, length) -#define \ -nxt_memcmp(s1, s2, length) \ +#define nxt_memcmp(s1, s2, length) \ memcmp((char *) s1, (char *) s2, length) -#define \ -nxt_memchr(s, c, length) \ +#define nxt_memchr(s, c, length) \ memchr((char *) s, c, length) -#define \ -nxt_strcmp(s1, s2) \ +#define nxt_strcmp(s1, s2) \ strcmp((char *) s1, (char *) s2) -#define \ -nxt_strncmp(s1, s2, length) \ +#define nxt_strncmp(s1, s2, length) \ strncmp((char *) s1, (char *) s2, length) @@ -125,16 +110,14 @@ typedef struct { #define nxt_null_string { 0, NULL } -#define \ -nxt_str_set(str, text) \ +#define nxt_str_set(str, text) \ do { \ (str)->length = nxt_length(text); \ (str)->start = (u_char *) text; \ } while (0) -#define \ -nxt_str_null(str) \ +#define nxt_str_null(str) \ do { \ (str)->length = 0; \ (str)->start = NULL; \ @@ -147,35 +130,29 @@ NXT_EXPORT nxt_str_t *nxt_str_dup(nxt_mp_t *mp, nxt_str_t *dst, NXT_EXPORT char *nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src); -#define \ -nxt_strstr_eq(s1, s2) \ +#define nxt_strstr_eq(s1, s2) \ (((s1)->length == (s2)->length) \ && (nxt_memcmp((s1)->start, (s2)->start, (s1)->length) == 0)) -#define \ -nxt_strcasestr_eq(s1, s2) \ +#define nxt_strcasestr_eq(s1, s2) \ (((s1)->length == (s2)->length) \ && (nxt_memcasecmp((s1)->start, (s2)->start, (s1)->length) == 0)) -#define \ -nxt_str_eq(s, p, _length) \ +#define nxt_str_eq(s, p, _length) \ (((s)->length == _length) && (nxt_memcmp((s)->start, p, _length) == 0)) -#define \ -nxt_str_start(s, p, _length) \ +#define nxt_str_start(s, p, _length) \ (((s)->length >= _length) && (nxt_memcmp((s)->start, p, _length) == 0)) -#define \ -nxt_strchr_eq(s, c) \ +#define nxt_strchr_eq(s, c) \ (((s)->length == 1) && ((s)->start[0] == c)) -#define \ -nxt_strchr_start(s, c) \ +#define nxt_strchr_start(s, c) \ (((s)->length != 0) && ((s)->start[0] == c)) diff --git a/src/nxt_thread.h b/src/nxt_thread.h index 2ebc331d..53b2d8c0 100644 --- a/src/nxt_thread.h +++ b/src/nxt_thread.h @@ -30,19 +30,15 @@ #if (NXT_HAVE_THREAD_STORAGE_CLASS) -#define \ -nxt_thread_extern_data(type, tsd) \ +#define nxt_thread_extern_data(type, tsd) \ NXT_EXPORT extern __thread type tsd -#define \ -nxt_thread_declare_data(type, tsd) \ +#define nxt_thread_declare_data(type, tsd) \ __thread type tsd -#define \ -nxt_thread_init_data(tsd) +#define nxt_thread_init_data(tsd) -#define \ -nxt_thread_get_data(tsd) \ +#define nxt_thread_get_data(tsd) \ &tsd @@ -67,18 +63,15 @@ typedef struct { } nxt_thread_specific_data_t[1]; -#define \ -nxt_thread_extern_data(type, tsd) \ +#define nxt_thread_extern_data(type, tsd) \ NXT_EXPORT extern nxt_thread_specific_data_t tsd -#define \ -nxt_thread_declare_data(type, tsd) \ +#define nxt_thread_declare_data(type, tsd) \ nxt_thread_specific_data_t tsd = { { (nxt_atomic_int_t) -1, sizeof(type) } } NXT_EXPORT void nxt_thread_init_data(nxt_thread_specific_data_t tsd); -#define \ -nxt_thread_get_data(tsd) \ +#define nxt_thread_get_data(tsd) \ pthread_getspecific((pthread_key_t) tsd->key) #endif @@ -101,8 +94,7 @@ NXT_EXPORT void nxt_thread_cancel(nxt_thread_handle_t handle); NXT_EXPORT void nxt_thread_wait(nxt_thread_handle_t handle); -#define \ -nxt_thread_handle() \ +#define nxt_thread_handle() \ pthread_self() @@ -125,18 +117,15 @@ NXT_EXPORT nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond, #if (NXT_HAVE_PTHREAD_YIELD) -#define \ -nxt_thread_yield() \ +#define nxt_thread_yield() \ pthread_yield() #elif (NXT_HAVE_PTHREAD_YIELD_NP) -#define \ -nxt_thread_yield() \ +#define nxt_thread_yield() \ pthread_yield_np() #else -#define \ -nxt_thread_yield() \ +#define nxt_thread_yield() \ nxt_sched_yield() #endif diff --git a/src/nxt_thread_id.h b/src/nxt_thread_id.h index 3263a47a..764c9934 100644 --- a/src/nxt_thread_id.h +++ b/src/nxt_thread_id.h @@ -179,12 +179,10 @@ NXT_EXPORT nxt_tid_t nxt_thread_tid(nxt_thread_t *thr); typedef pthread_t nxt_thread_handle_t; -#define \ -nxt_thread_handle_clear(th) \ +#define nxt_thread_handle_clear(th) \ th = (pthread_t) 0 -#define \ -nxt_thread_handle_equal(th0, th1) \ +#define nxt_thread_handle_equal(th0, th1) \ pthread_equal(th0, th1) diff --git a/src/nxt_thread_time.h b/src/nxt_thread_time.h index 05ecd938..77eaea49 100644 --- a/src/nxt_thread_time.h +++ b/src/nxt_thread_time.h @@ -70,21 +70,18 @@ NXT_EXPORT u_char *nxt_thread_time_string(nxt_thread_t *thr, void nxt_time_thread_start(nxt_msec_t interval); -#define \ -nxt_thread_monotonic_time(thr) \ +#define nxt_thread_monotonic_time(thr) \ (thr)->time.now.monotonic #if (NXT_DEBUG) -#define \ -nxt_thread_time_debug_update(thr) \ +#define nxt_thread_time_debug_update(thr) \ nxt_thread_time_update(thr) #else -#define \ -nxt_thread_time_debug_update(thr) +#define nxt_thread_time_debug_update(thr) #endif diff --git a/src/nxt_time.h b/src/nxt_time.h index d6785eb2..9617b3d4 100644 --- a/src/nxt_time.h +++ b/src/nxt_time.h @@ -74,20 +74,17 @@ NXT_EXPORT void nxt_timezone_update(void); #if (NXT_HAVE_TM_GMTOFF) -#define \ -nxt_timezone(tm) \ +#define nxt_timezone(tm) \ ((tm)->tm_gmtoff) #elif (NXT_HAVE_ALTZONE) -#define \ -nxt_timezone(tm) \ +#define nxt_timezone(tm) \ (-(((tm)->tm_isdst > 0) ? altzone : timezone)) #else -#define \ -nxt_timezone(tm) \ +#define nxt_timezone(tm) \ (-(((tm)->tm_isdst > 0) ? timezone + 3600 : timezone)) #endif @@ -103,8 +100,7 @@ typedef int32_t nxt_msec_int_t; * every 49 days. This signed subtraction takes into account that overflow. * "nxt_msec_diff(m1, m2) < 0" means that m1 is lesser than m2. */ -#define \ -nxt_msec_diff(m1, m2) \ +#define nxt_msec_diff(m1, m2) \ ((int32_t) ((m1) - (m2))) diff --git a/src/nxt_time_parse.c b/src/nxt_time_parse.c index 5a32b213..94c43289 100644 --- a/src/nxt_time_parse.c +++ b/src/nxt_time_parse.c @@ -282,9 +282,9 @@ nxt_time_parse(const u_char *p, size_t len) days = days - 719527 + 31 + 28; s = (uint64_t) days * 86400 - + (nxt_uint_t) hour * 3600 - + (nxt_uint_t) min * 60 - + (nxt_uint_t) sec; + + (nxt_uint_t) hour * 3600 + + (nxt_uint_t) min * 60 + + (nxt_uint_t) sec; #if (NXT_TIME_T_SIZE <= 4) diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 135c06ed..32bb07ab 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -55,6 +55,7 @@ nxt_inline void nxt_unit_mmap_buf_insert_tail(nxt_unit_mmap_buf_t **prev, nxt_inline void nxt_unit_mmap_buf_unlink(nxt_unit_mmap_buf_t *mmap_buf); static int nxt_unit_read_env(nxt_unit_port_t *ready_port, nxt_unit_port_t *router_port, nxt_unit_port_t *read_port, + int *shared_port_fd, int *shared_queue_fd, int *log_fd, uint32_t *stream, uint32_t *shm_limit, uint32_t *request_limit); static int nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream, @@ -424,12 +425,12 @@ static pid_t nxt_unit_pid; nxt_unit_ctx_t * nxt_unit_init(nxt_unit_init_t *init) { - int rc, queue_fd; + int rc, queue_fd, shared_queue_fd; void *mem; uint32_t ready_stream, shm_limit, request_limit; nxt_unit_ctx_t *ctx; nxt_unit_impl_t *lib; - nxt_unit_port_t ready_port, router_port, read_port; + nxt_unit_port_t ready_port, router_port, read_port, shared_port; nxt_unit_pid = getpid(); @@ -440,6 +441,8 @@ nxt_unit_init(nxt_unit_init_t *init) queue_fd = -1; mem = MAP_FAILED; + shared_port.out_fd = -1; + shared_port.data = NULL; if (init->ready_port.id.pid != 0 && init->ready_stream != 0 @@ -458,8 +461,12 @@ nxt_unit_init(nxt_unit_init_t *init) nxt_unit_port_id_init(&read_port.id, read_port.id.pid, read_port.id.id); + shared_port.in_fd = init->shared_port_fd; + shared_queue_fd = init->shared_queue_fd; + } else { rc = nxt_unit_read_env(&ready_port, &router_port, &read_port, + &shared_port.in_fd, &shared_queue_fd, &lib->log_fd, &ready_stream, &shm_limit, &request_limit); if (nxt_slow_path(rc != NXT_UNIT_OK)) { @@ -525,6 +532,27 @@ nxt_unit_init(nxt_unit_init_t *init) goto fail; } + nxt_unit_port_id_init(&shared_port.id, read_port.id.pid, + NXT_UNIT_SHARED_PORT_ID); + + mem = mmap(NULL, sizeof(nxt_app_queue_t), PROT_READ | PROT_WRITE, + MAP_SHARED, shared_queue_fd, 0); + if (nxt_slow_path(mem == MAP_FAILED)) { + nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", shared_queue_fd, + strerror(errno), errno); + + goto fail; + } + + nxt_unit_close(shared_queue_fd); + + lib->shared_port = nxt_unit_add_port(ctx, &shared_port, mem); + if (nxt_slow_path(lib->shared_port == NULL)) { + nxt_unit_alert(NULL, "failed to add shared_port"); + + goto fail; + } + rc = nxt_unit_ready(ctx, ready_port.out_fd, ready_stream, queue_fd); if (nxt_slow_path(rc != NXT_UNIT_OK)) { nxt_unit_alert(NULL, "failed to send READY message"); @@ -799,7 +827,8 @@ nxt_unit_mmap_buf_unlink(nxt_unit_mmap_buf_t *mmap_buf) static int nxt_unit_read_env(nxt_unit_port_t *ready_port, nxt_unit_port_t *router_port, - nxt_unit_port_t *read_port, int *log_fd, uint32_t *stream, + nxt_unit_port_t *read_port, int *shared_port_fd, int *shared_queue_fd, + int *log_fd, uint32_t *stream, uint32_t *shm_limit, uint32_t *request_limit) { int rc; @@ -845,11 +874,13 @@ nxt_unit_read_env(nxt_unit_port_t *ready_port, nxt_unit_port_t *router_port, "%"PRId64",%"PRIu32",%d;" "%"PRId64",%"PRIu32",%d;" "%"PRId64",%"PRIu32",%d,%d;" + "%d,%d;" "%d,%"PRIu32",%"PRIu32, &ready_stream, &ready_pid, &ready_id, &ready_fd, &router_pid, &router_id, &router_fd, &read_pid, &read_id, &read_in_fd, &read_out_fd, + shared_port_fd, shared_queue_fd, log_fd, shm_limit, request_limit); if (nxt_slow_path(rc == EOF)) { @@ -859,9 +890,9 @@ nxt_unit_read_env(nxt_unit_port_t *ready_port, nxt_unit_port_t *router_port, return NXT_UNIT_ERROR; } - if (nxt_slow_path(rc != 14)) { + if (nxt_slow_path(rc != 16)) { nxt_unit_alert(NULL, "invalid number of variables in %s env: " - "found %d of %d in %s", NXT_UNIT_INIT_ENV, rc, 14, vars); + "found %d of %d in %s", NXT_UNIT_INIT_ENV, rc, 16, vars); return NXT_UNIT_ERROR; } @@ -1137,7 +1168,6 @@ static int nxt_unit_process_new_port(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg) { void *mem; - nxt_unit_impl_t *lib; nxt_unit_port_t new_port, *port; nxt_port_msg_new_port_t *new_port_msg; @@ -1162,33 +1192,17 @@ nxt_unit_process_new_port(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg) recv_msg->stream, (int) new_port_msg->pid, (int) new_port_msg->id, recv_msg->fd[0], recv_msg->fd[1]); - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); - - if (new_port_msg->id == NXT_UNIT_SHARED_PORT_ID) { - nxt_unit_port_id_init(&new_port.id, lib->pid, new_port_msg->id); - - new_port.in_fd = recv_msg->fd[0]; - new_port.out_fd = -1; - - mem = mmap(NULL, sizeof(nxt_app_queue_t), PROT_READ | PROT_WRITE, - MAP_SHARED, recv_msg->fd[1], 0); - - } else { - if (nxt_slow_path(nxt_unit_fd_blocking(recv_msg->fd[0]) - != NXT_UNIT_OK)) - { - return NXT_UNIT_ERROR; - } + if (nxt_slow_path(nxt_unit_fd_blocking(recv_msg->fd[0]) != NXT_UNIT_OK)) { + return NXT_UNIT_ERROR; + } - nxt_unit_port_id_init(&new_port.id, new_port_msg->pid, - new_port_msg->id); + nxt_unit_port_id_init(&new_port.id, new_port_msg->pid, new_port_msg->id); - new_port.in_fd = -1; - new_port.out_fd = recv_msg->fd[0]; + new_port.in_fd = -1; + new_port.out_fd = recv_msg->fd[0]; - mem = mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, - MAP_SHARED, recv_msg->fd[1], 0); - } + mem = mmap(NULL, sizeof(nxt_port_queue_t), PROT_READ | PROT_WRITE, + MAP_SHARED, recv_msg->fd[1], 0); if (nxt_slow_path(mem == MAP_FAILED)) { nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", recv_msg->fd[1], @@ -1206,12 +1220,6 @@ nxt_unit_process_new_port(nxt_unit_ctx_t *ctx, nxt_unit_recv_msg_t *recv_msg) return NXT_UNIT_ERROR; } - if (new_port_msg->id == NXT_UNIT_SHARED_PORT_ID) { - lib->shared_port = port; - - return nxt_unit_ctx_ready(ctx); - } - nxt_unit_port_release(port); return NXT_UNIT_OK; @@ -5106,9 +5114,9 @@ nxt_unit_ctx_alloc(nxt_unit_ctx_t *ctx, void *data) rc = nxt_unit_ctx_init(lib, new_ctx, data); if (nxt_slow_path(rc != NXT_UNIT_OK)) { - nxt_unit_free(ctx, new_ctx); + nxt_unit_free(ctx, new_ctx); - return NULL; + return NULL; } queue_fd = -1; diff --git a/src/nxt_unit.h b/src/nxt_unit.h index 1b5280af..35f9fa55 100644 --- a/src/nxt_unit.h +++ b/src/nxt_unit.h @@ -176,6 +176,8 @@ struct nxt_unit_init_s { uint32_t ready_stream; nxt_unit_port_t router_port; nxt_unit_port_t read_port; + int shared_port_fd; + int shared_queue_fd; int log_fd; }; diff --git a/src/nxt_unix.h b/src/nxt_unix.h index 393f61d9..d8eaabc3 100644 --- a/src/nxt_unix.h +++ b/src/nxt_unix.h @@ -275,23 +275,19 @@ typedef struct iovec nxt_iobuf_t; -#define \ -nxt_iobuf_data(iob) \ +#define nxt_iobuf_data(iob) \ (iob)->iov_base -#define \ -nxt_iobuf_size(iob) \ +#define nxt_iobuf_size(iob) \ (iob)->iov_len -#define \ -nxt_iobuf_set(iob, p, size) \ +#define nxt_iobuf_set(iob, p, size) \ do { \ (iob)->iov_base = (void *) p; \ (iob)->iov_len = size; \ } while (0) -#define \ -nxt_iobuf_add(iob, size) \ +#define nxt_iobuf_add(iob, size) \ (iob)->iov_len += size diff --git a/src/nxt_var.c b/src/nxt_var.c index 60650ef4..0a722d17 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -627,7 +627,8 @@ nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query) nxt_array_reset(&query->parts); - nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, val[i].value); + nxt_debug(task, "var: \"%*s\" -> \"%V\"", var->length, src, + val[i].value); } done: diff --git a/src/nxt_vector.h b/src/nxt_vector.h index e8836dbf..dcac53d4 100644 --- a/src/nxt_vector.h +++ b/src/nxt_vector.h @@ -41,19 +41,16 @@ NXT_EXPORT void *nxt_vector_zero_add(nxt_vector_t *vector, NXT_EXPORT void nxt_vector_remove(nxt_vector_t *vector, void *item); -#define \ -nxt_vector_last(vector) \ +#define nxt_vector_last(vector) \ nxt_pointer_to((vector)->start, \ (vector)->item_size * ((vector)->items - 1)) -#define \ -nxt_vector_reset(vector) \ +#define nxt_vector_reset(vector) \ (vector)->items = 0; -#define \ -nxt_vector_is_empty(vector) \ +#define nxt_vector_is_empty(vector) \ ((vector)->items == 0) diff --git a/src/nxt_work_queue.h b/src/nxt_work_queue.h index 6c2d6c23..b6aa4d4c 100644 --- a/src/nxt_work_queue.h +++ b/src/nxt_work_queue.h @@ -16,12 +16,12 @@ struct nxt_task_s { uint32_t ident; nxt_work_t *next_work; - /* TODO: exception_handler, prev/next task, subtasks. */ + /* TODO: exception_handler, prev/next task, subtasks. */ }; #define nxt_task_next_ident() \ - ((uint32_t) nxt_atomic_fetch_add(&nxt_task_ident, 1) & 0x3FFFFFFF) + ((uint32_t) nxt_atomic_fetch_add(&nxt_task_ident, 1) & 0x3FFFFFFF) /* @@ -109,8 +109,7 @@ NXT_EXPORT void nxt_work_queue_thread_adopt(nxt_work_queue_t *wq); #else -#define \ -nxt_work_queue_name(_wq, _name) +#define nxt_work_queue_name(_wq, _name) #define nxt_work_queue_thread_adopt(_wq) diff --git a/src/perl/nxt_perl_psgi.c b/src/perl/nxt_perl_psgi.c index 02555c96..08a6f29e 100644 --- a/src/perl/nxt_perl_psgi.c +++ b/src/perl/nxt_perl_psgi.c @@ -28,19 +28,15 @@ typedef struct { } nxt_perl_psgi_ctx_t; -static long nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl, +static SSize_t nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); -static long nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, +static SSize_t nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); -static long nxt_perl_psgi_io_input_flush(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg); -static long nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, +static SSize_t nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); -static long nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl, +static SSize_t nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); -static long nxt_perl_psgi_io_error_flush(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg); /* static void nxt_perl_psgi_xs_core_global_changes(PerlInterpreter *my_perl, @@ -57,10 +53,8 @@ static SV *nxt_perl_psgi_call_method(PerlInterpreter *my_perl, SV *obj, /* For currect load XS modules */ EXTERN_C void boot_DynaLoader(pTHX_ CV *cv); -static nxt_int_t nxt_perl_psgi_io_input_init(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg); -static nxt_int_t nxt_perl_psgi_io_error_init(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg); +static int nxt_perl_psgi_io_init(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, const char *mode, void *req); static int nxt_perl_psgi_ctx_init(const char *script, nxt_perl_psgi_ctx_t *pctx); @@ -125,20 +119,26 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = { nxt_perl_psgi_start, }; +const nxt_perl_psgi_io_tab_t nxt_perl_psgi_io_tab_input = { + .read = nxt_perl_psgi_io_input_read, + .write = nxt_perl_psgi_io_input_write, +}; + +const nxt_perl_psgi_io_tab_t nxt_perl_psgi_io_tab_error = { + .read = nxt_perl_psgi_io_error_read, + .write = nxt_perl_psgi_io_error_write, +}; -static long + +static SSize_t nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length) { - nxt_perl_psgi_ctx_t *pctx; - - pctx = arg->pctx; - - return nxt_unit_request_read(pctx->req, vbuf, length); + return nxt_unit_request_read(arg->req, vbuf, length); } -static long +static SSize_t nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length) { @@ -146,15 +146,7 @@ nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, } -static long -nxt_perl_psgi_io_input_flush(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg) -{ - return 0; -} - - -static long +static SSize_t nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length) { @@ -162,25 +154,13 @@ nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, } -static long +static SSize_t nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length) { - nxt_perl_psgi_ctx_t *pctx; - - pctx = arg->pctx; - - nxt_unit_req_error(pctx->req, "Perl: %s", (const char*) vbuf); - - return (long) length; -} - + nxt_unit_req_error(arg->req, "Perl: %s", (const char*) vbuf); -static long -nxt_perl_psgi_io_error_flush(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg) -{ - return 0; + return (SSize_t) length; } @@ -461,70 +441,49 @@ nxt_perl_psgi_module_create(const char *script) } -static nxt_int_t -nxt_perl_psgi_io_input_init(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg) +static int +nxt_perl_psgi_io_init(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, const char *mode, void *req) { SV *io; PerlIO *fp; - fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg, "r"); - - if (nxt_slow_path(fp == NULL)) { - return NXT_ERROR; - } + if (arg->io == NULL) { + fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg->rv, mode); + if (nxt_slow_path(fp == NULL)) { + return NXT_UNIT_ERROR; + } - io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp); + io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp); + if (nxt_slow_path(io == NULL)) { + nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp); + return NXT_UNIT_ERROR; + } - if (nxt_slow_path(io == NULL)) { - nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp); - return NXT_ERROR; + arg->io = io; + arg->fp = fp; } - arg->io = io; - arg->fp = fp; - arg->flush = nxt_perl_psgi_io_input_flush; - arg->read = nxt_perl_psgi_io_input_read; - arg->write = nxt_perl_psgi_io_input_write; + arg->req = req; - return NXT_OK; + return NXT_UNIT_OK; } -static nxt_int_t -nxt_perl_psgi_io_error_init(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg) +static void +nxt_perl_psgi_io_release(PerlInterpreter *my_perl, nxt_perl_psgi_io_arg_t *arg) { - SV *io; - PerlIO *fp; - - fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg, "w"); - - if (nxt_slow_path(fp == NULL)) { - return NXT_ERROR; + if (arg->io != NULL) { + SvREFCNT_dec(arg->io); + arg->io = NULL; } - - io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp); - - if (nxt_slow_path(io == NULL)) { - nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp); - return NXT_ERROR; - } - - arg->io = io; - arg->fp = fp; - arg->flush = nxt_perl_psgi_io_error_flush; - arg->read = nxt_perl_psgi_io_error_read; - arg->write = nxt_perl_psgi_io_error_write; - - return NXT_OK; } static int nxt_perl_psgi_ctx_init(const char *script, nxt_perl_psgi_ctx_t *pctx) { - int status; + int status, res; char *run_module; PerlInterpreter *my_perl; @@ -577,19 +536,27 @@ nxt_perl_psgi_ctx_init(const char *script, nxt_perl_psgi_ctx_t *pctx) goto fail; } - pctx->arg_input.pctx = pctx; + pctx->arg_input.rv = newSV_type(SVt_RV); + sv_setptrref(pctx->arg_input.rv, &pctx->arg_input); + SvSETMAGIC(pctx->arg_input.rv); - status = nxt_perl_psgi_io_input_init(my_perl, &pctx->arg_input); - if (nxt_slow_path(status != NXT_OK)) { + pctx->arg_input.io_tab = &nxt_perl_psgi_io_tab_input; + + res = nxt_perl_psgi_io_init(my_perl, &pctx->arg_input, "r", NULL); + if (nxt_slow_path(res != NXT_UNIT_OK)) { nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.input"); goto fail; } - pctx->arg_error.pctx = pctx; + pctx->arg_error.rv = newSV_type(SVt_RV); + sv_setptrref(pctx->arg_error.rv, &pctx->arg_error); + SvSETMAGIC(pctx->arg_error.rv); + + pctx->arg_error.io_tab = &nxt_perl_psgi_io_tab_error; - status = nxt_perl_psgi_io_error_init(my_perl, &pctx->arg_error); - if (nxt_slow_path(status != NXT_OK)) { - nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.errors"); + res = nxt_perl_psgi_io_init(my_perl, &pctx->arg_error, "w", NULL); + if (nxt_slow_path(res != NXT_UNIT_OK)) { + nxt_unit_alert(NULL, "PSGI: Failed to init io.psgi.error"); goto fail; } @@ -607,6 +574,9 @@ nxt_perl_psgi_ctx_init(const char *script, nxt_perl_psgi_ctx_t *pctx) fail: + nxt_perl_psgi_io_release(my_perl, &pctx->arg_input); + nxt_perl_psgi_io_release(my_perl, &pctx->arg_error); + if (run_module != NULL) { nxt_unit_free(NULL, run_module); } @@ -614,6 +584,8 @@ fail: perl_destruct(my_perl); perl_free(my_perl); + pctx->my_perl = NULL; + return NXT_UNIT_ERROR; } @@ -640,7 +612,7 @@ nxt_perl_psgi_env_create(PerlInterpreter *my_perl, do { \ if (nxt_slow_path((FNS) != NXT_UNIT_OK)) \ goto fail; \ - } while (0) + } while (0) #define NL(S) (S), sizeof(S)-1 @@ -672,21 +644,25 @@ nxt_perl_psgi_env_create(PerlInterpreter *my_perl, r->tls ? newSVpv("https", 5) : newSVpv("http", 4))); + RC(nxt_perl_psgi_io_init(my_perl, &pctx->arg_input, "r", req)); RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.input"), - SvREFCNT_inc(pctx->arg_input.io))); + SvREFCNT_inc(pctx->arg_input.io))); + + RC(nxt_perl_psgi_io_init(my_perl, &pctx->arg_error, "w", req)); RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.errors"), - SvREFCNT_inc(pctx->arg_error.io))); + SvREFCNT_inc(pctx->arg_error.io))); + RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.multithread"), - nxt_perl_psgi_ctxs != NULL - ? &PL_sv_yes : &PL_sv_no)); + nxt_perl_psgi_ctxs != NULL + ? &PL_sv_yes : &PL_sv_no)); RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.multiprocess"), - &PL_sv_yes)); + &PL_sv_yes)); RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.run_once"), - &PL_sv_no)); + &PL_sv_no)); RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.nonblocking"), - &PL_sv_no)); + &PL_sv_no)); RC(nxt_perl_psgi_add_value(my_perl, hash_env, NL("psgi.streaming"), - &PL_sv_yes)); + &PL_sv_yes)); RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("QUERY_STRING"), &r->query, r->query_length)); @@ -1447,11 +1423,11 @@ nxt_perl_psgi_ctx_free(nxt_perl_psgi_ctx_t *pctx) PERL_SET_CONTEXT(my_perl); - nxt_perl_psgi_layer_stream_io_destroy(aTHX_ pctx->arg_input.io); - nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ pctx->arg_input.fp); + SvREFCNT_dec(pctx->arg_input.rv); + SvREFCNT_dec(pctx->arg_error.rv); - nxt_perl_psgi_layer_stream_io_destroy(aTHX_ pctx->arg_error.io); - nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ pctx->arg_error.fp); + nxt_perl_psgi_io_release(my_perl, &pctx->arg_input); + nxt_perl_psgi_io_release(my_perl, &pctx->arg_error); perl_destruct(my_perl); perl_free(my_perl); diff --git a/src/perl/nxt_perl_psgi_layer.c b/src/perl/nxt_perl_psgi_layer.c index f77453e9..303e5f27 100644 --- a/src/perl/nxt_perl_psgi_layer.c +++ b/src/perl/nxt_perl_psgi_layer.c @@ -93,11 +93,9 @@ nxt_perl_psgi_layer_stream_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); if (arg != NULL && SvOK(arg)) { - unit_stream->var = arg; + unit_stream->var = SvREFCNT_inc(arg); } - SvSETMAGIC(unit_stream->var); - return PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab); } @@ -105,11 +103,17 @@ nxt_perl_psgi_layer_stream_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, static IV nxt_perl_psgi_layer_stream_popped(pTHX_ PerlIO *f) { + nxt_perl_psgi_io_arg_t *arg; nxt_perl_psgi_layer_stream_t *unit_stream; unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); if (unit_stream->var != NULL) { + arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var)); + + arg->io = NULL; + arg->fp = NULL; + SvREFCNT_dec(unit_stream->var); unit_stream->var = Nullsv; } @@ -181,9 +185,6 @@ nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) return 0; } - unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); - arg = (nxt_perl_psgi_io_arg_t *) (intptr_t) SvIV(SvRV(unit_stream->var)); - if ((PerlIOBase(f)->flags & PERLIO_F_CANREAD) == 0) { PerlIOBase(f)->flags |= PERLIO_F_ERROR; @@ -192,7 +193,10 @@ nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) return 0; } - return (SSize_t) arg->read(PERL_GET_CONTEXT, arg, vbuf, count); + unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); + arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var)); + + return arg->io_tab->read(PERL_GET_CONTEXT, arg, vbuf, count); } @@ -204,13 +208,10 @@ nxt_perl_psgi_layer_stream_write(pTHX_ PerlIO *f, nxt_perl_psgi_layer_stream_t *unit_stream; if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) { - unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); + arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var)); - arg = (nxt_perl_psgi_io_arg_t *) - (intptr_t) SvIV(SvRV(unit_stream->var)); - - return (SSize_t) arg->write(PERL_GET_CONTEXT, arg, vbuf, count); + return arg->io_tab->write(PERL_GET_CONTEXT, arg, vbuf, count); } return 0; @@ -244,13 +245,7 @@ nxt_perl_psgi_layer_stream_fill(pTHX_ PerlIO *f) static IV nxt_perl_psgi_layer_stream_flush(pTHX_ PerlIO *f) { - nxt_perl_psgi_io_arg_t *arg; - nxt_perl_psgi_layer_stream_t *unit_stream; - - unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t); - arg = (nxt_perl_psgi_io_arg_t *) (intptr_t) SvIV(SvRV(unit_stream->var)); - - return (IV) arg->flush(PERL_GET_CONTEXT, arg); + return 0; } @@ -346,29 +341,11 @@ nxt_perl_psgi_layer_stream_init(pTHX) PerlIO * -nxt_perl_psgi_layer_stream_fp_create(pTHX_ nxt_perl_psgi_io_arg_t *arg, +nxt_perl_psgi_layer_stream_fp_create(pTHX_ SV *arg_rv, const char *mode) { - SV *arg_rv; - PerlIO *fp; - - arg_rv = newSV_type(SVt_RV); - - if (arg_rv == NULL) { - return NULL; - } - - sv_setptrref(arg_rv, arg); - - fp = PerlIO_openn(aTHX_ "NGINX_Unit_PSGI_Layer_Stream", - mode, 0, 0, 0, NULL, 1, &arg_rv); - - if (fp == NULL) { - SvREFCNT_dec(arg_rv); - return NULL; - } - - return fp; + return PerlIO_openn(aTHX_ "NGINX_Unit_PSGI_Layer_Stream", + mode, 0, 0, 0, NULL, 1, &arg_rv); } @@ -403,10 +380,3 @@ nxt_perl_psgi_layer_stream_io_create(pTHX_ PerlIO *fp) return rvio; } - - -void -nxt_perl_psgi_layer_stream_io_destroy(pTHX_ SV *rvio) -{ - SvREFCNT_dec(rvio); -} diff --git a/src/perl/nxt_perl_psgi_layer.h b/src/perl/nxt_perl_psgi_layer.h index af18ad0d..0972d66f 100644 --- a/src/perl/nxt_perl_psgi_layer.h +++ b/src/perl/nxt_perl_psgi_layer.h @@ -14,35 +14,35 @@ #include <perliol.h> +typedef struct nxt_perl_psgi_io_tab_s nxt_perl_psgi_io_tab_t; typedef struct nxt_perl_psgi_io_arg_s nxt_perl_psgi_io_arg_t; -typedef long (*nxt_perl_psgi_io_read_f)(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); -typedef long (*nxt_perl_psgi_io_write_f)(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); -typedef long (*nxt_perl_psgi_io_arg_f)(PerlInterpreter *my_perl, - nxt_perl_psgi_io_arg_t *arg); + +struct nxt_perl_psgi_io_tab_s { + SSize_t (*read)(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); + SSize_t (*write)(PerlInterpreter *my_perl, + nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); +}; struct nxt_perl_psgi_io_arg_s { - SV *io; - PerlIO *fp; + SV *rv; + SV *io; + PerlIO *fp; - nxt_perl_psgi_io_arg_f flush; - nxt_perl_psgi_io_read_f read; - nxt_perl_psgi_io_write_f write; + const nxt_perl_psgi_io_tab_t *io_tab; - void *pctx; + void *req; }; void nxt_perl_psgi_layer_stream_init(pTHX); -PerlIO *nxt_perl_psgi_layer_stream_fp_create(pTHX_ nxt_perl_psgi_io_arg_t *arg, +PerlIO *nxt_perl_psgi_layer_stream_fp_create(pTHX_ SV *arg_rv, const char *mode); void nxt_perl_psgi_layer_stream_fp_destroy(pTHX_ PerlIO *io); SV *nxt_perl_psgi_layer_stream_io_create(pTHX_ PerlIO *fp); -void nxt_perl_psgi_layer_stream_io_destroy(pTHX_ SV *rvio); #endif /* _NXT_PERL_PSGI_LAYER_H_INCLUDED_ */ diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 8687c869..188c4920 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -411,15 +411,8 @@ nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value) /* sys is a Borrowed reference. */ - if (nxt_conf_type(value) == NXT_CONF_STRING) { - n = 0; - goto value_is_string; - } - - /* NXT_CONF_ARRAY */ array = value; - - n = nxt_conf_array_elements_count(array); + n = nxt_conf_array_elements_count_or_1(array); while (n != 0) { n--; @@ -430,9 +423,7 @@ nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value) * specified in the "path" option. */ - value = nxt_conf_get_array_element(array, n); - - value_is_string: + value = nxt_conf_get_array_element_or_itself(array, n); nxt_conf_get_string(value, &str); diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 354e3a81..91af8f4b 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -117,15 +117,20 @@ nxt_python_asgi_get_func(PyObject *obj) if (PyMethod_Check(call)) { obj = PyMethod_GET_FUNCTION(call); - Py_INCREF(obj); - Py_DECREF(call); + if (PyFunction_Check(obj)) { + Py_INCREF(obj); - return obj; + } else { + obj = NULL; + } + + } else { + obj = NULL; } Py_DECREF(call); - return NULL; + return obj; } @@ -161,8 +166,10 @@ nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto) for (i = 0; i < nxt_py_targets->count; i++) { func = nxt_python_asgi_get_func(nxt_py_targets->target[i].application); if (nxt_slow_path(func == NULL)) { - nxt_unit_alert(NULL, "Python cannot find function for callable"); - return NXT_UNIT_ERROR; + nxt_unit_debug(NULL, "asgi: cannot find function for callable, " + "unable to check for legacy mode (#%d)", + (int) i); + continue; } code = (PyCodeObject *) PyFunction_GET_CODE(func); diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 62498127..8f4afd35 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -29,6 +29,7 @@ typedef struct { static nxt_int_t nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data); static VALUE nxt_ruby_init_basic(VALUE arg); +static VALUE nxt_ruby_script_basename(nxt_str_t *script); static VALUE nxt_ruby_hook_procs_load(VALUE path); static VALUE nxt_ruby_hook_register(VALUE arg); @@ -49,7 +50,7 @@ static void *nxt_ruby_thread_create_gvl(void *rctx); static VALUE nxt_ruby_thread_func(VALUE arg); static void *nxt_ruby_unit_run(void *ctx); static void nxt_ruby_ubf(void *ctx); -static int nxt_ruby_init_threads(nxt_ruby_app_conf_t *c); +static int nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c); static void nxt_ruby_join_threads(nxt_unit_ctx_t *ctx, nxt_ruby_app_conf_t *c); @@ -260,7 +261,7 @@ static nxt_int_t nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) { int state, rc; - VALUE res, path; + VALUE res, path, script; nxt_ruby_ctx_t ruby_ctx; nxt_unit_ctx_t *unit_ctx; nxt_unit_init_t ruby_unit_init; @@ -282,7 +283,10 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) ruby_options(2, argv); ruby_script("NGINX_Unit"); + script = nxt_ruby_script_basename(&c->script); + ruby_ctx.env = Qnil; + ruby_ctx.script = script; ruby_ctx.io_input = Qnil; ruby_ctx.io_error = Qnil; ruby_ctx.thread = Qnil; @@ -352,7 +356,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) goto fail; } - rc = nxt_ruby_init_threads(c); + rc = nxt_ruby_init_threads(script, c); if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { goto fail; } @@ -421,6 +425,37 @@ fail: static VALUE +nxt_ruby_script_basename(nxt_str_t *script) +{ + size_t len; + u_char *p, *last; + + last = NULL; + p = script->start + script->length; + + while (p > script->start) { + + if (p[-1] == '/') { + last = p; + break; + } + + p--; + } + + if (last != NULL) { + len = script->length - (last - script->start); + + } else { + last = script->start; + len = script->length; + } + + return rb_str_new((const char *) last, len); +} + + +static VALUE nxt_ruby_init_basic(VALUE arg) { int state; @@ -563,6 +598,7 @@ nxt_ruby_rack_env_create(VALUE arg) rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MAJOR)); rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MINOR)); + rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rctx->script); rb_hash_aset(hash_env, rb_str_new2("rack.version"), version); rb_hash_aset(hash_env, rb_str_new2("rack.input"), rctx->io_input); rb_hash_aset(hash_env, rb_str_new2("rack.errors"), rctx->io_error); @@ -1357,7 +1393,7 @@ nxt_ruby_ubf(void *ctx) static int -nxt_ruby_init_threads(nxt_ruby_app_conf_t *c) +nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c) { int state; uint32_t i; @@ -1379,6 +1415,7 @@ nxt_ruby_init_threads(nxt_ruby_app_conf_t *c) rctx = &nxt_ruby_ctxs[i]; rctx->env = Qnil; + rctx->script = script; rctx->io_input = Qnil; rctx->io_error = Qnil; rctx->thread = Qnil; diff --git a/src/ruby/nxt_ruby.h b/src/ruby/nxt_ruby.h index 26430021..3bdd567a 100644 --- a/src/ruby/nxt_ruby.h +++ b/src/ruby/nxt_ruby.h @@ -22,6 +22,7 @@ typedef struct { VALUE env; + VALUE script; VALUE io_input; VALUE io_error; VALUE thread; diff --git a/src/ruby/nxt_ruby_stream_io.c b/src/ruby/nxt_ruby_stream_io.c index 82ad3908..4ef69cee 100644 --- a/src/ruby/nxt_ruby_stream_io.c +++ b/src/ruby/nxt_ruby_stream_io.c @@ -18,6 +18,7 @@ static VALUE nxt_ruby_stream_io_puts(VALUE obj, VALUE args); static VALUE nxt_ruby_stream_io_write(VALUE obj, VALUE args); nxt_inline long nxt_ruby_stream_io_s_write(nxt_ruby_ctx_t *rctx, VALUE val); static VALUE nxt_ruby_stream_io_flush(VALUE obj); +static VALUE nxt_ruby_stream_io_close(VALUE obj); VALUE @@ -38,6 +39,7 @@ nxt_ruby_stream_io_input_init(void) rb_define_method(stream_io, "each", nxt_ruby_stream_io_each, 0); rb_define_method(stream_io, "read", nxt_ruby_stream_io_read, -2); rb_define_method(stream_io, "rewind", nxt_ruby_stream_io_rewind, 0); + rb_define_method(stream_io, "close", nxt_ruby_stream_io_close, 0); return stream_io; } @@ -60,6 +62,7 @@ nxt_ruby_stream_io_error_init(void) rb_define_method(stream_io, "puts", nxt_ruby_stream_io_puts, -2); rb_define_method(stream_io, "write", nxt_ruby_stream_io_write, -2); rb_define_method(stream_io, "flush", nxt_ruby_stream_io_flush, 0); + rb_define_method(stream_io, "close", nxt_ruby_stream_io_close, 0); return stream_io; } @@ -257,3 +260,10 @@ nxt_ruby_stream_io_flush(VALUE obj) { return Qnil; } + + +static VALUE +nxt_ruby_stream_io_close(VALUE obj) +{ + return Qnil; +} diff --git a/src/test/nxt_rbtree1_test.c b/src/test/nxt_rbtree1_test.c index d4783ea1..1f23998c 100644 --- a/src/test/nxt_rbtree1_test.c +++ b/src/test/nxt_rbtree1_test.c @@ -9,13 +9,11 @@ #include "nxt_rbtree1.h" -#define \ -nxt_rbtree1_is_empty(tree) \ +#define nxt_rbtree1_is_empty(tree) \ (((tree)->root) == (tree)->sentinel) -#define \ -nxt_rbtree1_is_there_successor(tree, node) \ +#define nxt_rbtree1_is_there_successor(tree, node) \ ((node) != (tree)->sentinel) diff --git a/test/conftest.py b/test/conftest.py index 689c857a..904abc32 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -159,9 +159,7 @@ def pytest_generate_tests(metafunc): type + ' ' + available_versions[0] ) elif callable(prereq_version): - generate_tests( - list(filter(prereq_version, available_versions)) - ) + generate_tests(list(filter(prereq_version, available_versions))) else: raise ValueError( @@ -203,9 +201,7 @@ def pytest_sessionstart(session): # discover modules from check option.available['modules']['openssl'] = check_openssl(unit['unitd']) - option.available['modules']['go'] = check_go( - option.current_dir, unit['temp_dir'], option.test_dir - ) + option.available['modules']['go'] = check_go() option.available['modules']['node'] = check_node(option.current_dir) option.available['modules']['regex'] = check_regex(unit['unitd']) @@ -322,9 +318,7 @@ def run(request): public_dir(path) - if os.path.isfile(path) or stat.S_ISSOCK( - os.stat(path).st_mode - ): + if os.path.isfile(path) or stat.S_ISSOCK(os.stat(path).st_mode): os.remove(path) else: for attempt in range(10): @@ -340,6 +334,10 @@ def run(request): _check_fds(log=log) + # check processes id's and amount + + _check_processes() + # print unit.log in case of error if hasattr(request.node, 'rep_call') and request.node.rep_call.failed: @@ -439,6 +437,16 @@ def unit_stop(): return + # check zombies + + out = subprocess.check_output( + ['ps', 'ax', '-o', 'state', '-o', 'ppid'] + ).decode() + z_ppids = re.findall(r'Z\s*(\d+)', out) + assert unit_instance['pid'] not in z_ppids, 'no zombies' + + # terminate unit + p = unit_instance['process'] if p.poll() is not None: @@ -522,7 +530,7 @@ def _clear_conf(sock, *, log=None): try: certs = json.loads( - http.get(url='/certificates', sock_type='unix', addr=sock,)['body'] + http.get(url='/certificates', sock_type='unix', addr=sock)['body'] ).keys() except json.JSONDecodeError: @@ -530,12 +538,58 @@ def _clear_conf(sock, *, log=None): for cert in certs: resp = http.delete( - url='/certificates/' + cert, sock_type='unix', addr=sock, + url='/certificates/' + cert, + sock_type='unix', + addr=sock, )['body'] assert 'success' in resp, 'remove certificate' +def _check_processes(): + router_pid = _fds_info['router']['pid'] + controller_pid = _fds_info['controller']['pid'] + unit_pid = unit_instance['pid'] + + for i in range(600): + out = ( + subprocess.check_output( + ['ps', '-ax', '-o', 'pid', '-o', 'ppid', '-o', 'command'] + ) + .decode() + .splitlines() + ) + out = [l for l in out if unit_pid in l] + + if len(out) <= 3: + break + + time.sleep(0.1) + + assert len(out) == 3, 'main, router, and controller expected' + + out = [l for l in out if 'unit: main' not in l] + assert len(out) == 2, 'one main' + + out = [ + l + for l in out + if re.search(router_pid + r'\s+' + unit_pid + r'.*unit: router', l) + is None + ] + assert len(out) == 1, 'one router' + + out = [ + l + for l in out + if re.search( + controller_pid + r'\s+' + unit_pid + r'.*unit: controller', l + ) + is None + ] + assert len(out) == 0, 'one controller' + + @print_log_on_assert def _check_fds(*, log=None): def waitforfds(diff): @@ -556,9 +610,7 @@ def _check_fds(*, log=None): ) ps['fds'] += fds_diff - assert ( - fds_diff <= option.fds_threshold - ), 'descriptors leak main process' + assert fds_diff <= option.fds_threshold, 'descriptors leak main process' else: ps['fds'] = _count_fds(unit_instance['pid']) @@ -590,7 +642,8 @@ def _count_fds(pid): try: out = subprocess.check_output( - ['procstat', '-f', pid], stderr=subprocess.STDOUT, + ['procstat', '-f', pid], + stderr=subprocess.STDOUT, ).decode() return len(out.splitlines()) @@ -599,7 +652,8 @@ def _count_fds(pid): try: out = subprocess.check_output( - ['lsof', '-n', '-p', pid], stderr=subprocess.STDOUT, + ['lsof', '-n', '-p', pid], + stderr=subprocess.STDOUT, ).decode() return len(out.splitlines()) diff --git a/test/perl/input_buffered_read/psgi.pl b/test/perl/input_buffered_read/psgi.pl new file mode 100644 index 00000000..4ca699d7 --- /dev/null +++ b/test/perl/input_buffered_read/psgi.pl @@ -0,0 +1,17 @@ +use FileHandle; + +my $app = sub { + my ($environ) = @_; + + $environ->{'psgi.input'}->read(my $body, 1024); + + open my $io, "<", \$body; + + # This makes $io work as FileHandle under 5.8, .10 and .11. + bless $io, 'FileHandle'; + + $environ->{'psgix.input.buffered'} = 1; + $environ->{'psgi.input'} = $io; + + return ['200', ['Content-Length' => length $body], [$body]]; +}; diff --git a/test/perl/input_close/psgi.pl b/test/perl/input_close/psgi.pl new file mode 100644 index 00000000..4a2d9bb9 --- /dev/null +++ b/test/perl/input_close/psgi.pl @@ -0,0 +1,8 @@ +my $app = sub { + my ($environ) = @_; + + $environ->{'psgi.input'}->read(my $body, 1024); + $environ->{'psgi.input'}->close(); + + return ['200', ['Content-Length' => length $body], [$body]]; +}; diff --git a/test/php/opcache/index.php b/test/php/opcache/index.php index de4002bb..cf67c4c2 100644 --- a/test/php/opcache/index.php +++ b/test/php/opcache/index.php @@ -12,7 +12,7 @@ if (function_exists('opcache_is_script_cached')) { opcache_compile_file(__DIR__ . '/test.php'); } } else { - header('X-Cached: -1'); + header('X-OPcache: -1'); } ?> diff --git a/test/php/opcache/preload/chdir.php b/test/php/opcache/preload/chdir.php new file mode 100644 index 00000000..ad75e6ad --- /dev/null +++ b/test/php/opcache/preload/chdir.php @@ -0,0 +1,7 @@ +<?php + +chdir(realpath(__DIR__ . '/..')); + +opcache_compile_file('index.php'); + +?> diff --git a/test/php/opcache/preload/fastcgi_finish_request.php b/test/php/opcache/preload/fastcgi_finish_request.php new file mode 100644 index 00000000..31630cfa --- /dev/null +++ b/test/php/opcache/preload/fastcgi_finish_request.php @@ -0,0 +1,5 @@ +<?php + +fastcgi_finish_request(); + +?> diff --git a/test/python/204_no_content/asgi.py b/test/python/204_no_content/asgi.py index 634facc2..5dbb67d0 100644 --- a/test/python/204_no_content/asgi.py +++ b/test/python/204_no_content/asgi.py @@ -1,8 +1,10 @@ async def application(scope, receive, send): assert scope['type'] == 'http' - await send({ - 'type': 'http.response.start', - 'status': 204, - 'headers': [], - }) + await send( + { + 'type': 'http.response.start', + 'status': 204, + 'headers': [], + } + ) diff --git a/test/ruby/errors_write/config.ru b/test/ruby/errors_write/config.ru index 47619d6b..79ee4d1d 100644 --- a/test/ruby/errors_write/config.ru +++ b/test/ruby/errors_write/config.ru @@ -1,5 +1,7 @@ app = Proc.new do |env| env['rack.errors'].write('Error in application') + env['rack.errors'].flush + env['rack.errors'].close ['200', {'Content-Length' => '0'}, ['']] end diff --git a/test/ruby/input_gets/config.ru b/test/ruby/input_gets/config.ru index 1a6633ab..151fe235 100644 --- a/test/ruby/input_gets/config.ru +++ b/test/ruby/input_gets/config.ru @@ -1,5 +1,6 @@ app = Proc.new do |env| body = env['rack.input'].gets + env['rack.input'].close ['200', { 'Content-Length' => body.length.to_s }, [body]] diff --git a/test/ruby/variables/config.ru b/test/ruby/variables/config.ru index 55d01796..e335e049 100644 --- a/test/ruby/variables/config.ru +++ b/test/ruby/variables/config.ru @@ -8,6 +8,7 @@ app = Proc.new do |env| 'Request-Method' => env['REQUEST_METHOD'], 'Request-Uri' => env['REQUEST_URI'], 'Http-Host' => env['HTTP_HOST'], + 'Script-Name' => env['SCRIPT_NAME'], 'Server-Protocol' => env['SERVER_PROTOCOL'], 'Server-Software' => env['SERVER_SOFTWARE'], 'Custom-Header' => env['HTTP_CUSTOM_HEADER'], diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index 021aa2b2..60fcffc1 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -1,14 +1,16 @@ import re import time -from distutils.version import LooseVersion import pytest +from packaging import version from unit.applications.lang.python import TestApplicationPython class TestASGIApplication(TestApplicationPython): prerequisites = { - 'modules': {'python': lambda v: LooseVersion(v) >= LooseVersion('3.5')} + 'modules': { + 'python': lambda v: version.parse(v) >= version.parse('3.5') + } } load_module = 'asgi' diff --git a/test/test_asgi_lifespan.py b/test/test_asgi_lifespan.py index 912d0d85..e295f7fa 100644 --- a/test/test_asgi_lifespan.py +++ b/test/test_asgi_lifespan.py @@ -1,14 +1,16 @@ import os -from distutils.version import LooseVersion from conftest import unit_stop +from packaging import version from unit.applications.lang.python import TestApplicationPython from unit.option import option class TestASGILifespan(TestApplicationPython): prerequisites = { - 'modules': {'python': lambda v: LooseVersion(v) >= LooseVersion('3.5')} + 'modules': { + 'python': lambda v: version.parse(v) >= version.parse('3.5') + } } load_module = 'asgi' @@ -67,7 +69,7 @@ class TestASGILifespan(TestApplicationPython): ], "applications": { "targets": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "working_directory": option.test_dir + "/python/lifespan/empty", diff --git a/test/test_asgi_targets.py b/test/test_asgi_targets.py index b9489cd3..c1e345ef 100644 --- a/test/test_asgi_targets.py +++ b/test/test_asgi_targets.py @@ -1,13 +1,14 @@ -from distutils.version import LooseVersion - import pytest +from packaging import version from unit.applications.lang.python import TestApplicationPython from unit.option import option class TestASGITargets(TestApplicationPython): prerequisites = { - 'modules': {'python': lambda v: LooseVersion(v) >= LooseVersion('3.5')} + 'modules': { + 'python': lambda v: version.parse(v) >= version.parse('3.5') + } } load_module = 'asgi' @@ -28,7 +29,7 @@ class TestASGITargets(TestApplicationPython): ], "applications": { "targets": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "working_directory": option.test_dir + "/python/targets/", diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py index bad54e22..975be90a 100644 --- a/test/test_asgi_websockets.py +++ b/test/test_asgi_websockets.py @@ -1,8 +1,8 @@ import struct import time -from distutils.version import LooseVersion import pytest +from packaging import version from unit.applications.lang.python import TestApplicationPython from unit.applications.websockets import TestApplicationWebsocket from unit.option import option @@ -10,7 +10,9 @@ from unit.option import option class TestASGIWebsockets(TestApplicationPython): prerequisites = { - 'modules': {'python': lambda v: LooseVersion(v) >= LooseVersion('3.5')} + 'modules': { + 'python': lambda v: version.parse(v) >= version.parse('3.5') + } } load_module = 'asgi' @@ -162,7 +164,7 @@ class TestASGIWebsockets(TestApplicationPython): self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) self.ws.frame_write( - sock, self.ws.OP_CONT, 'fragment2', length=2 ** 64 - 1 + sock, self.ws.OP_CONT, 'fragment2', length=2**64 - 1 ) self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE @@ -940,9 +942,7 @@ class TestASGIWebsockets(TestApplicationPython): frame = self.ws.frame_read(sock) if frame['opcode'] == self.ws.OP_TEXT: - self.check_frame( - frame, True, self.ws.OP_TEXT, 'fragment1fragment2' - ) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') frame = None self.check_close(sock, 1002, frame=frame) @@ -1187,7 +1187,7 @@ class TestASGIWebsockets(TestApplicationPython): _, sock, _ = self.ws.upgrade() - self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2**10) self.ws.frame_write(sock, self.ws.OP_TEXT, payload) self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) @@ -1349,62 +1349,62 @@ class TestASGIWebsockets(TestApplicationPython): def check_message(opcode, f_size): if opcode == self.ws.OP_TEXT: - payload = '*' * 4 * 2 ** 20 + payload = '*' * 4 * 2**20 else: - payload = b'*' * 4 * 2 ** 20 + payload = b'*' * 4 * 2**20 self.ws.message(sock, opcode, payload, fragmention_size=f_size) frame = self.ws.frame_read(sock, read_timeout=5) self.check_frame(frame, True, opcode, payload) - check_payload(op_text, 64 * 2 ** 10) # 9_1_1 - check_payload(op_text, 256 * 2 ** 10) # 9_1_2 - check_payload(op_text, 2 ** 20) # 9_1_3 - check_payload(op_text, 4 * 2 ** 20) # 9_1_4 - check_payload(op_text, 8 * 2 ** 20) # 9_1_5 - check_payload(op_text, 16 * 2 ** 20) # 9_1_6 + check_payload(op_text, 64 * 2**10) # 9_1_1 + check_payload(op_text, 256 * 2**10) # 9_1_2 + check_payload(op_text, 2**20) # 9_1_3 + check_payload(op_text, 4 * 2**20) # 9_1_4 + check_payload(op_text, 8 * 2**20) # 9_1_5 + check_payload(op_text, 16 * 2**20) # 9_1_6 - check_payload(op_binary, 64 * 2 ** 10) # 9_2_1 - check_payload(op_binary, 256 * 2 ** 10) # 9_2_2 - check_payload(op_binary, 2 ** 20) # 9_2_3 - check_payload(op_binary, 4 * 2 ** 20) # 9_2_4 - check_payload(op_binary, 8 * 2 ** 20) # 9_2_5 - check_payload(op_binary, 16 * 2 ** 20) # 9_2_6 + check_payload(op_binary, 64 * 2**10) # 9_2_1 + check_payload(op_binary, 256 * 2**10) # 9_2_2 + check_payload(op_binary, 2**20) # 9_2_3 + check_payload(op_binary, 4 * 2**20) # 9_2_4 + check_payload(op_binary, 8 * 2**20) # 9_2_5 + check_payload(op_binary, 16 * 2**20) # 9_2_6 if option.system != 'Darwin' and option.system != 'FreeBSD': check_message(op_text, 64) # 9_3_1 check_message(op_text, 256) # 9_3_2 - check_message(op_text, 2 ** 10) # 9_3_3 - check_message(op_text, 4 * 2 ** 10) # 9_3_4 - check_message(op_text, 16 * 2 ** 10) # 9_3_5 - check_message(op_text, 64 * 2 ** 10) # 9_3_6 - check_message(op_text, 256 * 2 ** 10) # 9_3_7 - check_message(op_text, 2 ** 20) # 9_3_8 - check_message(op_text, 4 * 2 ** 20) # 9_3_9 + check_message(op_text, 2**10) # 9_3_3 + check_message(op_text, 4 * 2**10) # 9_3_4 + check_message(op_text, 16 * 2**10) # 9_3_5 + check_message(op_text, 64 * 2**10) # 9_3_6 + check_message(op_text, 256 * 2**10) # 9_3_7 + check_message(op_text, 2**20) # 9_3_8 + check_message(op_text, 4 * 2**20) # 9_3_9 check_message(op_binary, 64) # 9_4_1 check_message(op_binary, 256) # 9_4_2 - check_message(op_binary, 2 ** 10) # 9_4_3 - check_message(op_binary, 4 * 2 ** 10) # 9_4_4 - check_message(op_binary, 16 * 2 ** 10) # 9_4_5 - check_message(op_binary, 64 * 2 ** 10) # 9_4_6 - check_message(op_binary, 256 * 2 ** 10) # 9_4_7 - check_message(op_binary, 2 ** 20) # 9_4_8 - check_message(op_binary, 4 * 2 ** 20) # 9_4_9 - - check_payload(op_text, 2 ** 20, chopsize=64) # 9_5_1 - check_payload(op_text, 2 ** 20, chopsize=128) # 9_5_2 - check_payload(op_text, 2 ** 20, chopsize=256) # 9_5_3 - check_payload(op_text, 2 ** 20, chopsize=512) # 9_5_4 - check_payload(op_text, 2 ** 20, chopsize=1024) # 9_5_5 - check_payload(op_text, 2 ** 20, chopsize=2048) # 9_5_6 - - check_payload(op_binary, 2 ** 20, chopsize=64) # 9_6_1 - check_payload(op_binary, 2 ** 20, chopsize=128) # 9_6_2 - check_payload(op_binary, 2 ** 20, chopsize=256) # 9_6_3 - check_payload(op_binary, 2 ** 20, chopsize=512) # 9_6_4 - check_payload(op_binary, 2 ** 20, chopsize=1024) # 9_6_5 - check_payload(op_binary, 2 ** 20, chopsize=2048) # 9_6_6 + check_message(op_binary, 2**10) # 9_4_3 + check_message(op_binary, 4 * 2**10) # 9_4_4 + check_message(op_binary, 16 * 2**10) # 9_4_5 + check_message(op_binary, 64 * 2**10) # 9_4_6 + check_message(op_binary, 256 * 2**10) # 9_4_7 + check_message(op_binary, 2**20) # 9_4_8 + check_message(op_binary, 4 * 2**20) # 9_4_9 + + check_payload(op_text, 2**20, chopsize=64) # 9_5_1 + check_payload(op_text, 2**20, chopsize=128) # 9_5_2 + check_payload(op_text, 2**20, chopsize=256) # 9_5_3 + check_payload(op_text, 2**20, chopsize=512) # 9_5_4 + check_payload(op_text, 2**20, chopsize=1024) # 9_5_5 + check_payload(op_text, 2**20, chopsize=2048) # 9_5_6 + + check_payload(op_binary, 2**20, chopsize=64) # 9_6_1 + check_payload(op_binary, 2**20, chopsize=128) # 9_6_2 + check_payload(op_binary, 2**20, chopsize=256) # 9_6_3 + check_payload(op_binary, 2**20, chopsize=512) # 9_6_4 + check_payload(op_binary, 2**20, chopsize=1024) # 9_6_5 + check_payload(op_binary, 2**20, chopsize=2048) # 9_6_6 self.close_connection(sock) diff --git a/test/test_client_ip.py b/test/test_client_ip.py index 4b2b2fa1..53e52201 100644 --- a/test/test_client_ip.py +++ b/test/test_client_ip.py @@ -7,10 +7,14 @@ class TestClientIP(TestApplicationPython): def client_ip(self, options): assert 'success' in self.conf( { - "127.0.0.1:7081": - {"client_ip": options, "pass": "applications/client_ip"}, - "[::1]:7082": - {"client_ip": options, "pass": "applications/client_ip"}, + "127.0.0.1:7081": { + "client_ip": options, + "pass": "applications/client_ip", + }, + "[::1]:7082": { + "client_ip": options, + "pass": "applications/client_ip", + }, }, 'listeners', ), 'listeners configure' @@ -48,9 +52,7 @@ class TestClientIP(TestApplicationPython): ), 'ipv6 default 2' assert self.get_xff('1.1.1.1') == '1.1.1.1', 'replace' assert self.get_xff('blah') == '127.0.0.1', 'bad header 2' - assert ( - self.get_xff('1.1.1.1', 'ipv6') == '::1' - ), 'bad source ipv6 2' + assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6 2' self.client_ip({'header': 'X-Forwarded-For', 'source': '!127.0.0.1'}) @@ -118,10 +120,18 @@ class TestClientIP(TestApplicationPython): def test_settings_client_ip_invalid(self): assert 'error' in self.conf( - {"http": {"client_ip": {'header': 'X-Forwarded-For', 'source': []}}}, + { + "http": { + "client_ip": {'header': 'X-Forwarded-For', 'source': []} + } + }, 'settings', ), 'empty array source' assert 'error' in self.conf( - {"http":{"client_ip": {'header': 'X-Forwarded-For', 'source': 'a'}}}, + { + "http": { + "client_ip": {'header': 'X-Forwarded-For', 'source': 'a'} + } + }, 'settings', ), 'empty source invalid' diff --git a/test/test_go_application.py b/test/test_go_application.py index 94da1aee..c8cf3e53 100644 --- a/test/test_go_application.py +++ b/test/test_go_application.py @@ -1,7 +1,6 @@ import re import pytest - from unit.applications.lang.go import TestApplicationGo @@ -158,9 +157,7 @@ class TestGoApplication(TestApplicationGo): 'applications/command_line_arguments/arguments', ) - assert ( - self.get()['body'] == arg1 + ',' + arg2 + ',' + arg3 - ), 'arguments' + assert self.get()['body'] == arg1 + ',' + arg2 + ',' + arg3, 'arguments' def test_go_application_command_line_arguments_change(self): self.load('command_line_arguments') @@ -177,6 +174,4 @@ class TestGoApplication(TestApplicationGo): assert 'success' in self.conf('[]', args_path) - assert ( - self.get()['headers']['Content-Length'] == '0' - ), 'arguments empty' + assert self.get()['headers']['Content-Length'] == '0', 'arguments empty' diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index 72988a34..c3f92679 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -167,9 +167,7 @@ class TestGoIsolation(TestApplicationGo): user='nobody', isolation={ 'namespaces': {'credential': True}, - 'uidmap': [ - {'container': 0, 'host': 0, 'size': nobody_uid + 1} - ], + 'uidmap': [{'container': 0, 'host': 0, 'size': nobody_uid + 1}], }, ) diff --git a/test/test_http_header.py b/test/test_http_header.py index ca355eb7..6773c44f 100644 --- a/test/test_http_header.py +++ b/test/test_http_header.py @@ -213,7 +213,7 @@ Connection: close self.post( headers={ 'Host': 'localhost', - 'Content-Length': str(2 ** 64), + 'Content-Length': str(2**64), 'Connection': 'close', }, body='X' * 1000, @@ -325,9 +325,7 @@ Connection: close def test_http_header_host_port_empty(self): self.load('host') - resp = self.get( - headers={'Host': 'exmaple.com:', 'Connection': 'close'} - ) + resp = self.get(headers={'Host': 'exmaple.com:', 'Connection': 'close'}) assert resp['status'] == 200, 'Host port empty status' assert ( @@ -376,9 +374,7 @@ Connection: close def test_http_header_host_trailing_period_2(self): self.load('host') - resp = self.get( - headers={'Host': 'EXAMPLE.COM.', 'Connection': 'close'} - ) + resp = self.get(headers={'Host': 'EXAMPLE.COM.', 'Connection': 'close'}) assert resp['status'] == 200, 'Host trailing period 2 status' assert ( @@ -453,14 +449,16 @@ Connection: close assert 'CUSTOM' not in resp['headers']['All-Headers'] assert 'success' in self.conf( - {'http': {'discard_unsafe_fields': False}}, 'settings', + {'http': {'discard_unsafe_fields': False}}, + 'settings', ) resp = check_status("!#$%&'*+.^`|~Custom_Header") assert 'CUSTOM' in resp['headers']['All-Headers'] assert 'success' in self.conf( - {'http': {'discard_unsafe_fields': True}}, 'settings', + {'http': {'discard_unsafe_fields': True}}, + 'settings', ) resp = check_status("!Custom-Header") diff --git a/test/test_java_application.py b/test/test_java_application.py index 3fd5c26e..adcb4eca 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -22,7 +22,7 @@ class TestJavaApplication(TestApplicationJava): "listeners": {"*:7080": {"pass": "applications/app"}}, "applications": { "app": { - "type": "java", + "type": self.get_application_type(), "processes": 1, "working_directory": option.test_dir + "/java/empty", "webapp": temp_dir + "/java", @@ -173,9 +173,7 @@ class TestJavaApplication(TestApplicationJava): } ) - assert ( - resp['headers']['X-Session-Id'] == session_id - ), 'session active 2' + assert resp['headers']['X-Session-Id'] == session_id, 'session active 2' time.sleep(2) @@ -187,9 +185,7 @@ class TestJavaApplication(TestApplicationJava): } ) - assert ( - resp['headers']['X-Session-Id'] == session_id - ), 'session active 3' + assert resp['headers']['X-Session-Id'] == session_id, 'session active 3' def test_java_application_session_inactive(self): self.load('session_inactive') @@ -213,9 +209,7 @@ class TestJavaApplication(TestApplicationJava): } ) - assert ( - resp['headers']['X-Session-Id'] != session_id - ), 'session inactive' + assert resp['headers']['X-Session-Id'] != session_id, 'session inactive' def test_java_application_session_invalidate(self): self.load('session_invalidate') @@ -391,9 +385,7 @@ class TestJavaApplication(TestApplicationJava): assert ( headers['X-Content-Type'] == 'text/plain;charset=utf-8' ), '#1 response Content-Type' - assert ( - headers['X-Character-Encoding'] == 'utf-8' - ), '#1 response charset' + assert headers['X-Character-Encoding'] == 'utf-8', '#1 response charset' headers = self.get(url='/2')['headers'] @@ -445,15 +437,11 @@ class TestJavaApplication(TestApplicationJava): headers = self.get(url='/6')['headers'] - assert ( - 'Content-Type' in headers - ) == False, '#6 no Content-Type header' + assert ('Content-Type' in headers) == False, '#6 no Content-Type header' assert ( 'X-Content-Type' in headers ) == False, '#6 no response Content-Type' - assert ( - headers['X-Character-Encoding'] == 'utf-8' - ), '#6 response charset' + assert headers['X-Character-Encoding'] == 'utf-8', '#6 response charset' headers = self.get(url='/7')['headers'] @@ -463,9 +451,7 @@ class TestJavaApplication(TestApplicationJava): assert ( headers['X-Content-Type'] == 'text/plain;charset=utf-8' ), '#7 response Content-Type' - assert ( - headers['X-Character-Encoding'] == 'utf-8' - ), '#7 response charset' + assert headers['X-Character-Encoding'] == 'utf-8', '#7 response charset' headers = self.get(url='/8')['headers'] @@ -475,9 +461,7 @@ class TestJavaApplication(TestApplicationJava): assert ( headers['X-Content-Type'] == 'text/html;charset=utf-8' ), '#8 response Content-Type' - assert ( - headers['X-Character-Encoding'] == 'utf-8' - ), '#8 response charset' + assert headers['X-Character-Encoding'] == 'utf-8', '#8 response charset' def test_java_application_welcome_files(self): self.load('welcome_files') @@ -490,9 +474,7 @@ class TestJavaApplication(TestApplicationJava): resp = self.get(url='/dir1/') - assert ( - 'This is index.txt.' in resp['body'] - ) == True, 'dir1 index body' + assert ('This is index.txt.' in resp['body']) == True, 'dir1 index body' assert resp['headers']['X-TXT-Filter'] == '1', 'TXT Filter header' headers = self.get(url='/dir2/')['headers'] @@ -655,9 +637,7 @@ class TestJavaApplication(TestApplicationJava): assert ( headers['X-FORWARD-Id'] == 'data' ), 'forward request servlet mapping' - assert ( - headers['X-FORWARD-Request-URI'] == '/fwd' - ), 'forward request uri' + assert headers['X-FORWARD-Request-URI'] == '/fwd', 'forward request uri' assert ( headers['X-FORWARD-Servlet-Path'] == '/fwd' ), 'forward request servlet path' @@ -1003,9 +983,7 @@ class TestJavaApplication(TestApplicationJava): ) assert resp['status'] == 200, 'multipart status' - assert re.search( - r'sample\.txt created', resp['body'] - ), 'multipart body' + assert re.search(r'sample\.txt created', resp['body']), 'multipart body' assert ( self.search_in_log( r'^Data from sample file$', name=reldst + '/sample.txt' diff --git a/test/test_java_isolation_rootfs.py b/test/test_java_isolation_rootfs.py index eac86a0c..3c6a45a3 100644 --- a/test/test_java_isolation_rootfs.py +++ b/test/test_java_isolation_rootfs.py @@ -11,7 +11,7 @@ class TestJavaIsolationRootfs(TestApplicationJava): def setup_method(self, is_su): if not is_su: - return + pytest.skip('require root') os.makedirs(option.temp_dir + '/jars') os.makedirs(option.temp_dir + '/tmp') @@ -61,7 +61,8 @@ class TestJavaIsolationRootfs(TestApplicationJava): self.load('empty_war', isolation=isolation) assert 'success' in self.conf( - '"/"', '/config/applications/empty_war/working_directory', + '"/"', + '/config/applications/empty_war/working_directory', ) assert 'success' in self.conf( diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index a80d3bf3..362c8619 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -869,9 +869,7 @@ class TestJavaWebsockets(TestApplicationJava): frame = self.ws.frame_read(sock) if frame['opcode'] == self.ws.OP_TEXT: - self.check_frame( - frame, True, self.ws.OP_TEXT, 'fragment1fragment2' - ) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') frame = None self.check_close(sock, 1002, frame=frame) @@ -1116,7 +1114,7 @@ class TestJavaWebsockets(TestApplicationJava): _, sock, _ = self.ws.upgrade() - self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2**10) self.ws.frame_write(sock, self.ws.OP_TEXT, payload) self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) @@ -1278,62 +1276,62 @@ class TestJavaWebsockets(TestApplicationJava): def check_message(opcode, f_size): if opcode == self.ws.OP_TEXT: - payload = '*' * 4 * 2 ** 20 + payload = '*' * 4 * 2**20 else: - payload = b'*' * 4 * 2 ** 20 + payload = b'*' * 4 * 2**20 self.ws.message(sock, opcode, payload, fragmention_size=f_size) frame = self.ws.frame_read(sock, read_timeout=5) self.check_frame(frame, True, opcode, payload) - check_payload(op_text, 64 * 2 ** 10) # 9_1_1 - check_payload(op_text, 256 * 2 ** 10) # 9_1_2 - check_payload(op_text, 2 ** 20) # 9_1_3 - check_payload(op_text, 4 * 2 ** 20) # 9_1_4 - check_payload(op_text, 8 * 2 ** 20) # 9_1_5 - check_payload(op_text, 16 * 2 ** 20) # 9_1_6 + check_payload(op_text, 64 * 2**10) # 9_1_1 + check_payload(op_text, 256 * 2**10) # 9_1_2 + check_payload(op_text, 2**20) # 9_1_3 + check_payload(op_text, 4 * 2**20) # 9_1_4 + check_payload(op_text, 8 * 2**20) # 9_1_5 + check_payload(op_text, 16 * 2**20) # 9_1_6 - check_payload(op_binary, 64 * 2 ** 10) # 9_2_1 - check_payload(op_binary, 256 * 2 ** 10) # 9_2_2 - check_payload(op_binary, 2 ** 20) # 9_2_3 - check_payload(op_binary, 4 * 2 ** 20) # 9_2_4 - check_payload(op_binary, 8 * 2 ** 20) # 9_2_5 - check_payload(op_binary, 16 * 2 ** 20) # 9_2_6 + check_payload(op_binary, 64 * 2**10) # 9_2_1 + check_payload(op_binary, 256 * 2**10) # 9_2_2 + check_payload(op_binary, 2**20) # 9_2_3 + check_payload(op_binary, 4 * 2**20) # 9_2_4 + check_payload(op_binary, 8 * 2**20) # 9_2_5 + check_payload(op_binary, 16 * 2**20) # 9_2_6 if option.system != 'Darwin' and option.system != 'FreeBSD': check_message(op_text, 64) # 9_3_1 check_message(op_text, 256) # 9_3_2 - check_message(op_text, 2 ** 10) # 9_3_3 - check_message(op_text, 4 * 2 ** 10) # 9_3_4 - check_message(op_text, 16 * 2 ** 10) # 9_3_5 - check_message(op_text, 64 * 2 ** 10) # 9_3_6 - check_message(op_text, 256 * 2 ** 10) # 9_3_7 - check_message(op_text, 2 ** 20) # 9_3_8 - check_message(op_text, 4 * 2 ** 20) # 9_3_9 + check_message(op_text, 2**10) # 9_3_3 + check_message(op_text, 4 * 2**10) # 9_3_4 + check_message(op_text, 16 * 2**10) # 9_3_5 + check_message(op_text, 64 * 2**10) # 9_3_6 + check_message(op_text, 256 * 2**10) # 9_3_7 + check_message(op_text, 2**20) # 9_3_8 + check_message(op_text, 4 * 2**20) # 9_3_9 check_message(op_binary, 64) # 9_4_1 check_message(op_binary, 256) # 9_4_2 - check_message(op_binary, 2 ** 10) # 9_4_3 - check_message(op_binary, 4 * 2 ** 10) # 9_4_4 - check_message(op_binary, 16 * 2 ** 10) # 9_4_5 - check_message(op_binary, 64 * 2 ** 10) # 9_4_6 - check_message(op_binary, 256 * 2 ** 10) # 9_4_7 - check_message(op_binary, 2 ** 20) # 9_4_8 - check_message(op_binary, 4 * 2 ** 20) # 9_4_9 - - check_payload(op_text, 2 ** 20, chopsize=64) # 9_5_1 - check_payload(op_text, 2 ** 20, chopsize=128) # 9_5_2 - check_payload(op_text, 2 ** 20, chopsize=256) # 9_5_3 - check_payload(op_text, 2 ** 20, chopsize=512) # 9_5_4 - check_payload(op_text, 2 ** 20, chopsize=1024) # 9_5_5 - check_payload(op_text, 2 ** 20, chopsize=2048) # 9_5_6 - - check_payload(op_binary, 2 ** 20, chopsize=64) # 9_6_1 - check_payload(op_binary, 2 ** 20, chopsize=128) # 9_6_2 - check_payload(op_binary, 2 ** 20, chopsize=256) # 9_6_3 - check_payload(op_binary, 2 ** 20, chopsize=512) # 9_6_4 - check_payload(op_binary, 2 ** 20, chopsize=1024) # 9_6_5 - check_payload(op_binary, 2 ** 20, chopsize=2048) # 9_6_6 + check_message(op_binary, 2**10) # 9_4_3 + check_message(op_binary, 4 * 2**10) # 9_4_4 + check_message(op_binary, 16 * 2**10) # 9_4_5 + check_message(op_binary, 64 * 2**10) # 9_4_6 + check_message(op_binary, 256 * 2**10) # 9_4_7 + check_message(op_binary, 2**20) # 9_4_8 + check_message(op_binary, 4 * 2**20) # 9_4_9 + + check_payload(op_text, 2**20, chopsize=64) # 9_5_1 + check_payload(op_text, 2**20, chopsize=128) # 9_5_2 + check_payload(op_text, 2**20, chopsize=256) # 9_5_3 + check_payload(op_text, 2**20, chopsize=512) # 9_5_4 + check_payload(op_text, 2**20, chopsize=1024) # 9_5_5 + check_payload(op_text, 2**20, chopsize=2048) # 9_5_6 + + check_payload(op_binary, 2**20, chopsize=64) # 9_6_1 + check_payload(op_binary, 2**20, chopsize=128) # 9_6_2 + check_payload(op_binary, 2**20, chopsize=256) # 9_6_3 + check_payload(op_binary, 2**20, chopsize=512) # 9_6_4 + check_payload(op_binary, 2**20, chopsize=1024) # 9_6_5 + check_payload(op_binary, 2**20, chopsize=2048) # 9_6_6 self.close_connection(sock) diff --git a/test/test_node_application.py b/test/test_node_application.py index 62a09c43..fc722582 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -218,9 +218,7 @@ class TestNodeApplication(TestApplicationNode): def test_node_application_status_message(self): self.load('status_message') - assert re.search( - r'200 blah', self.get(raw_resp=True) - ), 'status message' + assert re.search(r'200 blah', self.get(raw_resp=True)), 'status message' def test_node_application_get_header_type(self): self.load('get_header_type') diff --git a/test/test_node_es_modules.py b/test/test_node_es_modules.py index 12788fa4..8a9cb181 100644 --- a/test/test_node_es_modules.py +++ b/test/test_node_es_modules.py @@ -1,5 +1,4 @@ -from distutils.version import LooseVersion - +from packaging import version from unit.applications.lang.node import TestApplicationNode from unit.applications.websockets import TestApplicationWebsocket @@ -7,7 +6,7 @@ from unit.applications.websockets import TestApplicationWebsocket class TestNodeESModules(TestApplicationNode): prerequisites = { 'modules': { - 'node': lambda v: LooseVersion(v) >= LooseVersion("14.16.0") + 'node': lambda v: version.parse(v) >= version.parse('14.16.0') } } diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index e4c8a05e..1f9a2e6b 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -888,9 +888,7 @@ class TestNodeWebsockets(TestApplicationNode): frame = self.ws.frame_read(sock) if frame['opcode'] == self.ws.OP_TEXT: - self.check_frame( - frame, True, self.ws.OP_TEXT, 'fragment1fragment2' - ) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') frame = None self.check_close(sock, 1002, frame=frame) @@ -1135,7 +1133,7 @@ class TestNodeWebsockets(TestApplicationNode): _, sock, _ = self.ws.upgrade() - self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2**10) self.ws.frame_write(sock, self.ws.OP_TEXT, payload) self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) @@ -1297,62 +1295,62 @@ class TestNodeWebsockets(TestApplicationNode): def check_message(opcode, f_size): if opcode == self.ws.OP_TEXT: - payload = '*' * 4 * 2 ** 20 + payload = '*' * 4 * 2**20 else: - payload = b'*' * 4 * 2 ** 20 + payload = b'*' * 4 * 2**20 self.ws.message(sock, opcode, payload, fragmention_size=f_size) frame = self.ws.frame_read(sock, read_timeout=5) self.check_frame(frame, True, opcode, payload) - check_payload(op_text, 64 * 2 ** 10) # 9_1_1 - check_payload(op_text, 256 * 2 ** 10) # 9_1_2 - check_payload(op_text, 2 ** 20) # 9_1_3 - check_payload(op_text, 4 * 2 ** 20) # 9_1_4 - check_payload(op_text, 8 * 2 ** 20) # 9_1_5 - check_payload(op_text, 16 * 2 ** 20) # 9_1_6 + check_payload(op_text, 64 * 2**10) # 9_1_1 + check_payload(op_text, 256 * 2**10) # 9_1_2 + check_payload(op_text, 2**20) # 9_1_3 + check_payload(op_text, 4 * 2**20) # 9_1_4 + check_payload(op_text, 8 * 2**20) # 9_1_5 + check_payload(op_text, 16 * 2**20) # 9_1_6 - check_payload(op_binary, 64 * 2 ** 10) # 9_2_1 - check_payload(op_binary, 256 * 2 ** 10) # 9_2_2 - check_payload(op_binary, 2 ** 20) # 9_2_3 - check_payload(op_binary, 4 * 2 ** 20) # 9_2_4 - check_payload(op_binary, 8 * 2 ** 20) # 9_2_5 - check_payload(op_binary, 16 * 2 ** 20) # 9_2_6 + check_payload(op_binary, 64 * 2**10) # 9_2_1 + check_payload(op_binary, 256 * 2**10) # 9_2_2 + check_payload(op_binary, 2**20) # 9_2_3 + check_payload(op_binary, 4 * 2**20) # 9_2_4 + check_payload(op_binary, 8 * 2**20) # 9_2_5 + check_payload(op_binary, 16 * 2**20) # 9_2_6 if option.system != 'Darwin' and option.system != 'FreeBSD': check_message(op_text, 64) # 9_3_1 check_message(op_text, 256) # 9_3_2 - check_message(op_text, 2 ** 10) # 9_3_3 - check_message(op_text, 4 * 2 ** 10) # 9_3_4 - check_message(op_text, 16 * 2 ** 10) # 9_3_5 - check_message(op_text, 64 * 2 ** 10) # 9_3_6 - check_message(op_text, 256 * 2 ** 10) # 9_3_7 - check_message(op_text, 2 ** 20) # 9_3_8 - check_message(op_text, 4 * 2 ** 20) # 9_3_9 + check_message(op_text, 2**10) # 9_3_3 + check_message(op_text, 4 * 2**10) # 9_3_4 + check_message(op_text, 16 * 2**10) # 9_3_5 + check_message(op_text, 64 * 2**10) # 9_3_6 + check_message(op_text, 256 * 2**10) # 9_3_7 + check_message(op_text, 2**20) # 9_3_8 + check_message(op_text, 4 * 2**20) # 9_3_9 check_message(op_binary, 64) # 9_4_1 check_message(op_binary, 256) # 9_4_2 - check_message(op_binary, 2 ** 10) # 9_4_3 - check_message(op_binary, 4 * 2 ** 10) # 9_4_4 - check_message(op_binary, 16 * 2 ** 10) # 9_4_5 - check_message(op_binary, 64 * 2 ** 10) # 9_4_6 - check_message(op_binary, 256 * 2 ** 10) # 9_4_7 - check_message(op_binary, 2 ** 20) # 9_4_8 - check_message(op_binary, 4 * 2 ** 20) # 9_4_9 - - check_payload(op_text, 2 ** 20, chopsize=64) # 9_5_1 - check_payload(op_text, 2 ** 20, chopsize=128) # 9_5_2 - check_payload(op_text, 2 ** 20, chopsize=256) # 9_5_3 - check_payload(op_text, 2 ** 20, chopsize=512) # 9_5_4 - check_payload(op_text, 2 ** 20, chopsize=1024) # 9_5_5 - check_payload(op_text, 2 ** 20, chopsize=2048) # 9_5_6 - - check_payload(op_binary, 2 ** 20, chopsize=64) # 9_6_1 - check_payload(op_binary, 2 ** 20, chopsize=128) # 9_6_2 - check_payload(op_binary, 2 ** 20, chopsize=256) # 9_6_3 - check_payload(op_binary, 2 ** 20, chopsize=512) # 9_6_4 - check_payload(op_binary, 2 ** 20, chopsize=1024) # 9_6_5 - check_payload(op_binary, 2 ** 20, chopsize=2048) # 9_6_6 + check_message(op_binary, 2**10) # 9_4_3 + check_message(op_binary, 4 * 2**10) # 9_4_4 + check_message(op_binary, 16 * 2**10) # 9_4_5 + check_message(op_binary, 64 * 2**10) # 9_4_6 + check_message(op_binary, 256 * 2**10) # 9_4_7 + check_message(op_binary, 2**20) # 9_4_8 + check_message(op_binary, 4 * 2**20) # 9_4_9 + + check_payload(op_text, 2**20, chopsize=64) # 9_5_1 + check_payload(op_text, 2**20, chopsize=128) # 9_5_2 + check_payload(op_text, 2**20, chopsize=256) # 9_5_3 + check_payload(op_text, 2**20, chopsize=512) # 9_5_4 + check_payload(op_text, 2**20, chopsize=1024) # 9_5_5 + check_payload(op_text, 2**20, chopsize=2048) # 9_5_6 + + check_payload(op_binary, 2**20, chopsize=64) # 9_6_1 + check_payload(op_binary, 2**20, chopsize=128) # 9_6_2 + check_payload(op_binary, 2**20, chopsize=256) # 9_6_3 + check_payload(op_binary, 2**20, chopsize=512) # 9_6_4 + check_payload(op_binary, 2**20, chopsize=1024) # 9_6_5 + check_payload(op_binary, 2**20, chopsize=2048) # 9_6_6 self.close_connection(sock) diff --git a/test/test_perl_application.py b/test/test_perl_application.py index dfd8be6c..0d1d7906 100644 --- a/test/test_perl_application.py +++ b/test/test_perl_application.py @@ -100,6 +100,22 @@ class TestPerlApplication(TestApplicationPerl): self.post(body='0123456789')['body'] == '0123456789' ), 'input read parts' + def test_perl_application_input_buffered_read(self): + self.load('input_buffered_read') + + assert self.post(body='012345')['body'] == '012345', 'buffered read #1' + assert ( + self.post(body='9876543210')['body'] == '9876543210' + ), 'buffered read #2' + + def test_perl_application_input_close(self): + self.load('input_close') + + assert self.post(body='012345')['body'] == '012345', 'input close #1' + assert ( + self.post(body='9876543210')['body'] == '9876543210' + ), 'input close #2' + @pytest.mark.skip('not yet') def test_perl_application_input_read_offset(self): self.load('input_read_offset') @@ -118,8 +134,7 @@ class TestPerlApplication(TestApplicationPerl): assert self.get()['body'] == '1', 'errors result' assert ( - self.wait_for_record(r'\[error\].+Error in application') - is not None + self.wait_for_record(r'\[error\].+Error in application') is not None ), 'errors print' def test_perl_application_header_equal_names(self): diff --git a/test/test_php_application.py b/test/test_php_application.py index d9c16a6d..606ac723 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -1,3 +1,4 @@ +import getpass import os import re import shutil @@ -18,18 +19,43 @@ class TestPHPApplication(TestApplicationPHP): assert re.search(r'time: \d+', body), 'disable_functions before time' assert re.search(r'exec: \/\w+', body), 'disable_functions before exec' + def check_opcache(self): + resp = self.get() + assert resp['status'] == 200, 'status' + + headers = resp['headers'] + if 'X-OPcache' in headers and headers['X-OPcache'] == '-1': + pytest.skip('opcache is not supported') + + return resp + def set_opcache(self, app, val): assert 'success' in self.conf( {"admin": {"opcache.enable": val, "opcache.enable_cli": val}}, 'applications/' + app + '/options', ) - opcache = self.get()['headers']['X-OPcache'] - - if not opcache or opcache == '-1': - pytest.skip('opcache is not supported') + r = self.check_opcache() + assert r['headers']['X-OPcache'] == val, 'opcache value' + + def set_preload(self, preload): + with open(option.temp_dir + '/php.ini', 'w') as f: + f.write( + """opcache.preload = %(test_dir)s/php/opcache/preload\ +/%(preload)s +opcache.preload_user = %(user)s +""" + % { + 'test_dir': option.test_dir, + 'preload': preload, + 'user': option.user or getpass.getuser(), + } + ) - assert opcache == val, 'opcache value' + assert 'success' in self.conf( + {"file": option.temp_dir + "/php.ini"}, + 'applications/opcache/options', + ) def test_php_application_variables(self): self.load('variables') @@ -294,20 +320,28 @@ class TestPHPApplication(TestApplicationPHP): self.load('ini_precision') assert 'success' in self.conf( - {"file": "php.ini", "admin": {"precision": "5"}}, + {"file": "ini/php.ini", "admin": {"precision": "5"}}, 'applications/ini_precision/options', ) + assert ( + self.get()['headers']['X-File'] + == option.test_dir + '/php/ini_precision/ini/php.ini' + ), 'ini file' assert self.get()['headers']['X-Precision'] == '5', 'ini value admin' def test_php_application_ini_user(self): self.load('ini_precision') assert 'success' in self.conf( - {"file": "php.ini", "user": {"precision": "5"}}, + {"file": "ini/php.ini", "user": {"precision": "5"}}, 'applications/ini_precision/options', ) + assert ( + self.get()['headers']['X-File'] + == option.test_dir + '/php/ini_precision/ini/php.ini' + ), 'ini file' assert self.get()['headers']['X-Precision'] == '5', 'ini value user' def test_php_application_ini_user_2(self): @@ -385,9 +419,7 @@ class TestPHPApplication(TestApplicationPHP): body = self.get()['body'] - assert not re.search( - r'time: \d+', body - ), 'disable_functions comma time' + assert not re.search(r'time: \d+', body), 'disable_functions comma time' assert not re.search( r'exec: \/\w+', body ), 'disable_functions comma exec' @@ -464,9 +496,7 @@ class TestPHPApplication(TestApplicationPHP): body = self.get()['body'] - assert not re.search( - r'time: \d+', body - ), 'disable_functions space time' + assert not re.search(r'time: \d+', body), 'disable_functions space time' assert not re.search( r'exec: \/\w+', body ), 'disable_functions space exec' @@ -566,7 +596,7 @@ class TestPHPApplication(TestApplicationPHP): "listeners": {"*:7080": {"pass": "applications/script"}}, "applications": { "script": { - "type": "php", + "type": self.get_application_type(), "processes": {"spare": 0}, "root": option.test_dir + "/php/script", "script": "phpinfo.php", @@ -586,7 +616,7 @@ class TestPHPApplication(TestApplicationPHP): "listeners": {"*:7080": {"pass": "applications/phpinfo"}}, "applications": { "phpinfo": { - "type": "php", + "type": self.get_application_type(), "processes": {"spare": 0}, "root": option.test_dir + "/php/phpinfo", } @@ -613,7 +643,7 @@ class TestPHPApplication(TestApplicationPHP): "listeners": {"*:7080": {"pass": "applications/phpinfo"}}, "applications": { "phpinfo": { - "type": "php", + "type": self.get_application_type(), "processes": {"spare": 0}, "root": new_root, "working_directory": new_root, @@ -637,7 +667,8 @@ class TestPHPApplication(TestApplicationPHP): assert resp['body'] == script_cwd, 'default cwd' assert 'success' in self.conf( - '"' + option.test_dir + '"', 'applications/cwd/working_directory', + '"' + option.test_dir + '"', + 'applications/cwd/working_directory', ) resp = self.get() @@ -717,16 +748,31 @@ class TestPHPApplication(TestApplicationPHP): def test_php_application_shared_opcache(self): self.load('opcache', limits={'requests': 1}) - r = self.get() - cached = r['headers']['X-Cached'] - if cached == '-1': - pytest.skip('opcache is not supported') - + r = self.check_opcache() pid = r['headers']['X-Pid'] - - assert cached == '0', 'not cached' + assert r['headers']['X-Cached'] == '0', 'not cached' r = self.get() assert r['headers']['X-Pid'] != pid, 'new instance' assert r['headers']['X-Cached'] == '1', 'cached' + + def test_php_application_opcache_preload_chdir(self, temp_dir): + self.load('opcache') + + self.check_opcache() + + self.set_preload('chdir.php') + + assert self.get()['headers']['X-Cached'] == '0', 'not cached' + assert self.get()['headers']['X-Cached'] == '1', 'cached' + + def test_php_application_opcache_preload_ffr(self, temp_dir): + self.load('opcache') + + self.check_opcache() + + self.set_preload('fastcgi_finish_request.php') + + assert self.get()['headers']['X-Cached'] == '0', 'not cached' + assert self.get()['headers']['X-Cached'] == '1', 'cached' diff --git a/test/test_php_targets.py b/test/test_php_targets.py index 76326131..918c5fda 100644 --- a/test/test_php_targets.py +++ b/test/test_php_targets.py @@ -22,7 +22,7 @@ class TestPHPTargets(TestApplicationPHP): ], "applications": { "targets": { - "type": "php", + "type": self.get_application_type(), "processes": {"spare": 0}, "targets": { "1": { @@ -66,7 +66,7 @@ class TestPHPTargets(TestApplicationPHP): }, "applications": { "targets": { - "type": "php", + "type": self.get_application_type(), "processes": {"spare": 0}, "targets": { "default": { diff --git a/test/test_proxy.py b/test/test_proxy.py index 553cb07c..68ae2394 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -72,15 +72,14 @@ Content-Length: 10 "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], "applications": { "mirror": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + "/python/mirror", - "working_directory": option.test_dir - + "/python/mirror", + "working_directory": option.test_dir + "/python/mirror", "module": "wsgi", }, "custom_header": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + "/python/custom_header", "working_directory": option.test_dir @@ -88,7 +87,7 @@ Content-Length: 10 "module": "wsgi", }, "delayed": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + "/python/delayed", "working_directory": option.test_dir @@ -123,11 +122,10 @@ Content-Length: 10 }, "applications": { "mirror": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + "/python/mirror", - "working_directory": option.test_dir - + "/python/mirror", + "working_directory": option.test_dir + "/python/mirror", "module": "wsgi", } }, @@ -499,11 +497,10 @@ Content-Length: 10 "routes": [{"action": {"proxy": "http://127.0.0.1:7082"}}], "applications": { "mirror": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + "/python/mirror", - "working_directory": option.test_dir - + "/python/mirror", + "working_directory": option.test_dir + "/python/mirror", "module": "wsgi", }, }, diff --git a/test/test_proxy_chunked.py b/test/test_proxy_chunked.py index 73d94332..f024eaf5 100644 --- a/test/test_proxy_chunked.py +++ b/test/test_proxy_chunked.py @@ -90,12 +90,13 @@ class TestProxyChunked(TestApplicationPython): assert 'success' in self.conf( { - "listeners": {"*:7080": {"pass": "routes"},}, + "listeners": { + "*:7080": {"pass": "routes"}, + }, "routes": [ { "action": { - "proxy": "http://127.0.0.1:" - + str(self.SERVER_PORT) + "proxy": "http://127.0.0.1:" + str(self.SERVER_PORT) } } ], @@ -166,9 +167,7 @@ class TestProxyChunked(TestApplicationPython): assert ( self.get_http10( - body=self.chunks( - [('1', hex(i % 16)[2:]) for i in range(4096)] - ), + body=self.chunks([('1', hex(i % 16)[2:]) for i in range(4096)]), )['body'] == part * 256 ) @@ -210,8 +209,7 @@ class TestProxyChunked(TestApplicationPython): assert resp['body'][-5:] != '0\r\n\r\n', 'no zero chunk' assert ( - self.get_http10(body='\r\n\r\n80000000\r\nA X 100')['status'] - == 200 + self.get_http10(body='\r\n\r\n80000000\r\nA X 100')['status'] == 200 ) assert ( self.get_http10(body='\r\n\r\n10000000000000000\r\nA X 100')[ diff --git a/test/test_python_application.py b/test/test_python_application.py index 7bd43664..befbd4d8 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -293,36 +293,6 @@ custom-header: BLAH assert resp == {}, 'reconfigure 2 keep-alive 3' - def test_python_keepalive_reconfigure_3(self): - self.load('empty') - - assert self.get()['status'] == 200, 'init' - - (_, sock) = self.http( - b"""GET / HTTP/1.1 -""", - start=True, - raw=True, - no_recv=True, - ) - - assert self.get()['status'] == 200 - - assert 'success' in self.conf( - {"listeners": {}, "applications": {}} - ), 'reconfigure 3 clear configuration' - - resp = self.http( - b"""Host: localhost -Connection: close - -""", - sock=sock, - raw=True, - ) - - assert resp['status'] == 200, 'reconfigure 3' - def test_python_atexit(self): self.load('atexit') @@ -735,9 +705,7 @@ last line: 987654321 'nobody uid user=nobody group=%s' % group ) - assert obj['GID'] == group_id, ( - 'nobody gid user=nobody group=%s' % group - ) + assert obj['GID'] == group_id, 'nobody gid user=nobody group=%s' % group self.load('user_group', group=group) diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index 53d28285..8cef6812 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -56,9 +56,7 @@ class TestPythonIsolation(TestApplicationPython): ret = self.getjson(url='/?path=/app/python/ns_inspect') - assert ( - ret['body']['FileExists'] == True - ), 'application exists in rootfs' + assert ret['body']['FileExists'] == True, 'application exists in rootfs' def test_python_isolation_rootfs_no_language_deps(self, is_su, temp_dir): if not is_su: @@ -93,8 +91,7 @@ class TestPythonIsolation(TestApplicationPython): self.load('ns_inspect', isolation=isolation) assert ( - self.getjson(url='/?path=/proc/self')['body']['FileExists'] - == False + self.getjson(url='/?path=/proc/self')['body']['FileExists'] == False ), 'no /proc/self' isolation['automount']['procfs'] = True diff --git a/test/test_python_isolation_chroot.py b/test/test_python_isolation_chroot.py index 1554fb72..8e5b5fce 100644 --- a/test/test_python_isolation_chroot.py +++ b/test/test_python_isolation_chroot.py @@ -35,6 +35,4 @@ class TestPythonIsolation(TestApplicationPython): ret = self.getjson(url='/?path=/app/python/ns_inspect') - assert ( - ret['body']['FileExists'] == True - ), 'application exists in rootfs' + assert ret['body']['FileExists'] == True, 'application exists in rootfs' diff --git a/test/test_python_targets.py b/test/test_python_targets.py index e5dca870..8e9ecb87 100644 --- a/test/test_python_targets.py +++ b/test/test_python_targets.py @@ -21,7 +21,7 @@ class TestPythonTargets(TestApplicationPython): ], "applications": { "targets": { - "type": "python", + "type": self.get_application_type(), "working_directory": option.test_dir + "/python/targets/", "path": option.test_dir + '/python/targets/', diff --git a/test/test_reconfigure.py b/test/test_reconfigure.py new file mode 100644 index 00000000..ab05a1c8 --- /dev/null +++ b/test/test_reconfigure.py @@ -0,0 +1,53 @@ +import time + +import pytest +from unit.applications.proto import TestApplicationProto + + +class TestReconfigure(TestApplicationProto): + prerequisites = {} + + @pytest.fixture(autouse=True) + def setup_method_fixture(self): + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes"}}, + "routes": [{"action": {"return": 200}}], + "applications": {}, + } + ) + + def clear_conf(self): + assert 'success' in self.conf({"listeners": {}, "applications": {}}) + + def test_reconfigure(self): + (_, sock) = self.http( + b"""GET / HTTP/1.1 +""", + start=True, + raw=True, + no_recv=True, + ) + + self.clear_conf() + + resp = self.http( + b"""Host: localhost +Connection: close + +""", + sock=sock, + raw=True, + ) + assert resp['status'] == 200, 'finish request' + + def test_reconfigure_2(self): + (_, sock) = self.http(b'', raw=True, start=True, no_recv=True) + + # Waiting for connection completion. + # Delay should be more than TCP_DEFER_ACCEPT. + time.sleep(1.5) + + self.clear_conf() + + assert self.get(sock=sock)['status'] == 408, 'request timeout' diff --git a/test/test_reconfigure_tls.py b/test/test_reconfigure_tls.py new file mode 100644 index 00000000..0f92a419 --- /dev/null +++ b/test/test_reconfigure_tls.py @@ -0,0 +1,105 @@ +import socket +import ssl +import time + +import pytest +from unit.applications.tls import TestApplicationTLS + + +class TestReconfigureTLS(TestApplicationTLS): + prerequisites = {'modules': {'openssl': 'any'}} + + @pytest.fixture(autouse=True) + def setup_method_fixture(self): + if 'HAS_TLSv1_2' not in dir(ssl) or not ssl.HAS_TLSv1_2: + pytest.skip('OpenSSL too old') + + self.certificate() + + assert 'success' in self.conf( + { + "listeners": { + "*:7080": { + "pass": "routes", + "tls": {"certificate": "default"}, + } + }, + "routes": [{"action": {"return": 200}}], + "applications": {}, + } + ), 'load application configuration' + + def create_socket(self): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + ssl_sock = ctx.wrap_socket( + s, server_hostname='localhost', do_handshake_on_connect=False + ) + ssl_sock.connect(('127.0.0.1', 7080)) + + return ssl_sock + + def clear_conf(self): + assert 'success' in self.conf({"listeners": {}, "applications": {}}) + + @pytest.mark.skip('not yet') + def test_reconfigure_tls_switch(self): + assert 'success' in self.conf_delete('listeners/*:7080/tls') + + (_, sock) = self.get( + headers={'Host': 'localhost', 'Connection': 'keep-alive'}, + start=True, + read_timeout=1, + ) + + assert 'success' in self.conf( + {"pass": "routes", "tls": {"certificate": "default"}}, + 'listeners/*:7080', + ) + + assert self.get(sock=sock)['status'] == 200, 'reconfigure' + assert self.get_ssl()['status'] == 200, 'reconfigure tls' + + def test_reconfigure_tls(self): + ssl_sock = self.create_socket() + + ssl_sock.sendall("""GET / HTTP/1.1\r\n""".encode()) + + self.clear_conf() + + ssl_sock.sendall( + """Host: localhost\r\nConnection: close\r\n\r\n""".encode() + ) + + assert ( + self.recvall(ssl_sock).decode().startswith('HTTP/1.1 200 OK') + ), 'finish request' + + def test_reconfigure_tls_2(self): + ssl_sock = self.create_socket() + + # Waiting for connection completion. + # Delay should be more than TCP_DEFER_ACCEPT. + time.sleep(1.5) + + self.clear_conf() + + try: + ssl_sock.do_handshake() + except ssl.SSLError: + ssl_sock.close() + success = True + + if not success: + pytest.fail('Connection is not closed.') + + def test_reconfigure_tls_3(self): + ssl_sock = self.create_socket() + ssl_sock.do_handshake() + + self.clear_conf() + + assert self.get(sock=ssl_sock)['status'] == 408, 'request timeout' diff --git a/test/test_respawn.py b/test/test_respawn.py index 5a5d6126..19d97d37 100644 --- a/test/test_respawn.py +++ b/test/test_respawn.py @@ -82,8 +82,7 @@ class TestRespawn(TestApplicationPython): skip_alert(r'process %s exited on signal 9' % pid) assert ( - self.wait_for_process(self.PATTERN_CONTROLLER, unit_pid) - is not None + self.wait_for_process(self.PATTERN_CONTROLLER, unit_pid) is not None ) assert self.get()['status'] == 200 diff --git a/test/test_return.py b/test/test_return.py index 2f7b7ae4..82bf1e64 100644 --- a/test/test_return.py +++ b/test/test_return.py @@ -83,7 +83,7 @@ Connection: close assert resp['body'] == '' def test_return_location(self): - reserved = ":/?#[]@!$&'()*+,;=" + reserved = ":/?#[]@!&'()*+,;=" unreserved = ( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789-._~" @@ -107,15 +107,15 @@ Connection: close check_location(reserved) # After first "?" all other "?" encoded. - check_location("/?" + reserved, "/?:/%3F#[]@!$&'()*+,;=") + check_location("/?" + reserved, "/?:/%3F#[]@!&'()*+,;=") check_location("???", "?%3F%3F") # After first "#" all other "?" or "#" encoded. - check_location("/#" + reserved, "/#:/%3F%23[]@!$&'()*+,;=") + check_location("/#" + reserved, "/#:/%3F%23[]@!&'()*+,;=") check_location("##?#?", "#%23%3F%23%3F") # After first "?" next "#" not encoded. - check_location("/?#" + reserved, "/?#:/%3F%23[]@!$&'()*+,;=") + check_location("/?#" + reserved, "/?#:/%3F%23[]@!&'()*+,;=") check_location("??##", "?%3F#%23") check_location("/?##?", "/?#%23%3F") @@ -161,6 +161,38 @@ Connection: close ), 'location method not allowed' assert self.get()['headers']['Location'] == 'blah' + assert 'success' in self.conf( + '"https://${host}${uri}"', 'routes/0/action/location' + ), 'location with variables' + assert self.get()['headers']['Location'] == 'https://localhost/' + + assert 'success' in self.conf( + '"/#$host"', 'routes/0/action/location' + ), 'location with encoding and a variable' + assert self.get()['headers']['Location'] == '/#localhost' + + assert ( + self.get(headers={"Host": "#foo?bar", "Connection": "close"})[ + 'headers' + ]['Location'] + == "/#%23foo%3Fbar" + ), 'location with a variable with encoding' + + assert 'success' in self.conf( + '""', 'routes/0/action/location' + ), 'location empty' + assert self.get()['headers']['Location'] == '' + + assert 'success' in self.conf( + '"${host}"', 'routes/0/action/location' + ), 'location empty with variable' + assert ( + self.get(headers={"Host": "", "Connection": "close"})['headers'][ + 'Location' + ] + == "" + ), 'location with empty variable' + def test_return_invalid(self): def check_error(conf): assert 'error' in self.conf(conf, 'routes/0/action') @@ -171,6 +203,8 @@ Connection: close check_error({"return": 1000}) check_error({"return": -1}) check_error({"return": 200, "share": "/blah"}) + check_error({"return": 200, "location": "$hos"}) + check_error({"return": 200, "location": "$hostblah"}) assert 'error' in self.conf( '001', 'routes/0/action/return' diff --git a/test/test_routing.py b/test/test_routing.py index 167d2640..fda429a4 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- import pytest -from unit.applications.proto import TestApplicationProto +from unit.applications.lang.python import TestApplicationPython from unit.option import option -class TestRouting(TestApplicationProto): +class TestRouting(TestApplicationPython): prerequisites = {'modules': {'python': 'any'}} def setup_method(self): @@ -12,7 +12,10 @@ class TestRouting(TestApplicationProto): { "listeners": {"*:7080": {"pass": "routes"}}, "routes": [ - {"match": {"method": "GET"}, "action": {"return": 200},} + { + "match": {"method": "GET"}, + "action": {"return": 200}, + } ], "applications": {}, } @@ -289,7 +292,7 @@ class TestRouting(TestApplicationProto): "listeners": {"*:7080": {"pass": "applications/" + path}}, "applications": { name: { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + '/python/empty', "working_directory": option.test_dir @@ -313,7 +316,7 @@ class TestRouting(TestApplicationProto): "listeners": {"*:7080": {"pass": "applications/" + path}}, "applications": { name: { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + '/python/empty', "working_directory": option.test_dir @@ -333,7 +336,7 @@ class TestRouting(TestApplicationProto): "listeners": {"*:7081": {"pass": "applications/empty"}}, "applications": { "empty": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + '/python/empty', "working_directory": option.test_dir + '/python/empty', @@ -387,7 +390,7 @@ class TestRouting(TestApplicationProto): { "applications": { "app": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": "/app", "module": "wsgi", @@ -430,7 +433,7 @@ class TestRouting(TestApplicationProto): { "applications": { "app": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": "/app", "module": "wsgi", @@ -476,7 +479,7 @@ class TestRouting(TestApplicationProto): "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], "applications": { "app": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": "/app", "module": "wsgi", @@ -490,11 +493,15 @@ class TestRouting(TestApplicationProto): 'routes/0/action', ), 'proxy share' assert 'error' in self.conf( - {"proxy": "http://127.0.0.1:7081", "pass": "applications/app",}, + { + "proxy": "http://127.0.0.1:7081", + "pass": "applications/app", + }, 'routes/0/action', ), 'proxy pass' assert 'error' in self.conf( - {"share": temp_dir, "pass": "applications/app"}, 'routes/0/action', + {"share": temp_dir, "pass": "applications/app"}, + 'routes/0/action', ), 'share pass' def test_routes_rules_two(self): @@ -693,7 +700,8 @@ class TestRouting(TestApplicationProto): assert self.post()['status'] == 404, 'routes edit POST' assert 'success' in self.conf_post( - {"match": {"method": "POST"}, "action": {"return": 200}}, 'routes', + {"match": {"method": "POST"}, "action": {"return": 200}}, + 'routes', ), 'routes edit configure 2' assert 'GET' == self.conf_get( 'routes/0/match/method' @@ -733,7 +741,8 @@ class TestRouting(TestApplicationProto): assert self.post()['status'] == 404, 'routes edit POST 5' assert 'success' in self.conf_post( - {"match": {"method": "POST"}, "action": {"return": 200}}, 'routes', + {"match": {"method": "POST"}, "action": {"return": 200}}, + 'routes', ), 'routes edit configure 6' assert self.get()['status'] == 404, 'routes edit GET 6' @@ -1042,9 +1051,7 @@ class TestRouting(TestApplicationProto): def check_headers(hds): hds = dict({"Host": "localhost", "Connection": "close"}, **hds) - assert ( - self.get(headers=hds)['status'] == 200 - ), 'headers array match' + assert self.get(headers=hds)['status'] == 200, 'headers array match' def check_headers_404(hds): hds = dict({"Host": "localhost", "Connection": "close"}, **hds) @@ -1262,9 +1269,7 @@ class TestRouting(TestApplicationProto): self.get(url='/?foo=bar&blah=test')['status'] == 200 ), 'multiple 2' assert self.get(url='/?foo=bar&blah')['status'] == 404, 'multiple 3' - assert ( - self.get(url='/?foo=bar&blah=tes')['status'] == 404 - ), 'multiple 4' + assert self.get(url='/?foo=bar&blah=tes')['status'] == 404, 'multiple 4' assert ( self.get(url='/?foo=b%61r&bl%61h=t%65st')['status'] == 200 ), 'multiple 5' @@ -1494,9 +1499,7 @@ class TestRouting(TestApplicationProto): sock, port = sock_port() sock2, port2 = sock_port() - self.route_match( - {"source": "127.0.0.1:" + str(port) + "-" + str(port)} - ) + self.route_match({"source": "127.0.0.1:" + str(port) + "-" + str(port)}) assert self.get(sock=sock)['status'] == 200, 'range single' assert self.get(sock=sock2)['status'] == 404, 'range single 2' @@ -1544,7 +1547,10 @@ class TestRouting(TestApplicationProto): def test_routes_source_addr(self): assert 'success' in self.conf( - {"*:7080": {"pass": "routes"}, "[::1]:7081": {"pass": "routes"},}, + { + "*:7080": {"pass": "routes"}, + "[::1]:7081": {"pass": "routes"}, + }, 'listeners', ), 'source listeners configure' @@ -1650,7 +1656,10 @@ class TestRouting(TestApplicationProto): def test_routes_source_cidr(self): assert 'success' in self.conf( - {"*:7080": {"pass": "routes"}, "[::1]:7081": {"pass": "routes"},}, + { + "*:7080": {"pass": "routes"}, + "[::1]:7081": {"pass": "routes"}, + }, 'listeners', ), 'source listeners configure' diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index ed0200d9..95c75d47 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -44,6 +44,7 @@ class TestRubyApplication(TestApplicationRuby): 'Request-Method': 'POST', 'Request-Uri': '/', 'Http-Host': 'localhost', + 'Script-Name': 'config.ru', 'Server-Protocol': 'HTTP/1.1', 'Custom-Header': 'blah', 'Rack-Version': '13', @@ -172,17 +173,16 @@ class TestRubyApplication(TestApplicationRuby): def test_ruby_application_errors_puts(self): self.load('errors_puts') - self.get() + assert self.get()['status'] == 200 assert ( - self.wait_for_record(r'\[error\].+Error in application') - is not None + self.wait_for_record(r'\[error\].+Error in application') is not None ), 'errors puts' def test_ruby_application_errors_puts_int(self): self.load('errors_puts_int') - self.get() + assert self.get()['status'] == 200 assert ( self.wait_for_record(r'\[error\].+1234567890') is not None @@ -191,11 +191,9 @@ class TestRubyApplication(TestApplicationRuby): def test_ruby_application_errors_write(self): self.load('errors_write') - self.get() - + assert self.get()['status'] == 200 assert ( - self.wait_for_record(r'\[error\].+Error in application') - is not None + self.wait_for_record(r'\[error\].+Error in application') is not None ), 'errors write' def test_ruby_application_errors_write_to_s_custom(self): @@ -206,8 +204,7 @@ class TestRubyApplication(TestApplicationRuby): def test_ruby_application_errors_write_int(self): self.load('errors_write_int') - self.get() - + assert self.get()['status'] == 200 assert ( self.wait_for_record(r'\[error\].+1234567890') is not None ), 'errors write int' @@ -215,7 +212,7 @@ class TestRubyApplication(TestApplicationRuby): def test_ruby_application_at_exit(self): self.load('at_exit') - self.get() + assert self.get()['status'] == 200 assert 'success' in self.conf({"listeners": {}, "applications": {}}) @@ -229,7 +226,8 @@ class TestRubyApplication(TestApplicationRuby): try: locales = ( subprocess.check_output( - ['locale', '-a'], stderr=subprocess.STDOUT, + ['locale', '-a'], + stderr=subprocess.STDOUT, ) .decode() .split('\n') diff --git a/test/test_ruby_hooks.py b/test/test_ruby_hooks.py index 20980ad7..b4a79ebb 100644 --- a/test/test_ruby_hooks.py +++ b/test/test_ruby_hooks.py @@ -81,7 +81,10 @@ class TestRubyHooks(TestApplicationRuby): threads = 1 self.load( - 'hooks', processes=processes, threads=threads, hooks='multiple.rb', + 'hooks', + processes=processes, + threads=threads, + hooks='multiple.rb', ) hooked = self._wait_cookie('worker_boot.*', processes) diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py index 940427f1..ea208523 100644 --- a/test/test_ruby_isolation.py +++ b/test/test_ruby_isolation.py @@ -34,11 +34,13 @@ class TestRubyIsolation(TestApplicationRuby): self.load('status_int', isolation=isolation) assert 'success' in self.conf( - '"/ruby/status_int/config.ru"', 'applications/status_int/script', + '"/ruby/status_int/config.ru"', + 'applications/status_int/script', ) assert 'success' in self.conf( - '"/ruby/status_int"', 'applications/status_int/working_directory', + '"/ruby/status_int"', + 'applications/status_int/working_directory', ) assert self.get()['status'] == 200, 'status int' diff --git a/test/test_settings.py b/test/test_settings.py index a16e35e8..ea3cfb99 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -207,9 +207,7 @@ Connection: close {"unix:" + addr: {'application': 'body_generate'}}, 'listeners' ) - assert 'success' in self.conf( - {'http': {'send_timeout': 1}}, 'settings' - ) + assert 'success' in self.conf({'http': {'send_timeout': 1}}, 'settings') data = req(addr, data_len) assert re.search(r'200 OK', data), 'send timeout status' @@ -237,14 +235,10 @@ Connection: close assert self.get()['status'] == 200, 'init' - assert 'success' in self.conf( - {'http': {'idle_timeout': 2}}, 'settings' - ) + assert 'success' in self.conf({'http': {'idle_timeout': 2}}, 'settings') assert req()['status'] == 408, 'status idle timeout' - assert 'success' in self.conf( - {'http': {'idle_timeout': 7}}, 'settings' - ) + assert 'success' in self.conf({'http': {'idle_timeout': 7}}, 'settings') assert req()['status'] == 200, 'status idle timeout 2' def test_settings_idle_timeout_2(self): @@ -259,14 +253,10 @@ Connection: close assert self.get()['status'] == 200, 'init' - assert 'success' in self.conf( - {'http': {'idle_timeout': 1}}, 'settings' - ) + assert 'success' in self.conf({'http': {'idle_timeout': 1}}, 'settings') assert req()['status'] == 408, 'status idle timeout' - assert 'success' in self.conf( - {'http': {'idle_timeout': 7}}, 'settings' - ) + assert 'success' in self.conf({'http': {'idle_timeout': 7}}, 'settings') assert req()['status'] == 200, 'status idle timeout 2' def test_settings_max_body_size(self): diff --git a/test/test_static.py b/test/test_static.py index 80f4c610..b9c78fdd 100644 --- a/test/test_static.py +++ b/test/test_static.py @@ -3,7 +3,8 @@ import shutil import socket import pytest -from conftest import unit_run, unit_stop +from conftest import unit_run +from conftest import unit_stop from unit.applications.proto import TestApplicationProto from unit.option import option from unit.utils import waitforfiles @@ -86,6 +87,22 @@ class TestStatic(TestApplicationProto): assert self.get(url='/')['body'] == '0123456789', 'before 1.26.0 2' def test_static_index(self): + def set_index(index): + assert 'success' in self.conf( + {"share": option.temp_dir + "/assets$uri", "index": index}, + 'routes/0/action', + ), 'configure index' + + set_index('README') + assert self.get()['body'] == 'readme', 'index' + + self.conf_delete('routes/0/action/index') + assert self.get()['body'] == '0123456789', 'delete index' + + set_index('') + assert self.get()['status'] == 404, 'index empty' + + def test_static_index_default(self): assert self.get(url='/index.html')['body'] == '0123456789', 'index' assert self.get(url='/')['body'] == '0123456789', 'index 2' assert self.get(url='//')['body'] == '0123456789', 'index 3' @@ -101,6 +118,18 @@ class TestStatic(TestApplicationProto): resp['headers']['Content-Type'] == 'text/html' ), 'index not found 2 Content-Type' + def test_static_index_invalid(self, skip_alert): + skip_alert(r'failed to apply new conf') + + def check_index(index): + assert 'error' in self.conf( + {"share": option.temp_dir + "/assets$uri", "index": index}, + 'routes/0/action', + ) + + check_index({}) + check_index(['index.html', '$blah']) + def test_static_large_file(self, temp_dir): file_size = 32 * 1024 * 1024 with open(temp_dir + '/assets/large', 'wb') as f: @@ -132,7 +161,8 @@ class TestStatic(TestApplicationProto): def test_static_space_in_name(self, temp_dir): os.rename( - temp_dir + '/assets/dir/file', temp_dir + '/assets/dir/fi le', + temp_dir + '/assets/dir/file', + temp_dir + '/assets/dir/fi le', ) assert waitforfiles(temp_dir + '/assets/dir/fi le') assert self.get(url='/dir/fi le')['body'] == 'blah', 'file name' @@ -153,9 +183,7 @@ class TestStatic(TestApplicationProto): assert ( self.get(url='/ di r %2Ffi le')['body'] == 'blah' ), 'slash encoded' - assert ( - self.get(url='/ di r /fi%20le')['body'] == 'blah' - ), 'file encoded' + assert self.get(url='/ di r /fi%20le')['body'] == 'blah', 'file encoded' assert ( self.get(url='/%20di%20r%20%2Ffi%20le')['body'] == 'blah' ), 'encoded' @@ -194,7 +222,8 @@ class TestStatic(TestApplicationProto): ), 'file name 2' os.rename( - temp_dir + '/assets/ di r ', temp_dir + '/assets/ди ректория', + temp_dir + '/assets/ di r ', + temp_dir + '/assets/ди ректория', ) assert waitforfiles(temp_dir + '/assets/ди ректория/фа йл') assert ( @@ -265,13 +294,14 @@ class TestStatic(TestApplicationProto): self.get(url='/')['headers']['Content-Type'] == 'text/plain' ), 'mime_types index default' assert ( - self.get(url='/dir/file')['headers']['Content-Type'] - == 'text/plain' + self.get(url='/dir/file')['headers']['Content-Type'] == 'text/plain' ), 'mime_types file in dir' def test_static_mime_types_partial_match(self): assert 'success' in self.conf( - {"text/x-blah": ["ile", "fil", "f", "e", ".file"],}, + { + "text/x-blah": ["ile", "fil", "f", "e", ".file"], + }, 'settings/http/static/mime_types', ), 'configure mime_types' assert 'Content-Type' not in self.get(url='/dir/file'), 'partial match' @@ -312,16 +342,14 @@ class TestStatic(TestApplicationProto): '"file"', 'settings/http/static/mime_types/text%2Fplain' ), 'mime_types add array element' assert ( - self.get(url='/dir/file')['headers']['Content-Type'] - == 'text/plain' + self.get(url='/dir/file')['headers']['Content-Type'] == 'text/plain' ), 'mime_types reverted' assert 'success' in self.conf( '"file"', 'settings/http/static/mime_types/text%2Fplain' ), 'configure mime_types update' assert ( - self.get(url='/dir/file')['headers']['Content-Type'] - == 'text/plain' + self.get(url='/dir/file')['headers']['Content-Type'] == 'text/plain' ), 'mime_types updated' assert ( 'Content-Type' not in self.get(url='/log.log')['headers'] @@ -345,7 +373,10 @@ class TestStatic(TestApplicationProto): 'settings/http/static/mime_types', ), 'mime_types same extensions array' assert 'error' in self.conf( - {"text/x-code": [".h", ".c", "readme"], "text/plain": "README",}, + { + "text/x-code": [".h", ".c", "readme"], + "text/plain": "README", + }, 'settings/http/static/mime_types', ), 'mime_types same extensions case insensitive' diff --git a/test/test_static_chroot.py b/test/test_static_chroot.py index 62288807..b896a9b9 100644 --- a/test/test_static_chroot.py +++ b/test/test_static_chroot.py @@ -26,13 +26,14 @@ class TestStaticChroot(TestApplicationProto): def update_action(self, share, chroot): return self.conf( - {"share": share, "chroot": chroot}, 'routes/0/action', + {"share": share, "chroot": chroot}, + 'routes/0/action', ) def get_custom(self, uri, host): - return self.get( - url=uri, headers={'Host': host, 'Connection': 'close'} - )['status'] + return self.get(url=uri, headers={'Host': host, 'Connection': 'close'})[ + 'status' + ] def test_static_chroot(self, temp_dir): assert self.get(url='/dir/file')['status'] == 200, 'default chroot' @@ -101,7 +102,8 @@ class TestStaticChroot(TestApplicationProto): ), 'chroot empty absolute' assert 'success' in self.conf( - {"share": ".$uri", "chroot": ""}, 'routes/0/action', + {"share": ".$uri", "chroot": ""}, + 'routes/0/action', ), 'configure chroot empty relative' assert ( @@ -120,13 +122,15 @@ class TestStaticChroot(TestApplicationProto): assert self.get(url='/dir/file')['status'] == 403, 'relative chroot' assert 'success' in self.conf( - {"share": ".$uri"}, 'routes/0/action', + {"share": ".$uri"}, + 'routes/0/action', ), 'configure relative share' assert self.get(url=self.test_path)['status'] == 200, 'relative share' assert 'success' in self.conf( - {"share": ".$uri", "chroot": "."}, 'routes/0/action', + {"share": ".$uri", "chroot": "."}, + 'routes/0/action', ), 'configure relative' assert self.get(url=self.test_path)['status'] == 200, 'relative' @@ -208,13 +212,16 @@ class TestStaticChroot(TestApplicationProto): def test_static_chroot_invalid(self, temp_dir): assert 'error' in self.conf( - {"share": temp_dir, "chroot": True}, 'routes/0/action', + {"share": temp_dir, "chroot": True}, + 'routes/0/action', ), 'configure chroot error' assert 'error' in self.conf( - {"share": temp_dir, "symlinks": "True"}, 'routes/0/action', + {"share": temp_dir, "symlinks": "True"}, + 'routes/0/action', ), 'configure symlink error' assert 'error' in self.conf( - {"share": temp_dir, "mount": "True"}, 'routes/0/action', + {"share": temp_dir, "mount": "True"}, + 'routes/0/action', ), 'configure mount error' assert 'error' in self.update_action( diff --git a/test/test_static_fallback.py b/test/test_static_fallback.py index 71b268c8..1f1a1df7 100644 --- a/test/test_static_fallback.py +++ b/test/test_static_fallback.py @@ -82,7 +82,10 @@ class TestStaticFallback(TestApplicationProto): def test_static_fallback_share(self, temp_dir): self.action_update( - {"share": "/blah", "fallback": {"share": temp_dir + "/assets$uri"},} + { + "share": "/blah", + "fallback": {"share": temp_dir + "/assets$uri"}, + } ) resp = self.get() diff --git a/test/test_static_mount.py b/test/test_static_mount.py index 82eda956..91cf836c 100644 --- a/test/test_static_mount.py +++ b/test/test_static_mount.py @@ -41,9 +41,7 @@ class TestStaticMount(TestApplicationProto): self._load_conf( { "listeners": {"*:7080": {"pass": "routes"}}, - "routes": [ - {"action": {"share": temp_dir + "/assets/dir$uri"}} - ], + "routes": [{"action": {"share": temp_dir + "/assets/dir$uri"}}], } ) diff --git a/test/test_static_types.py b/test/test_static_types.py index 18564a21..0e86517b 100644 --- a/test/test_static_types.py +++ b/test/test_static_types.py @@ -85,7 +85,10 @@ class TestStaticTypes(TestApplicationProto): def test_static_types_regex(self, temp_dir): self.action_update( - {"share": temp_dir + "/assets$uri", "types": ["~text/(html|plain)"]} + { + "share": temp_dir + "/assets$uri", + "types": ["~text/(html|plain)"], + } ) assert self.get(url='/file.php')['status'] == 403, 'regex fail' self.check_body('/file.html', '.html') diff --git a/test/test_tls.py b/test/test_tls.py index 01336765..56ee8298 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -175,11 +175,13 @@ basicConstraints = critical,CA:TRUE""" self.add_tls() - cert_old = self.get_server_certificate() + cert_old = ssl.get_server_certificate(('127.0.0.1', 7080)) self.certificate() - assert cert_old != self.get_server_certificate(), 'update certificate' + assert cert_old != ssl.get_server_certificate( + ('127.0.0.1', 7080) + ), 'update certificate' @pytest.mark.skip('not yet') def test_tls_certificate_key_incorrect(self): @@ -200,11 +202,13 @@ basicConstraints = critical,CA:TRUE""" self.add_tls() - cert_old = self.get_server_certificate() + cert_old = ssl.get_server_certificate(('127.0.0.1', 7080)) self.add_tls(cert='new') - assert cert_old != self.get_server_certificate(), 'change certificate' + assert cert_old != ssl.get_server_certificate( + ('127.0.0.1', 7080) + ), 'change certificate' def test_tls_certificate_key_rsa(self): self.load('empty') @@ -354,9 +358,7 @@ basicConstraints = critical,CA:TRUE""" self.add_tls(cert='int') - assert ( - self.get_ssl()['status'] == 200 - ), 'certificate chain intermediate' + assert self.get_ssl()['status'] == 200, 'certificate chain intermediate' # intermediate server @@ -385,6 +387,51 @@ basicConstraints = critical,CA:TRUE""" self.get_ssl()['status'] == 200 ), 'certificate chain intermediate server' + def test_tls_certificate_chain_long(self, temp_dir): + self.load('empty') + + self.generate_ca_conf() + + # Minimum chain length is 3. + chain_length = 10 + + for i in range(chain_length): + if i == 0: + self.certificate('root', False) + elif i == chain_length - 1: + self.req('end') + else: + self.req('int{}'.format(i)) + + for i in range(chain_length - 1): + if i == 0: + self.ca(cert='root', out='int1') + elif i == chain_length - 2: + self.ca(cert='int{}'.format(chain_length - 2), out='end') + else: + self.ca(cert='int{}'.format(i), out='int{}'.format(i + 1)) + + for i in range(chain_length - 1, 0, -1): + path = temp_dir + ( + '/end.crt' if i == chain_length - 1 else '/int{}.crt'.format(i) + ) + + with open(temp_dir + '/all.crt', 'a') as chain, open(path) as cert: + chain.write(cert.read()) + + self.set_certificate_req_context() + + assert 'success' in self.certificate_load( + 'all', 'end' + ), 'certificate chain upload' + + chain = self.conf_get('/certificates/all/chain') + assert len(chain) == chain_length - 1, 'certificate chain length' + + self.add_tls(cert='all') + + assert self.get_ssl()['status'] == 200, 'certificate chain long' + def test_tls_certificate_empty_cn(self, temp_dir): self.certificate('root', False) @@ -446,27 +493,6 @@ basicConstraints = critical,CA:TRUE""" }, 'subject alt_names' assert cert['chain'][0]['issuer']['common_name'] == 'root', 'issuer' - @pytest.mark.skip('not yet') - def test_tls_reconfigure(self): - self.load('empty') - - assert self.get()['status'] == 200, 'init' - - self.certificate() - - (resp, sock) = self.get( - headers={'Host': 'localhost', 'Connection': 'keep-alive'}, - start=True, - read_timeout=1, - ) - - assert resp['status'] == 200, 'initial status' - - self.add_tls() - - assert self.get(sock=sock)['status'] == 200, 'reconfigure status' - assert self.get_ssl()['status'] == 200, 'reconfigure tls status' - def test_tls_keepalive(self): self.load('mirror') diff --git a/test/test_tls_sni.py b/test/test_tls_sni.py index d5f205cf..dbd5d900 100644 --- a/test/test_tls_sni.py +++ b/test/test_tls_sni.py @@ -178,7 +178,8 @@ basicConstraints = critical,CA:TRUE""" self.add_tls(["localhost.com", "example.com"]) resp, sock = self.get_ssl( - headers={'Content-Length': '0', 'Connection': 'close'}, start=True, + headers={'Content-Length': '0', 'Connection': 'close'}, + start=True, ) assert resp['status'] == 200 assert ( @@ -272,9 +273,7 @@ basicConstraints = critical,CA:TRUE""" ) assert resp['status'] == 200 - assert ( - sock.getpeercert()['subjectAltName'][0][1] == 'alt.localhost.com' - ) + assert sock.getpeercert()['subjectAltName'][0][1] == 'alt.localhost.com' def test_tls_sni_invalid(self): self.config_bundles({"localhost": {"subj": "subj1", "alt_names": ''}}) diff --git a/test/test_tls_tickets.py b/test/test_tls_tickets.py index 6899eaa1..5399fae7 100644 --- a/test/test_tls_tickets.py +++ b/test/test_tls_tickets.py @@ -17,9 +17,7 @@ class TestTLSTicket(TestApplicationTLS): prerequisites = {'modules': {'openssl': 'any'}} ticket = 'U1oDTh11mMxODuw12gS0EXX1E/PkZG13cJNQ6m5+6BGlfPTjNlIEw7PSVU3X1gTE' - ticket2 = ( - '5AV0DSYIYbZWZQB7fCnTHZmMxtotb/aXjam+n2XS79lTvX3Tq9xGqpC8XKNEF2lt' - ) + ticket2 = '5AV0DSYIYbZWZQB7fCnTHZmMxtotb/aXjam+n2XS79lTvX3Tq9xGqpC8XKNEF2lt' ticket80 = '6Pfil8lv/k8zf8MndPpfXaO5EAV6dhME6zs6CfUyq2yziynQwSywtKQMqHGnJ2HR\ 49TZXi/Y4/8RSIO7QPsU51/HLR1gWIMhVM2m9yh93Bw=' @@ -182,7 +180,8 @@ class TestTLSTicket(TestApplicationTLS): def test_tls_ticket_invalid(self): def check_tickets(tickets): assert 'error' in self.conf( - {"tickets": tickets}, 'listeners/*:7080/tls/session', + {"tickets": tickets}, + 'listeners/*:7080/tls/session', ) check_tickets({}) diff --git a/test/test_upstreams_rr.py b/test/test_upstreams_rr.py index 163eb646..dd64e1d9 100644 --- a/test/test_upstreams_rr.py +++ b/test/test_upstreams_rr.py @@ -274,7 +274,7 @@ Connection: close ], "applications": { "delayed": { - "type": "python", + "type": self.get_application_type(), "processes": {"spare": 0}, "path": option.test_dir + "/python/delayed", "working_directory": option.test_dir @@ -342,7 +342,8 @@ Connection: close assert self.get()['body'] == '' assert 'success' in self.conf( - {"127.0.0.1:7083": {"weight": 2}}, 'upstreams/one/servers', + {"127.0.0.1:7083": {"weight": 2}}, + 'upstreams/one/servers', ), 'active req new server' assert 'success' in self.conf_delete( 'upstreams/one/servers/127.0.0.1:7083' diff --git a/test/test_usr1.py b/test/test_usr1.py index 9a12b747..3d190935 100644 --- a/test/test_usr1.py +++ b/test/test_usr1.py @@ -59,9 +59,7 @@ class TestUSR1(TestApplicationPython): body = 'body_for_a_log_new\n' assert self.post(body=body)['status'] == 200 - assert ( - self.wait_for_record(body, log_new) is not None - ), 'rename new' + assert self.wait_for_record(body, log_new) is not None, 'rename new' assert not os.path.isfile(log_path), 'rename old' os.kill(unit_pid, signal.SIGUSR1) diff --git a/test/test_variables.py b/test/test_variables.py index d8547b7b..71553685 100644 --- a/test/test_variables.py +++ b/test/test_variables.py @@ -17,6 +17,7 @@ class TestVariables(TestApplicationProto): "5GET": [{"action": {"return": 206}}], "GETGET": [{"action": {"return": 207}}], "localhost": [{"action": {"return": 208}}], + "9?q#a": [{"action": {"return": 209}}], }, }, ), 'configure routes' @@ -28,6 +29,14 @@ class TestVariables(TestApplicationProto): assert self.get()['status'] == 201, 'method GET' assert self.post()['status'] == 202, 'method POST' + def test_variables_request_uri(self): + self.conf_routes("\"routes$request_uri\"") + + assert self.get(url='/3')['status'] == 203, 'request_uri' + assert self.get(url='/4*')['status'] == 204, 'request_uri 2' + assert self.get(url='/4%2A')['status'] == 204, 'request_uri 3' + assert self.get(url='/9?q#a')['status'] == 209, 'request_uri query' + def test_variables_uri(self): self.conf_routes("\"routes$uri\"") @@ -103,20 +112,16 @@ class TestVariables(TestApplicationProto): def test_variables_empty(self): def update_pass(prefix): assert 'success' in self.conf( - { - "listeners": { - "*:7080": {"pass": prefix + "/$method"}, - }, - }, + {"listeners": {"*:7080": {"pass": prefix + "/$method"}}}, ), 'variables empty' - update_pass("routes"); + update_pass("routes") assert self.get(url='/1')['status'] == 404 - update_pass("upstreams"); + update_pass("upstreams") assert self.get(url='/2')['status'] == 404 - update_pass("applications"); + update_pass("applications") assert self.get(url='/3')['status'] == 404 def test_variables_invalid(self): diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 367059e6..04af26e1 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -1,4 +1,5 @@ import os +import shutil import subprocess from unit.applications.proto import TestApplicationProto @@ -6,14 +7,25 @@ from unit.option import option class TestApplicationGo(TestApplicationProto): - def prepare_env(self, script, name, static=False): - if not os.path.exists(option.temp_dir + '/go'): - os.mkdir(option.temp_dir + '/go') + @staticmethod + def prepare_env(script, name='app', static=False): + temp_dir = option.temp_dir + '/go/' + + if not os.path.exists(temp_dir): + os.mkdir(temp_dir) + + cache_dir = option.cache_dir + '/go-build' + + if not os.path.exists(cache_dir): + os.mkdir(cache_dir) env = os.environ.copy() env['GOPATH'] = option.current_dir + '/build/go' - env['GOCACHE'] = option.cache_dir + '/go' - env['GO111MODULE'] = 'auto' + env['GOCACHE'] = cache_dir + + shutil.copy2( + option.test_dir + '/go/' + script + '/' + name + '.go', temp_dir + ) if static: args = [ @@ -24,23 +36,33 @@ class TestApplicationGo(TestApplicationProto): '-ldflags', '-extldflags "-static"', '-o', - option.temp_dir + '/go/' + name, - option.test_dir + '/go/' + script + '/' + name + '.go', + temp_dir + name, + temp_dir + name + '.go', ] else: args = [ 'go', 'build', '-o', - option.temp_dir + '/go/' + name, - option.test_dir + '/go/' + script + '/' + name + '.go', + temp_dir + name, + temp_dir + name + '.go', ] + replace_path = option.current_dir + '/build/go/src/unit.nginx.org/go' + + with open(temp_dir + 'go.mod', 'w') as f: + f.write( + f"""module test/app +require unit.nginx.org/go v0.0.0 +replace unit.nginx.org/go => {replace_path} +""" + ) + if option.detailed: print("\n$ GOPATH=" + env['GOPATH'] + " " + " ".join(args)) try: - process = subprocess.run(args, env=env) + process = subprocess.run(args, env=env, cwd=temp_dir) except KeyboardInterrupt: raise @@ -61,7 +83,7 @@ class TestApplicationGo(TestApplicationProto): executable = "/go/" + name static_build = True - self.prepare_env(script, name, static=static_build) + TestApplicationGo.prepare_env(script, name, static=static_build) conf = { "listeners": {"*:7080": {"pass": "applications/" + script}}, diff --git a/test/unit/applications/tls.py b/test/unit/applications/tls.py index c7254235..93400328 100644 --- a/test/unit/applications/tls.py +++ b/test/unit/applications/tls.py @@ -52,21 +52,6 @@ class TestApplicationTLS(TestApplicationProto): def post_ssl(self, **kwargs): return self.post(wrapper=self.context.wrap_socket, **kwargs) - def get_server_certificate(self, addr=('127.0.0.1', 7080)): - - ssl_list = dir(ssl) - - if 'PROTOCOL_TLS' in ssl_list: - ssl_version = ssl.PROTOCOL_TLS - - elif 'PROTOCOL_TLSv1_2' in ssl_list: - ssl_version = ssl.PROTOCOL_TLSv1_2 - - else: - ssl_version = ssl.PROTOCOL_TLSv1_1 - - return ssl.get_server_certificate(addr, ssl_version=ssl_version) - def openssl_conf(self, rewrite=False, alt_names=[]): conf_path = option.temp_dir + '/openssl.conf' diff --git a/test/unit/applications/websockets.py b/test/unit/applications/websockets.py index aa83339c..d647ce9b 100644 --- a/test/unit/applications/websockets.py +++ b/test/unit/applications/websockets.py @@ -43,7 +43,11 @@ class TestApplicationWebsocket(TestApplicationProto): 'Sec-WebSocket-Version': 13, } - _, sock = self.get(headers=headers, no_recv=True, start=True,) + _, sock = self.get( + headers=headers, + no_recv=True, + start=True, + ) resp = '' while True: @@ -218,9 +222,7 @@ class TestApplicationWebsocket(TestApplicationProto): while pos < message_len: end = min(pos + fragmention_size, message_len) fin = end == message_len - self.frame_write( - sock, op_code, message[pos:end], fin=fin, **kwargs - ) + self.frame_write(sock, op_code, message[pos:end], fin=fin, **kwargs) op_code = self.OP_CONT pos = end diff --git a/test/unit/check/go.py b/test/unit/check/go.py index cc17f0fe..3d9d13e7 100644 --- a/test/unit/check/go.py +++ b/test/unit/check/go.py @@ -1,34 +1,8 @@ -import os -import subprocess +from unit.applications.lang.go import TestApplicationGo -def check_go(current_dir, temp_dir, test_dir): - if not os.path.exists(temp_dir + '/go'): - os.mkdir(temp_dir + '/go') +def check_go(): + process = TestApplicationGo.prepare_env('empty') - env = os.environ.copy() - env['GOPATH'] = current_dir + '/build/go' - env['GO111MODULE'] = 'auto' - - try: - process = subprocess.run( - [ - 'go', - 'build', - '-o', - temp_dir + '/go/app', - test_dir + '/go/empty/app.go', - ], - env=env, - stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, - ) - - if process.returncode == 0: - return True - - except KeyboardInterrupt: - raise - - except subprocess.CalledProcessError: - return None + if process != None and process.returncode == 0: + return True diff --git a/test/unit/control.py b/test/unit/control.py index 3008a64b..99436ca0 100644 --- a/test/unit/control.py +++ b/test/unit/control.py @@ -30,10 +30,6 @@ def args_handler(conf_func): class TestControl(TestHTTP): - - # TODO socket reuse - # TODO http client - @args_handler def conf(self, conf, url): return self.put(**self._get_args(url, conf))['body'] diff --git a/test/unit/http.py b/test/unit/http.py index dcfcd232..b4a1a17b 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -328,9 +328,7 @@ class TestHTTP: datatype = value['type'] if not isinstance(value['data'], io.IOBase): - pytest.fail( - 'multipart encoding of file requires a stream.' - ) + pytest.fail('multipart encoding of file requires a stream.') data = value['data'].read() @@ -1,5 +1,5 @@ # Copyright (C) NGINX, Inc. -NXT_VERSION=1.26.1 -NXT_VERNUM=12601 +NXT_VERSION=1.27.0 +NXT_VERNUM=12700 |