summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_conf_validation.c (follow)
AgeCommit message (Collapse)AuthorFilesLines
2024-08-20http: Add "if" option to the "match" objectZhidao HONG1-0/+4
This feature allows users to specify conditions to check if one route is matched. It is used the same way as the "if" option in the access log. Example: { "match": { "if": "`${headers['User-Agent'].split('/')[0] == 'curl'}`" }, "action": { "return": 204 } }
2024-08-20conf, router: Make the listen(2) backlog configurableAndrew Clayton1-0/+32
@oopsoop2 on GitHub reported a performance issue related to the default listen(2) backlog size of 511 on nginx. They found that increasing it helped, nginx has a config option to configure this. They would like to be able to do the same on Unit (which also defaults to 511 on some systems). This seems reasonable. NOTE: On Linux before commit 97c15fa38 ("socket: Use a default listen backlog of -1 on Linux") we defaulted to 511. Since that commit we default to the Kernels default, which before 5.4 is 128 and after is 4096. This adds a new per-listener 'backlog' config option, e.g { "listeners": { "[::1]:8080": { "pass": "routes", "backlog": 1024 }, } ... } This doesn't effect the control socket. Closes: https://github.com/nginx/unit/issues/1384 Reported-by: <https://github.com/oopsoop2> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-08-19router: Make the number of router threads configurableAndrew Clayton1-0/+27
Unit generally creates an extra number of router threads (to handle client connections, not incl the main thread) to match the number of available CPUs. There are cases when this can go wrong, e.g on a high CPU count machine and Unit is being effectively limited to a few CPUs via the cgroups cpu controller. So Unit may create a large number of router threads when they are only going to effectively run on a couple of CPUs or so. There may be other cases where you would like to tweak the number of router threads, depending on your workload. As it turns out it looks like it was intended to be made configurable but was just never hooked up to the config system. This adds a new '/settings/listen_threads' config option which can be set like { "listen": { ... }, "settings": { "listen_threads": 2, ... }, ... } Before this patch (on a four cpu system) $ ps -efL | grep router andrew 419832 419829 419832 0 5 Aug12 pts/10 00:00:00 unit: router andrew 419832 419829 419833 0 5 Aug12 pts/10 00:00:00 unit: router andrew 419832 419829 419834 0 5 Aug12 pts/10 00:00:00 unit: router andrew 419832 419829 445145 0 5 03:31 pts/10 00:00:00 unit: router andrew 419832 419829 445146 0 5 03:31 pts/10 00:00:00 unit: router After, with a threads setting of 2 $ ps -efL | grep router andrew 419832 419829 419832 0 3 Aug12 pts/10 00:00:00 unit: router andrew 419832 419829 419833 0 3 Aug12 pts/10 00:00:00 unit: router andrew 419832 419829 419834 0 3 Aug12 pts/10 00:00:00 unit: router Closes: https://github.com/nginx/unit/issues/1042 Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-07-02python: Support application factoriesGourav1-0/+11
Adds support for the app factory pattern to the Python language module. A factory is a callable that returns a WSGI or ASGI application object. Unit does not support passing arguments to factories. Setting the `factory` option to `true` instructs Unit to treat the configured `callable` as a factory. For example: "my-app": { "type": "python", "path": "/srv/www/", "module": "hello", "callable": "create_app", "factory": true } This is similar to other WSGI / ASGI servers. E.g., $ uvicorn --factory hello:create_app $ gunicorn 'hello:create_app()' The factory setting defaults to false. Closes: https://github.com/nginx/unit/issues/1106 Link: <https://github.com/nginx/unit/pull/1336#issuecomment-2179381605> [ Commit message - Dan / Minor code tweaks - Andrew ] Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-06-20http: Support chunked request bodiesZhidao HONG1-0/+3
This is a temporary support for chunked request bodies by converting to Content-Length. This allows for processing of such requests until a more permanent solution is developed. A new configuration option "chunked_transform" has been added to enable this feature. The option can be set as follows: { "settings": { "chunked_transform": true } } By default, this option is set to false, which retains the current behaviour of rejecting chunked requests with a '411 Length Required' status code. Please note that this is an experimental implementation. Reviewed-by: Andrew Clayton <a.clayton@nginx.com>
2024-04-25Constify a bunch of static local variablesAndrew Clayton1-15/+15
A common pattern was to declare variables in functions like static nxt_str_t ... Not sure why static, as they were being treated more like string literals (and of course they are _not_ thread safe), let's actually make them constants (qualifier wise). This handles core code conversion. Reviewed-by: Zhidao HONG <z.hong@f5.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-04-25configuration: Constify numerous pointersAndrew Clayton1-5/+5
Mark numerous function argument pointers as 'const' in the configuration sub-system. This also does the same with a few functions in src/nxt_conf_validation.c that are required to accomplish the below, attacking the rest is an exercise for another day... While this is a worthwhile hardening exercise in its own right, the main impetus for this is to 'constify' some local function variables which are currently defined with 'static' storage class and turn them into 'static const', which will be done in a subsequent patch. Reviewed-by: Zhidao HONG <z.hong@f5.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-04-10HTTP: Added variable validation to the response_headers optionZhidao HONG1-1/+12
This is to improve error messages for response headers configuration. Take the configuration as an example: { "response_headers": { "a": "$b" } } Previously, when applying it the user would see this error message: failed to apply previous configuration After this change, the user will see this improved error message: the previous configuration is invalid: Unknown variable "b" in the "a" value
2024-02-21Wasm-wc: Wire up the language module to the config systemAndrew Clayton1-0/+17
This exposes the various WebAssembly Component Model language module specific options. The application type is "wasm-wasi-component". There is a "component" option that is required, this specifies the full path to the WebAssembly component to be run. This component should be in binary format, i.e a .wasm file. There is also currently one optional option "access" Due to the sandboxed nature of WebAssembly, by default Wasm modules/components don't have any access to the underlying filesystem. There is however a capabilities based mechanism[0] for allowing such access. This adds a config option to the 'wasm-wasi-component' application type (same as for 'wasm'); 'access.filesystem' which takes an array of directory paths that are then made available to the wasm module/component. This access works recursively, i.e everything under a specific path is allowed access to. Example config might look like "applications": { "my-wasm-component": { "type": "wasm-wasi-component", "component": "/path/to/component.wasm", "access" { "filesystem": [ "/tmp", "/var/tmp" ] } } } The actual mechanism used allows directories to be mapped differently in the guest. But at the moment we don't support that and just map say /tmp to /tmp. This can be revisited if it's something users clamour for. [0]: <https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-capabilities.md> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-02-08Configuration: Fix validation of "processes"Alejandro Colomar1-1/+1
It's an integer, not a floating number. Fixes: 68c6b67ffc84 ("Configuration: support for rational numbers.") Closes: https://github.com/nginx/unit/issues/1115 Link: <https://github.com/nginx/unit/pull/1116> Reviewed-by: Zhidao Hong <z.hong@f5.com> Reviewed-by: Andrew Clayton <a.clayton@nginx.com> Cc: Dan Callahan <d.callahan@f5.com> Cc: Valentin Bartenev <vbartenev@gmail.com> Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-02-05Configuration: Don't corrupt abstract socket namesAlejandro Colomar1-6/+11
The commit that added support for Unix sockets accepts abstract sockets using '@' in the config, but we stored it internally using '\0'. We want to support abstract sockets transparently to the user, so that if the user configures unitd with '@', if we receive a query about the current configuration, the user should see the same exact thing that was configured. So, this commit avoids the transformation in the internal state file, storing user input pristine, and we only transform the '@' in temporary strings. This commit fixes another bug, where we try to connect to abstract sockets with a trailing '\0' in their name due to calling twice nxt_sockaddr_parse() on the same string. By calling that function only once with each copy of the string, we have fixed that bug. The following code was responsible for this bug, which the second time it was called, considered these sockets as file-backed (not abstract) Unix socket, and so appended a '\0' to the socket name. $ grepc -tfd nxt_sockaddr_unix_parse . | grep -A10 @ if (path[0] == '@') { path[0] = '\0'; socklen--; #if !(NXT_LINUX) nxt_thread_log_error(NXT_LOG_ERR, "abstract unix domain sockets are not supported"); return NULL; #endif } sa = nxt_sockaddr_alloc(mp, socklen, addr->length); This bug was found thanks to some experiment about using 'const' for some strings. And here's some history: - 9041d276fc6a ("nxt_sockaddr_parse() introducted.") This commit introduced support for abstract Unix sockets, but they only worked as "servers", and not as "listeners". We corrupted the JSON config file, and stored a \u0000. This also caused calling connect(2) with a bogus trailing null byte, which tried to connect to a different abstract socket. - d8e0768a5bae ("Fixed support for abstract Unix sockets.") This commit (partially) fixed support for abstract Unix sockets, so they they worked also as listeners. We still corrupted the JSON config file, and stored a \u0000. This caused calling connect(2) (and now bind(2) too) with a bogus trailing null byte. - e2aec6686a4d ("Storing abstract sockets with @ internally.") This commit fixed the problem by which we were corrupting the config file, but only for "listeners", not for "servers". (It also fixes the issue about the terminating '\0'.) We completely forgot about "servers", and other callers of the same function. To reproduce the problem, I used the following config: ```json { "listeners": { "*:80": { "pass": "routes/u" }, "unix:@abstract": { "pass": "routes/a" } }, "routes": { "u": [{ "action": { "pass": "upstreams/u" } }], "a": [{ "action": { "return": 302, "location": "/i/am/not/at/home/" } }] }, "upstreams": { "u": { "servers": { "unix:@abstract": {} } } } } ``` And then check the state file: $ sudo cat /opt/local/nginx/unit/master/var/lib/unit/conf.json \ | jq . \ | grep unix; "unix:@abstract": { "unix:\u0000abstract": {} After this patch, the state file has a '@' as expected: $ sudo cat /opt/local/nginx/unit/unix/var/lib/unit/conf.json \ | jq . \ | grep unix; "unix:@abstract": { "unix:@abstract": {} Regarding the trailing null byte, here are some tests: $ sudo strace -f -e 'bind,connect' /opt/local/nginx/unit/d8e0/sbin/unitd \ |& grep abstract; [pid 22406] bind(10, {sa_family=AF_UNIX, sun_path=@"abstract\0"}, 12) = 0 [pid 22410] connect(134, {sa_family=AF_UNIX, sun_path=@"abstract\0"}, 12) = 0 ^C $ sudo killall unitd $ sudo strace -f -e 'bind,connect' /opt/local/nginx/unit/master/sbin/unitd \ |& grep abstract; [pid 22449] bind(10, {sa_family=AF_UNIX, sun_path=@"abstract"}, 11) = 0 [pid 22453] connect(134, {sa_family=AF_UNIX, sun_path=@"abstract\0"}, 12) = -1 ECONNREFUSED (Connection refused) ^C $ sudo killall unitd $ sudo strace -f -e 'bind,connect' /opt/local/nginx/unit/unix/sbin/unitd \ |& grep abstract; [pid 22488] bind(10, {sa_family=AF_UNIX, sun_path=@"abstract"}, 11) = 0 [pid 22492] connect(134, {sa_family=AF_UNIX, sun_path=@"abstract"}, 11) = 0 ^C Fixes: 9041d276fc6a ("nxt_sockaddr_parse() introducted.") Fixes: d8e0768a5bae ("Fixed support for abstract Unix sockets.") Fixes: e2aec6686a4d ("Storing abstract sockets with @ internally.") Link: <https://github.com/nginx/unit/pull/1108> Reviewed-by: Andrew Clayton <a.clayton@nginx.com> Cc: Liam Crilly <liam.crilly@nginx.com> Cc: Zhidao Hong <z.hong@f5.com> Signed-off-by: Alejandro Colomar <alx@kernel.org>
2024-01-30Configuration: Remove procmap validation codeAndrew Clayton1-71/+2
With the previous commit which introduced the use of the NXT_CONF_VLDT_REQUIRED flag, we no longer need to do this separate validation, it's only purpose was to check if the three uidmap/gidmap settings had been provided. Reviewed-by: Zhidao Hong <z.hong@f5.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-01-30Configuration: Use the NXT_CONF_VLDT_REQUIRED flag for procmapAndrew Clayton1-0/+3
Use the NXT_CONF_VLDT_REQUIRED flag on the app_procmap members. These three settings are required. These are for the uidmap & gidmap settings in the config. Suggested-by: Zhidao HONG <z.hong@f5.com> Reviewed-by: Zhidao Hong <z.hong@f5.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2024-01-29HTTP: enhanced access log with conditional filtering.Zhidao HONG1-0/+37
This feature allows users to specify conditions to control if access log should be recorded. The "if" option supports a string and JavaScript code. If its value is empty, 0, false, null, or undefined, the logs will not be recorded. And the '!' as a prefix inverses the condition. Example 1: Only log requests that sent a session cookie. { "access_log": { "if": "$cookie_session", "path": "..." } } Example 2: Do not log health check requests. { "access_log": { "if": "`${uri == '/health' ? false : true}`", "path": "..." } } Example 3: Only log requests when the time is before 22:00. { "access_log": { "if": "`${new Date().getHours() < 22}`", "path": "..." } } or { "access_log": { "if": "!`${new Date().getHours() >= 22}`", "path": "..." } } Closes: https://github.com/nginx/unit/issues/594
2023-12-14HTTP: added TSTR validation flag to the rewrite option.Zhidao HONG1-0/+1
This is to improve error messages for rewrite configuration. Take the configuration as an example: { "rewrite": "`${a + " } Previously, when applying it the user would see this error message: failed to apply previous configuration After this change, the user will see this improved error message: the previous configuration is invalid: "SyntaxError: Unexpected end of input in default:1" in the "rewrite" value.
2023-08-17Wasm: Add support for directory access.Andrew Clayton1-0/+16
Due to the sandboxed nature of WebAssembly, by default WASM modules don't have any access to the underlying filesystem. There is however a capabilities based mechanism[0] for allowing such access. This adds a config option to the 'wasm' application type; 'access.filesystem' which takes an array of directory paths that are then made available to the WASM module. This access works recursively, i.e everything under a specific path is allowed access to. Example config might look like "access" { "filesystem": [ "/tmp", "/var/tmp" ] } The actual mechanism used allows directories to be mapped differently in the guest. But at the moment we don't support that and just map say /tmp to /tmp. This can be revisited if it's something users clamour for. Network sockets are another resource that may be controlled in this manner, for example there is a wasi_config_preopen_socket() function, however this requires the runtime to open the network socket then effectively pass this through to the guest. This is something that can be revisited in the future if users desire it. [0]: <https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-capabilities.md> Reviewed-by: Alejandro Colomar <alx@nginx.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2023-08-17Wasm: Wire up Wasm language module support to the config system.Andrew Clayton1-0/+39
This exposes various WebAssembly language module specific options. The application type is "wasm". There is a "module" option that is required, this specifies the full path to the WebAssembly module to be run. This module should be in binary format, i.e a .wasm file. There are also currently eight function handlers that can be specified. Three of them are _required_ 1) request_handler The main driving function. This may be called multiple times for a single HTTP request if the request is larger than the shared memory. 2) malloc_handler Used to allocate a chunk of memory at language module startup. This memory is allocated from the WASM modules address space and is what is sued for communicating between the WASM module (the guest) and Unit (the host). 3) free_handler Used to free the memory from above at language module shutdown. Then there are the following five _optional_ handlers 1) module_init_handler If set, called at language module startup. 2) module_end_handler If set, called at language module shutdown. 3) request_init_handler If set, called at the start of request. Called only once per HTTP request. 4) request_end_handler If set, called once all of a request has been sent to the WASM module. 5) response_end_handler If set, called at the end of a request, once the WASM module has sent all its headers and data. Example config "applications": { "luw-echo-request": { "type": "wasm", "module": "/path/to/unit-wasm/examples/c/luw-echo-request.wasm", "request_handler": "luw_request_handler", "malloc_handler": "luw_malloc_handler", "free_handler": "luw_free_handler", "module_init_handler": "luw_module_init_handler", "module_end_handler": "luw_module_end_handler", } } Reviewed-by: Alejandro Colomar <alx@nginx.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2023-08-09HTTP: controlling response headers support.Zhidao HONG1-0/+37
2023-05-08NJS: supported loadable modules.Zhidao HONG1-13/+61
2023-04-20HTTP: added basic URI rewrite.Zhidao HONG1-4/+14
This commit introduced the basic URI rewrite. It allows users to change request URI. Note the "rewrite" option ignores the contained query if any and the query from the request is preserverd. An example: "routes": [ { "match": { "uri": "/v1/test" }, "action": { "return": 200 } }, { "action": { "rewrite": "/v1$uri", "pass": "routes" } } ] Reviewed-by: Alejandro Colomar <alx@nginx.com>
2023-04-25Allow to remove the version string in HTTP responses.Andrew Clayton1-0/+3
Normally Unit responds to HTTP requests by including a header like Server: Unit/1.30.0 however it can sometimes be beneficial to withhold the version information and in this case just respond with Server: Unit This patch adds a new "settings.http" boolean option called server_version, which defaults to true, in which case the full version information is sent. However this can be set to false, e.g "settings": { "http": { "server_version": false } }, in which case Unit responds without the version information as the latter example above shows. Link: <https://www.ietf.org/rfc/rfc9110.html#section-10.2.4> Closes: <https://github.com/nginx/unit/issues/158> Reviewed-by: Alejandro Colomar <alx@nginx.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2023-04-11Add per-application logging.Andrew Clayton1-0/+6
Currently when running in the foreground, unit application processes will send stdout to the current TTY and stderr to the unit log file. That behaviour won't change. When running as a daemon, unit application processes will send stdout to /dev/null and stderr to the unit log file. This commit allows to alter the latter case of unit running as a daemon, by allowing applications to redirect stdout and/or stderr to specific log files. This is done via two new application options, 'stdout' & 'stderr', e.g "applications": { "myapp": { ... "stdout": "/path/to/log/unit/app/stdout.log", "stderr": "/path/to/log/unit/app/stderr.log" } } These log files are created by the application processes themselves and thus the log directories need to be writable by the user (and or group) of the application processes. E.g $ sudo mkdir -p /path/to/log/unit/app $ sudo chown APP_USER /path/to/log/unit/app These need to be setup before starting unit with the above config. Currently these log files do not participate in log-file rotation (SIGUSR1), that may change in a future commit. In the meantime these logs can be rotated using the traditional copy/truncate method. NOTE: You may or may not see stuff printed to stdout as stdout was traditionally used by CGI applications to communicate with the webserver. Closes: <https://github.com/nginx/unit/issues/197> Closes: <https://github.com/nginx/unit/issues/846> Reviewed-by: Alejandro Colomar <alx@nginx.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2023-03-21HTTP: added route logging.Alejandro Colomar1-0/+3
- Configuration: added "/config/settings/http/log_route". Type: bool Default: false This adds configurability to the error log. It allows enabling and disabling logs related to how the router performs selection of the routes. - HTTP: logging request line. Log level: [notice] The request line is essential to understand which logs correspond to which request when reading the logs. - HTTP: logging route that's been discarded. Log level: [info] - HTTP: logging route whose action is selected. Log level: [notice] - HTTP: logging when "fallback" action is taken. Log level: [notice] Closes: <https://github.com/nginx/unit/issues/758> Link: <https://github.com/nginx/unit/pull/824> Link: <https://github.com/nginx/unit/pull/839> Suggested-by: Timo Stark <t.stark@nginx.com> Suggested-by: Mark L Wood-Patrick <mwoodpatrick@gmail.com> Suggested-by: Liam Crilly <liam@nginx.com> Tested-by: Liam Crilly <liam@nginx.com> Acked-by: Artem Konev <a.konev@f5.com> Cc: Andrew Clayton <a.clayton@nginx.com> Cc: Andrei Zeliankou <zelenkov@nginx.com> Reviewed-by: Zhidao Hong <z.hong@f5.com> Signed-off-by: Alejandro Colomar <alx@nginx.com>
2023-01-30NJS: adding the missing vm destruction.Zhidao HONG1-4/+14
This commit fixed the njs memory leak happened in the config validation, updating and http requests.
2022-12-14Python: Added "prefix" to configuration.OutOfFocus41-0/+37
This patch gives users the option to set a `"prefix"` attribute for Python applications, either at the top level or for specific `"target"`s. If the attribute is present, the value of `"prefix"` must be a string beginning with `"/"`. If the value of the `"prefix"` attribute is longer than 1 character and ends in `"/"`, the trailing `"/"` is stripped. The purpose of the `"prefix"` attribute is to set the `SCRIPT_NAME` context value for WSGI applications and the `root_path` context value for ASGI applications, allowing applications to properly route requests regardless of the path that the server uses to expose the application. The context value is only set if the request's URL path begins with the value of the `"prefix"` attribute. In all other cases, the `SCRIPT_NAME` or `root_path` values are not set. In addition, for WSGI applications, the value of `"prefix"` will be stripped from the beginning of the request's URL path before it is sent to the application. Reviewed-by: Andrei Zeliankou <zelenkov@nginx.com> Reviewed-by: Artem Konev <artem.konev@nginx.com> Signed-off-by: Alejandro Colomar <alx@nginx.com>
2022-12-13Configuration: made large_header_buffers a valid setting.Andrew Clayton1-0/+3
This is an extension to the previous commit, which made large_header_buffer_size a valid configuration setting. This commit makes a related value, large_header_buffers, a valid configuration setting. While large_header_buffer_size effectively limits the maximum size of any single header (although unit will try to pack multiple headers into a buffer if they wholly fit). large_header_buffers limits how many of these 'large' buffers are available. It makes sense to also allow this to be user set. large_header_buffers is already set by the configuration system in nxt_router.c it just isn't set as a valid config option in nxt_conf_validation.c With this change users can set this option in their config if required by the following "settings": { "http": { "large_header_buffers": 8 } }, It retains its default value of 4 if this is not set. NOTE: This is being released as undocumented and subject to change as it exposes internal workings of unit. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2022-12-13Configuration: made large_header_buffer_size a valid setting.Andrew Clayton1-0/+3
@JanMikes and @tagur87 on GitHub both reported issues with long URLs that were exceeding the 8192 byte large_header_buffer_size setting, which resulted in a HTTP 431 error (Request Header Fields Too Large). This can be resolved in the code by updating the following line in src/nxt_router.c::nxt_router_conf_create() skcf->large_header_buffer_size = 8192; However, requiring users to modify unit and install custom versions is less than ideal. We could increase the value, but to what? This commit takes the option of allowing the user to set this option in their config by making large_header_buffer_size a valid configuration setting. large_header_buffer_size is already set by the configuration system in nxt_router.c it just isn't set as a valid config option in nxt_conf_validation.c With this change users can set this option in their config if required by the following "settings": { "http": { "large_header_buffer_size": 16384 } }, It retains its default value of 8192 bytes if this is not set. With this commit, without the above setting or too low a value, with a long URL you get a 431 error. With the above setting set to a large enough value, the request is successful. NOTE: This setting really determines the maximum size of any single header _value_. Also, unit will try and place multiple values into a buffer _if_ they fully fit. NOTE: This is being released as undocumented and subject to change as it exposes internal workings of unit. Closes: <https://github.com/nginx/unit/issues/521> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2022-12-10Isolation: wired up cgroup support to the config system.Andrew Clayton1-0/+62
This hooks the cgroup support up to the config system so it can actually be used. To make use of this in unit a new "cgroup" section has been added to the isolation configuration. e.g "applications": { "python": { "type": "python", "processes": 5, "path": "/opt/unit/unit-cgroup-test/", "module": "app", "isolation": { "cgroup": { "path": "app/python" } } } } Now there are two ways to specify the path, relative, like the above (without a leading '/') and absolute (with a leading '/'). In the above case the "python" application is placed into its own cgroup under CGROUP_ROOT/<main unit process cgroup>/app/python. Whereas if you specified say "path": "/unit/app/python" Then the python application would be placed under CGROUP_ROOT/unit/app/python The first option allows you to easily take advantage of any resource limits that have already been configured for unit. With the second method (absolute pathname) if you know of an already existing cgroup where you'd like to place it, you can, e.g "path": "/system.slice/unit/python" Where system.slice has already been created by systemd and may already have some overall system limits applied which would also apply to unit. Limits apply down the hierarchy and lower groups can't exceed the previous group limits. So what does this actually look like? Lets take the unit-calculator application[0] and have each of its applications placed into their own cgroup. If we give each application a new section like "isolation": { "cgroup": { "path": "/unit/unit-calculator/add" } } changing the path for each one, we can visualise the result with the systemd-cgls command, e.g │ └─session-5.scope (#4561) │ ├─ 6667 sshd: andrew [priv] │ ├─ 6684 sshd: andrew@pts/0 │ ├─ 6685 -bash │ ├─ 12632 unit: main v1.28.0 [/opt/unit/sbin/unitd --control 127.0.0.1:808> │ ├─ 12634 unit: controller │ ├─ 12635 unit: router │ ├─ 13550 systemd-cgls │ └─ 13551 less ├─unit (#4759) │ └─unit-calculator (#5037) │ ├─subtract (#5069) │ │ ├─ 12650 unit: "subtract" prototype │ │ └─ 12651 unit: "subtract" application │ ├─multiply (#5085) │ │ ├─ 12653 unit: "multiply" prototype │ │ └─ 12654 unit: "multiply" application │ ├─divide (#5101) │ │ ├─ 12671 unit: "divide" prototype │ │ └─ 12672 node divide.js │ ├─sqroot (#5117) │ │ ├─ 12679 unit: "sqroot" prototype │ │ └─ 12680 /home/andrew/src/unit-calculator/sqroot/sqroot │ └─add (#5053) │ ├─ 12648 unit: "add" prototype │ └─ 12649 unit: "add" application We used an absolute path so the cgroups will be created relative to the main cgroupfs mount, e.g /sys/fs/cgroup We can see that the main unit processes are in the same cgroup as the shell from where they were started, by default child process are placed into the same cgroup as the parent. Then we can see that each application has been placed into its own cgroup under /sys/fs/cgroup Taking another example of a simple 5 process python application, with "isolation": { "cgroup": { "path": "app/python" } } Here we have specified a relative path and thus the python application will be placed below the existing cgroup that contains the main unit process. E.g │ │ │ ├─app-glib-cinnamon\x2dcustom\x2dlauncher\x2d3-43951.scope (#90951) │ │ │ │ ├─ 988 unit: main v1.28.0 [/opt/unit/sbin/unitd --no-daemon] │ │ │ │ ├─ 990 unit: controller │ │ │ │ ├─ 991 unit: router │ │ │ │ ├─ 43951 xterm -bg rgb:20/20/20 -fg white -fa DejaVu Sans Mono │ │ │ │ ├─ 43956 bash │ │ │ │ ├─ 58828 sudo -i │ │ │ │ ├─ 58831 -bash │ │ │ │ └─app (#107351) │ │ │ │ └─python (#107367) │ │ │ │ ├─ 992 unit: "python" prototype │ │ │ │ ├─ 993 unit: "python" application │ │ │ │ ├─ 994 unit: "python" application │ │ │ │ ├─ 995 unit: "python" application │ │ │ │ ├─ 996 unit: "python" application │ │ │ │ └─ 997 unit: "python" application [0]: <https://github.com/lcrilly/unit-calculator> Reviewed-by: Alejandro Colomar <alx@nginx.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2022-11-20Basic njs support.Zhidao HONG1-11/+22
2022-11-20Var: separating nxt_tstr_t from nxt_var_t.Zhidao HONG1-3/+3
It's for the introduction of njs support. For each option that supports native variable and JS template literals introduced next, it's unified as template string. No functional changes.
2022-11-04Removed the unsafe nxt_memchr() wrapper for memchr(3).Alejandro Colomar1-6/+6
The casts are unnecessary, since memchr(3)'s argument is 'const void *'. It might have been necessary in the times of K&R, where 'void *' didn't exist. Nowadays, it's unnecessary, and _very_ unsafe, since casts can hide all classes of bugs by silencing most compiler warnings. The changes from nxt_memchr() to memchr(3) were scripted: $ find src/ -type f \ | grep '\.[ch]$' \ | xargs sed -i 's/nxt_memchr/memchr/' Reviewed-by: Andrew Clayton <a.clayton@nginx.com> Signed-off-by: Alejandro Colomar <alx@nginx.com>
2022-10-14Configuration: stopped automatic migration to the "share" behavior.Zhidao HONG1-21/+0
This commit removed the $uri auto-append for the "share" option introduced in rev be6409cdb028. The main reason is that it causes problems when preparing Unit configurations to be loaded at startup from the state directory. E.g. Docker. A valid conf.json file with $uri references will end up with $uri$uri due to the auto-append.
2022-08-18Storing abstract sockets with @ internally.Alejandro Colomar1-1/+6
We accept both "\u0000socket-name" and "@socket-name" as abstract unix sockets. The first one is passed to the kernel pristine, while the second is transformed '@'->'\0'. The commit that added support for unix sockets accepts both variants, but we internally stored it in the same way, using "\u0000..." for both. We want to support abstract sockets transparently to the user, so that if the user configures unitd with '@', if we receive a query about the current configuration, the user should see the same exact thing that was configured. So, this commit avoids the transformation in the internal state file, storing user input pristine, and we only transform the '@' for a string that will be used internally (not user-visible). This commit (indirectly) fixes a small bug, where we created abstract sockets with a trailing '\0' in their name due to calling twice nxt_sockaddr_parse() on the same string. By calling that function only once with each copy of the string, we have fixed that bug.
2022-07-28Log: customizable access log format.Zhidao HONG1-1/+80
2022-07-26Supporting UNIX sockets in address matching.Alejandro Colomar1-0/+5
This closes #645 issue on GitHub. (Also moved a changelog line that was misplaced in a previous commit.)
2022-07-14Var: dynamic variables support.Zhidao HONG1-1/+6
This commit adds the variables $arg_NAME, $header_NAME, and $cookie_NAME.
2022-06-20Router: forwared header replacement.Zhidao HONG1-0/+50
2022-05-30Static: supporting new "index" option.Alejandro Colomar1-0/+3
This supports a new option "index" that configures a custom index file name to be served when a directory is requested. This initial support only allows a single fixed string. An example: { "share": "/www/data/static/$uri", "index": "lookatthis.htm" } When <example.com/foo/bar/> is requested, </www/data/static/foo/bar/lookatthis.html> is served. Default is "index.html". === nxt_conf_validator.c: Accept "index" as a member of "share", and make sure it's a string. === I tried this feature in my own computer, where I tried the following: - Setting "index" to "lookatthis.htm", and check that the correct file is being served (check both a different name and a different extension). - Not setting "index", and check that <index.html> is being served. - Settind "index" to an array of strings, and check that the configuration fails: { "error": "Invalid configuration.", "detail": "The \"index\" value must be a string, but not an array." }
2022-04-28Supporting variables in "location".Alejandro Colomar1-0/+1
............ Description: ............ Before this commit, the encoded URI could be calculated at configuration time. Now, since variables can only be resolved at request time, we have different situations: - "location" contains no variables: In this case, we still encode the URI in the conf structure, at configuration time, and then we just copy the resulting string to the ctx structure at request time. - "location" contains variables: In this case, we compile the var string at configure time, then when we resolve it at request time, and then we encode the string. In both cases, as was being done before, if the string is empty, either before or after resolving variables, we skip the encoding. ........... Usefulness: ........... An example of why this feature may be useful is redirecting HTTP to HTTPS with something like: "action": { "return": 301, "location": "https://${host}${uri}" } ..... Bugs: ..... This feature conflicts with the relevant RFCs in the following: '$' is used for Unit variables, but '$' is a reserved character in a URI, to be used as a sub-delimiter. However, it's almost never used as that, and in fact, other parts of Unit already conflict with '$' being a reserved character for use as a sub-delimiter, so this is at least consistent in that sense. VBart suggested an easy workaround if we ever need it: adding a variable '$sign' which resolves to a literal '$'. ...... Notes: ...... An empty string is handled as if "location" wasn't specified at all, so no Location header is sent. This is incorrect, and the code is slightly misleading. The Location header consists of a URI-reference[1], which might be a relative one, which itself might consist of an empty string[2]. [1]: <https://www.rfc-editor.org/rfc/rfc7231#section-7.1.2> [2]: <https://stackoverflow.com/a/43338457> Now that we have variables, it's more likely that an empty Location header will be requested, and we should handle it correctly. I think in a future commit we should modify the code to allow differentiating between an unset "location" and an empty one, which should be treated as any other "location" string. ................. Testing (manual): ................. { "listeners": { "*:80": { "pass": "routes/str" }, "*:81": { "pass": "routes/empty" }, "*:82": { "pass": "routes/var" }, "*:83": { "pass": "routes/enc-str" }, "*:84": { "pass": "routes/enc-var" } }, "routes": { "str": [ { "action": { "return": 301, "location": "foo" } } ], "empty": [ { "action": { "return": 301, "location": "" } } ], "var": [ { "action": { "return": 301, "location": "$host" } } ], "enc-str": [ { "action": { "return": 301, "location": "f%23o#o" } } ], "enc-var": [ { "action": { "return": 301, "location": "f%23o${host}#o" } } ] } } $ curl --dump-header - localhost:80 HTTP/1.1 301 Moved Permanently Location: foo Server: Unit/1.27.0 Date: Thu, 07 Apr 2022 23:30:06 GMT Content-Length: 0 $ curl --dump-header - localhost:81 HTTP/1.1 301 Moved Permanently Server: Unit/1.27.0 Date: Thu, 07 Apr 2022 23:30:08 GMT Content-Length: 0 $ curl --dump-header - localhost:82 HTTP/1.1 301 Moved Permanently Location: localhost Server: Unit/1.27.0 Date: Thu, 07 Apr 2022 23:30:15 GMT Content-Length: 0 $ curl --dump-header - -H "Host: bar" localhost:82 HTTP/1.1 301 Moved Permanently Location: bar Server: Unit/1.27.0 Date: Thu, 07 Apr 2022 23:30:23 GMT Content-Length: 0 $ curl --dump-header - -H "Host: " localhost:82 HTTP/1.1 301 Moved Permanently Server: Unit/1.27.0 Date: Thu, 07 Apr 2022 23:30:29 GMT Content-Length: 0 $ curl --dump-header - localhost:83 HTTP/1.1 301 Moved Permanently Location: f%23o#o Server: Unit/1.27.0 Date: Sat, 09 Apr 2022 11:22:23 GMT Content-Length: 0 $ curl --dump-header - -H "Host: " localhost:84 HTTP/1.1 301 Moved Permanently Location: f%23o#o Server: Unit/1.27.0 Date: Sat, 09 Apr 2022 11:22:44 GMT Content-Length: 0 $ curl --dump-header - -H "Host: alx" localhost:84 HTTP/1.1 301 Moved Permanently Location: f%23oalx#o Server: Unit/1.27.0 Date: Sat, 09 Apr 2022 11:22:52 GMT Content-Length: 0 $ curl --dump-header - -H "Host: a#l%23x" localhost:84 HTTP/1.1 301 Moved Permanently Location: f%2523oa#l%2523x%23o Server: Unit/1.27.0 Date: Sat, 09 Apr 2022 11:23:09 GMT Content-Length: 0 $ curl --dump-header - -H "Host: b##ar" localhost:82 HTTP/1.1 301 Moved Permanently Location: b#%23ar Server: Unit/1.27.0 Date: Sat, 09 Apr 2022 11:25:01 GMT Content-Length: 0
2022-04-27Added NXT_MAYBE_UNUSED for __attribute__((__unused__)).Alejandro Colomar1-1/+2
When testing some configurations of compilers and OSes, I noticed that clang(1) 13 on Debian caused a function to be compiled but unused, and the compiler triggered a compile error. To avoid that error, use __attribute__((__unused__)). Let's call our wrapper NXT_MAYBE_UNUSED, since it describes itself more precisely than the GCC attribute name. It's also the name that C2x (likely C23) has given to the standard attribute, which is [[maybe_unused]], so it's also likely to be more readable because of that name being in ISO C.
2022-04-26Fixed indentation.Alejandro Colomar1-3/+3
Some lines (incorrectly) had an indentation of 3 or 5, or 7 or 9, or 11 or 13, or 15 or 17 spaces instead of 4, 8, 12, or 16. Fix them. Found with: $ find src -type f | xargs grep -n '^ [^ ]'; $ find src -type f | xargs grep -n '^ [^ *]'; $ find src -type f | xargs grep -n '^ [^ ]'; $ find src -type f | xargs grep -n '^ [^ *]'; $ find src -type f | xargs grep -n '^ [^ +]'; $ find src -type f | xargs grep -n '^ [^ *+]'; $ find src -type f | xargs grep -n '^ [^ +]'; $ find src -type f | xargs grep -n '^ [^ *+]';
2021-11-05Router: matching query string support.Zhidao HONG1-0/+5
The "query" option matches decoded arguments, including plus ('+') to space (' '). Like "uri", it can be a string or an array of strings.
2021-11-05Configuration: improved matching pattern error messages.Zhidao HONG1-22/+51
2021-10-26Custom implementation of Base64 decoding function.Valentin Bartenev1-7/+3
Compared to the previous implementation based on OpenSSL, the new implementation has these advantages: 1. Strict and reliable detection of invalid strings, including strings with less than 4 bytes of garbage at the end; 2. Allows to use Base64 strings without '=' padding.
2021-10-09Configuration: automatic migration to the new "share" behavior.Zhidao HONG1-0/+21
2021-10-01Static: multiple paths in the "share" option.Zhidao HONG1-2/+49
2021-09-30Static: variables in the "share" option.Zhidao HONG1-0/+1
This commit supports variable in the "share" option, the finding path to file serve is the value from "share". An example: { "share": "/www/data/static$uri" }
2021-09-28Static: variables in the "chroot" option.Zhidao HONG1-13/+26
2021-09-14Fixing build with glibc 2.34.Max Romanov1-3/+4
Explicitly using the sysconf() call to obtain the minimum thread stack size instead of the PTHREAD_STACK_MIN macro. This closes #576 PR on GitHub.
2021-08-17Added TLS session tickets support.Andrey Suvorov1-0/+73