summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKonstantin Pavlov <thresh@nginx.com>2022-06-02 16:51:49 +0400
committerKonstantin Pavlov <thresh@nginx.com>2022-06-02 16:51:49 +0400
commitd9fddee1dbfc1f5d49c8f40386289d7188030952 (patch)
tree842a62b343ac33eba10e7a426a10b55bb1c46aed
parent420395ee2e7cd464e157c49bea3d74f15bf25f30 (diff)
parent0d48fe73c4450901622373e35f6ff3a944ec13d6 (diff)
downloadunit-1.27.0-1.tar.gz
unit-1.27.0-1.tar.bz2
Merged with the default branch.1.27.0-1
-rw-r--r--.gitignore4
-rw-r--r--.hgtags1
-rw-r--r--CHANGES36
-rw-r--r--CONTRIBUTING.md90
-rw-r--r--NOTICE12
-rw-r--r--README24
-rw-r--r--README.md183
-rw-r--r--auto/clang18
-rw-r--r--auto/modules/go3
-rw-r--r--auto/modules/ruby28
-rw-r--r--auto/os/test3
-rwxr-xr-xconfigure1
-rw-r--r--docs/changes.xml104
-rw-r--r--docs/unitlogo.pngbin0 -> 29600 bytes
-rw-r--r--go/go.mod1
-rw-r--r--pkg/deb/Makefile16
-rw-r--r--pkg/deb/Makefile.go2
-rw-r--r--pkg/deb/debian.module/copyright.unit-jsc1015
-rw-r--r--pkg/deb/debian.module/copyright.unit-jsc1115
-rw-r--r--pkg/deb/debian.module/copyright.unit-jsc815
-rw-r--r--pkg/deb/debian.module/rules-noarch.in3
-rwxr-xr-xpkg/deb/debian.module/rules.in3
-rw-r--r--pkg/deb/debian/copyright12
-rw-r--r--pkg/deb/debian/rules.in6
-rw-r--r--pkg/docker/Dockerfile.go1.18 (renamed from pkg/docker/Dockerfile.go1.17)12
-rw-r--r--pkg/docker/Dockerfile.jsc116
-rw-r--r--pkg/docker/Dockerfile.minimal6
-rw-r--r--pkg/docker/Dockerfile.node168
-rw-r--r--pkg/docker/Dockerfile.perl5.346
-rw-r--r--pkg/docker/Dockerfile.php8.16
-rw-r--r--pkg/docker/Dockerfile.python3.106
-rw-r--r--pkg/docker/Dockerfile.ruby3.1 (renamed from pkg/docker/Dockerfile.ruby3.0)10
-rw-r--r--pkg/docker/Makefile8
-rw-r--r--pkg/docker/template.Dockerfile4
-rw-r--r--pkg/rpm/Makefile14
-rw-r--r--pkg/rpm/Makefile.go2
-rw-r--r--pkg/rpm/Makefile.python392
-rw-r--r--pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc1015
-rw-r--r--pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc1115
-rw-r--r--pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc815
-rw-r--r--pkg/rpm/unit.spec.in4
-rw-r--r--src/java/nginx/unit/Context.java19
-rw-r--r--src/java/nginx/unit/websocket/WsRemoteEndpointImplBase.java2
-rw-r--r--src/nodejs/unit-http/loader.mjs4
-rw-r--r--src/nxt_application.c3
-rw-r--r--src/nxt_application.h3
-rw-r--r--src/nxt_array.h9
-rw-r--r--src/nxt_atomic.h60
-rw-r--r--src/nxt_buf.h84
-rw-r--r--src/nxt_buf_pool.h15
-rw-r--r--src/nxt_cache.c3
-rw-r--r--src/nxt_cert.c1
-rw-r--r--src/nxt_clang.h77
-rw-r--r--src/nxt_clone.c2
-rw-r--r--src/nxt_conf.c29
-rw-r--r--src/nxt_conf.h6
-rw-r--r--src/nxt_conf_validation.c13
-rw-r--r--src/nxt_djb_hash.h3
-rw-r--r--src/nxt_dyld.h3
-rw-r--r--src/nxt_errno.h12
-rw-r--r--src/nxt_event_engine.h36
-rw-r--r--src/nxt_external.c12
-rw-r--r--src/nxt_fastcgi_source.c3
-rw-r--r--src/nxt_fd_event.h6
-rw-r--r--src/nxt_fiber.c3
-rw-r--r--src/nxt_file.h39
-rw-r--r--src/nxt_gnutls.c4
-rw-r--r--src/nxt_h1proto.c10
-rw-r--r--src/nxt_http.h29
-rw-r--r--src/nxt_http_chunk_parse.c3
-rw-r--r--src/nxt_http_parse.c3
-rw-r--r--src/nxt_http_request.c276
-rw-r--r--src/nxt_http_return.c177
-rw-r--r--src/nxt_http_route.c354
-rw-r--r--src/nxt_http_static.c78
-rw-r--r--src/nxt_http_variables.c20
-rw-r--r--src/nxt_job.h9
-rw-r--r--src/nxt_list.h12
-rw-r--r--src/nxt_log.h21
-rw-r--r--src/nxt_log_moderation.h6
-rw-r--r--src/nxt_lvlhsh.c69
-rw-r--r--src/nxt_lvlhsh.h6
-rw-r--r--src/nxt_main_process.c32
-rw-r--r--src/nxt_malloc.c13
-rw-r--r--src/nxt_malloc.h27
-rw-r--r--src/nxt_mem_map.h9
-rw-r--r--src/nxt_mem_zone.c27
-rw-r--r--src/nxt_mem_zone.h3
-rw-r--r--src/nxt_mp.c16
-rw-r--r--src/nxt_openssl.c32
-rw-r--r--src/nxt_port.c5
-rw-r--r--src/nxt_queue.h60
-rw-r--r--src/nxt_router.c85
-rw-r--r--src/nxt_service.h3
-rw-r--r--src/nxt_signal.h6
-rw-r--r--src/nxt_socket.h6
-rw-r--r--src/nxt_source.h3
-rw-r--r--src/nxt_sprintf.c41
-rw-r--r--src/nxt_string.h69
-rw-r--r--src/nxt_thread.h33
-rw-r--r--src/nxt_thread_id.h6
-rw-r--r--src/nxt_thread_time.h9
-rw-r--r--src/nxt_time.h12
-rw-r--r--src/nxt_time_parse.c6
-rw-r--r--src/nxt_unit.c84
-rw-r--r--src/nxt_unit.h2
-rw-r--r--src/nxt_unix.h12
-rw-r--r--src/nxt_var.c3
-rw-r--r--src/nxt_vector.h9
-rw-r--r--src/nxt_work_queue.h7
-rw-r--r--src/perl/nxt_perl_psgi.c190
-rw-r--r--src/perl/nxt_perl_psgi_layer.c64
-rw-r--r--src/perl/nxt_perl_psgi_layer.h28
-rw-r--r--src/python/nxt_python.c13
-rw-r--r--src/python/nxt_python_asgi.c19
-rw-r--r--src/ruby/nxt_ruby.c45
-rw-r--r--src/ruby/nxt_ruby.h1
-rw-r--r--src/ruby/nxt_ruby_stream_io.c10
-rw-r--r--src/test/nxt_rbtree1_test.c6
-rw-r--r--test/conftest.py86
-rw-r--r--test/perl/input_buffered_read/psgi.pl17
-rw-r--r--test/perl/input_close/psgi.pl8
-rw-r--r--test/php/opcache/index.php2
-rw-r--r--test/php/opcache/preload/chdir.php7
-rw-r--r--test/php/opcache/preload/fastcgi_finish_request.php5
-rw-r--r--test/python/204_no_content/asgi.py12
-rw-r--r--test/ruby/errors_write/config.ru2
-rw-r--r--test/ruby/input_gets/config.ru1
-rw-r--r--test/ruby/variables/config.ru1
-rw-r--r--test/test_asgi_application.py6
-rw-r--r--test/test_asgi_lifespan.py8
-rw-r--r--test/test_asgi_targets.py9
-rw-r--r--test/test_asgi_websockets.py98
-rw-r--r--test/test_client_ip.py28
-rw-r--r--test/test_go_application.py9
-rw-r--r--test/test_go_isolation.py4
-rw-r--r--test/test_http_header.py16
-rw-r--r--test/test_java_application.py46
-rw-r--r--test/test_java_isolation_rootfs.py5
-rw-r--r--test/test_java_websockets.py90
-rw-r--r--test/test_node_application.py4
-rw-r--r--test/test_node_es_modules.py5
-rw-r--r--test/test_node_websockets.py90
-rw-r--r--test/test_perl_application.py19
-rw-r--r--test/test_php_application.py94
-rw-r--r--test/test_php_targets.py4
-rw-r--r--test/test_proxy.py19
-rw-r--r--test/test_proxy_chunked.py14
-rw-r--r--test/test_python_application.py34
-rw-r--r--test/test_python_isolation.py7
-rw-r--r--test/test_python_isolation_chroot.py4
-rw-r--r--test/test_python_targets.py2
-rw-r--r--test/test_reconfigure.py53
-rw-r--r--test/test_reconfigure_tls.py105
-rw-r--r--test/test_respawn.py3
-rw-r--r--test/test_return.py42
-rw-r--r--test/test_routing.py57
-rw-r--r--test/test_ruby_application.py22
-rw-r--r--test/test_ruby_hooks.py5
-rw-r--r--test/test_ruby_isolation.py6
-rw-r--r--test/test_settings.py20
-rw-r--r--test/test_static.py59
-rw-r--r--test/test_static_chroot.py27
-rw-r--r--test/test_static_fallback.py5
-rw-r--r--test/test_static_mount.py4
-rw-r--r--test/test_static_types.py5
-rw-r--r--test/test_tls.py82
-rw-r--r--test/test_tls_sni.py7
-rw-r--r--test/test_tls_tickets.py7
-rw-r--r--test/test_upstreams_rr.py5
-rw-r--r--test/test_usr1.py4
-rw-r--r--test/test_variables.py21
-rw-r--r--test/unit/applications/lang/go.py44
-rw-r--r--test/unit/applications/tls.py15
-rw-r--r--test/unit/applications/websockets.py10
-rw-r--r--test/unit/check/go.py36
-rw-r--r--test/unit/control.py4
-rw-r--r--test/unit/http.py4
-rw-r--r--version4
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__/
diff --git a/.hgtags b/.hgtags
index 04b825f4..532c8f34 100644
--- a/.hgtags
+++ b/.hgtags
@@ -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
diff --git a/CHANGES b/CHANGES
index d7fa5641..98208fa9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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
+
diff --git a/NOTICE b/NOTICE
index ef97b24f..73274140 100644
--- a/NOTICE
+++ b/NOTICE
@@ -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.
+
diff --git a/auto/clang b/auto/clang
index 8639457a..1a05b5a3 100644
--- a/auto/clang
+++ b/auto/clang
@@ -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"
diff --git a/configure b/configure
index c9264d59..bc21e579 100755
--- a/configure
+++ b/configure
@@ -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 &lt;defan@nginx.com&gt;">
+
+<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 &lt;defan@nginx.com&gt;">
+
+<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 &lt;defan@nginx.com&gt;">
diff --git a/docs/unitlogo.png b/docs/unitlogo.png
new file mode 100644
index 00000000..dbd87fd8
--- /dev/null
+++ b/docs/unitlogo.png
Binary files differ
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()
diff --git a/version b/version
index 77ca3d3f..1d59a58f 100644
--- a/version
+++ b/version
@@ -1,5 +1,5 @@
# Copyright (C) NGINX, Inc.
-NXT_VERSION=1.26.1
-NXT_VERNUM=12601
+NXT_VERSION=1.27.0
+NXT_VERNUM=12700