Commit Graph

135 Commits

Author SHA1 Message Date
Andrew Clayton
47ff51009f Wasm: Add support for directory access.
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-17 13:09:49 +01:00
Andrew Clayton
e99854afdf Wasm: Wire up Wasm language module support to the config system.
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-17 13:09:49 +01:00
Zhidao HONG
a28bef097c HTTP: controlling response headers support. 2023-08-09 14:37:16 +08:00
Zhidao HONG
a3c3a29493 NJS: supported loadable modules. 2023-05-08 16:00:25 +08:00
Zhidao HONG
14d6d97bac HTTP: added basic URI rewrite.
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-20 23:20:41 +08:00
Andrew Clayton
1a485fed6a Allow to remove the version string in HTTP responses.
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-25 13:59:43 +01:00
Andrew Clayton
45c45eaeb4 Add per-application logging.
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-04-11 19:08:32 +01:00
Alejandro Colomar
0ebce31c92 HTTP: added route logging.
-  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-03-21 13:02:38 +01:00
Zhidao HONG
789762ff3d NJS: adding the missing vm destruction.
This commit fixed the njs memory leak happened in the config validation, updating and http requests.
2023-01-30 11:16:01 +08:00
OutOfFocus4
6dae517ebd Python: Added "prefix" to configuration.
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-14 11:30:30 +01:00
Andrew Clayton
f88371ff1d Configuration: made large_header_buffers a valid setting.
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-13 13:36:30 +00:00
Andrew Clayton
dad7ef9a12 Configuration: made large_header_buffer_size a valid setting.
@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-13 13:36:30 +00:00
Andrew Clayton
f67a01b88f Isolation: wired up cgroup support to the config system.
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-12-10 14:00:20 +00:00
Zhidao HONG
4d6d146e92 Basic njs support. 2022-11-20 23:16:51 +08:00
Zhidao HONG
4735931ace Var: separating nxt_tstr_t from nxt_var_t.
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-20 23:15:01 +08:00
Alejandro Colomar
ebf02266a2 Removed the unsafe nxt_memchr() wrapper for memchr(3).
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-11-04 00:30:50 +01:00
Zhidao HONG
c03ebf7ffe Configuration: stopped automatic migration to the "share" behavior.
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-10-14 14:00:02 +08:00
Alejandro Colomar
e2aec6686a Storing abstract sockets with @ internally.
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-08-18 18:56:24 +02:00
Zhidao HONG
3f8cf62c03 Log: customizable access log format. 2022-07-28 11:05:04 +08:00
Alejandro Colomar
6e36584a2e Supporting UNIX sockets in address matching.
This closes #645 issue on GitHub.

(Also moved a changelog line that was misplaced in a previous commit.)
2022-07-26 16:24:33 +02:00
Zhidao HONG
45b89e3257 Var: dynamic variables support.
This commit adds the variables $arg_NAME, $header_NAME, and $cookie_NAME.
2022-07-14 04:32:49 +08:00
Zhidao HONG
9d2672a701 Router: forwared header replacement. 2022-06-20 13:22:13 +08:00
Alejandro Colomar
9af5f36951 Static: supporting new "index" option.
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-05-30 12:42:18 +02:00
Alejandro Colomar
6fb7777ce7 Supporting variables in "location".
............
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-28 20:40:01 +02:00
Alejandro Colomar
0b79735b50 Added NXT_MAYBE_UNUSED for __attribute__((__unused__)).
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-27 01:14:22 +02:00
Alejandro Colomar
a3d19f71a2 Fixed indentation.
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 '^                 [^ *+]';
2022-04-26 12:38:48 +02:00
Zhidao HONG
aee908bcbd Router: matching query string support.
The "query" option matches decoded arguments, including plus ('+') to
space (' ').  Like "uri", it can be a string or an array of strings.
2021-11-05 22:56:34 +08:00
Zhidao HONG
85ab3f5ab5 Configuration: improved matching pattern error messages. 2021-11-05 10:51:41 +08:00
Valentin Bartenev
7bf6253941 Custom implementation of Base64 decoding function.
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-26 15:43:44 +03:00
Zhidao HONG
5fa5b1464f Configuration: automatic migration to the new "share" behavior. 2021-10-09 10:44:31 +08:00
Zhidao HONG
95e6535909 Static: multiple paths in the "share" option. 2021-10-01 10:03:55 +08:00
Zhidao HONG
c5220944d2 Static: variables in the "share" option.
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-30 22:17:28 +08:00
Zhidao HONG
37144d6849 Static: variables in the "chroot" option. 2021-09-28 23:08:26 +08:00
Max Romanov
d21ebcce83 Fixing build with glibc 2.34.
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-09-14 19:35:49 +03:00
Andrey Suvorov
e0aa132172 Added TLS session tickets support. 2021-08-17 16:52:32 -07:00
Oisin Canty
ca373aaccd Router: client IP address replacement.
This commit introduces the replacement of the client address based on the value
of a specified HTTP header.  This is intended for use when Unit is placed
behind a reverse proxy like nginx or a CDN.

You must specify the source addresses of the trusted proxies.  This can be
accomplished with any valid IP pattern supported by Unit's match block:

["10.0.0.1", "10.4.0.0/16", "!192.168.1.1"]

The feature is configured per listener.

The client address replacement functionality only operates when there is a
source IP match and the specified header is present.  Typically this would be
an 'X-Forwarded-For' header.

{
    "listeners": {
        "127.0.0.1:8080": {
            "client_ip": {
                "header": "X-Forwarded-For",
                "source": [
                    "10.0.0.0/8"
                ]
            },
            "pass": "applications/my_app"
        },
    }
}

If a request occurs and Unit receives a header like below:

"X-Forwarded-For: 84.123.23.23"

By default, Unit trusts the last rightmost IP in the header, so REMOTE_ADDR
will be set to 84.123.23.23 if the connection originated from 10.0.0.0/8.

If Unit runs behind consecutive reverse proxies and receives a header similar
to the following:

"X-Forwarded-For: 84.123.23.23, 10.0.0.254"

You will need to enable "recursive" checking, which walks the header from
last address to first and chooses the first non-trusted address it finds.

{
    "listeners": {
        "127.0.0.1:8080": {
            "client_ip": {
                "header": "X-Forwarded-For",
                "source": [
                    "10.0.0.0/8"
                ]
                "recursive": true,
            },
            "pass": "applications/my_app"
        },
    }
}

If a connection from 10.0.0.0/8 occurs, the chain is walked.  Here, 10.0.0.254
is also a trusted address so the client address will be replaced with
84.123.23.23.

If all IP addresses in the header are trusted, the client address is set to
the first address in the header:

If 10.0.0.0/8 is trusted and "X-Forwarded-For: 10.0.0.3, 10.0.0.2, 10.0.0.1",
the client address will be replaced with 10.0.0.3.
2021-08-12 08:23:16 +00:00
Zhidao HONG
a3df6efc8d Router: split nxt_http_static_conf_t from nxt_http_action_t.
No functional changes.
2021-07-23 09:14:43 +08:00
Andrey Suvorov
c37ff7ed0e Enabling configure TLS sessions.
To support TLS sessions, Unit uses the OpenSSL built-in session cache; the
cache_size option defines the number sessions to store.  To disable the feather,
the option must be zero.
2021-07-21 15:22:52 -07:00
Oisin Canty
655e321075 Ruby: process and thread lifecycle hooks.
This feature allows one to specify blocks of code that are called when certain
lifecycle events occur.  A user configures a "hooks" property on the app
configuration that points to a script.  This script will be evaluated on boot
and should contain blocks of code that will be called on specific events.

An example of configuration:

{
    "type": "ruby",
    "processes": 2,
    "threads": 2,
    "user": "vagrant",
    "group": "vagrant",
    "script": "config.ru",
    "hooks": "hooks.rb",
    "working_directory": "/home/vagrant/unit/rbhooks",
    "environment": {
        "GEM_HOME": "/home/vagrant/.ruby"
    }
}

An example of a valid "hooks.rb" file follows:

File.write("./hooks.#{Process.pid}", "hooks evaluated")

on_worker_boot do
    File.write("./worker_boot.#{Process.pid}", "worker booted")
end

on_thread_boot do
    File.write("./thread_boot.#{Process.pid}.#{Thread.current.object_id}",
               "thread booted")
end

on_thread_shutdown do
    File.write("./thread_shutdown.#{Process.pid}.#{Thread.current.object_id}",
               "thread shutdown")
end

on_worker_shutdown do
    File.write("./worker_shutdown.#{Process.pid}", "worker shutdown")
end

This closes issue #535 on GitHub.
2021-07-02 12:57:55 +00:00
Andrey Suvorov
3f7ccf142f Enabling SSL_CTX configuration by using SSL_CONF_cmd().
To perform various configuration operations on SSL_CTX, OpenSSL provides
SSL_CONF_cmd().  Specifically, to configure ciphers for a listener,
"CipherString" and "Ciphersuites" file commands are used:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html


This feature can be configured in the "tls/conf_commands" section.
2021-05-26 11:19:47 -07:00
Oisin Canty
d67a0c8711 Static: handled unknown MIME types when MIME-filtering active. 2021-05-26 16:48:11 +00:00
Oisin Canty
2fe76afaa6 Configuration: generalized application "targets" validation. 2021-05-25 13:21:29 +00:00
Oisin Canty
f60389a782 Python: support for multiple targets. 2021-05-20 13:02:45 +00:00
Oisin Canty
b9d5eb285a Static: implemented MIME filtering 2021-05-06 14:22:21 +00:00
Zhidao HONG
53279af5d4 Static: support for openat2() features.
Support for chrooting, rejecting symlinks, and rejecting crossing mounting
points on a per-request basis during static file serving.
2021-04-29 22:04:34 +08:00
Andrey Suvorov
d2b0882d89 Added ability to configure multiple certificates on a listener.
The certificate is selected by matching the arriving SNI to the common name and
the alternatives names.  If no certificate matches the name, the first bundle in
the array is chosen.
2021-03-24 13:19:36 -07:00
Max Romanov
fddde539c9 Fixing NetBSD compatibility.
Instead of PTHREAD_STACK_MIN define, NetBSD requires to get minimum stack
size using sysctl(_SC_THREAD_STACK_MIN).

This change originally proposed by Juraj Lutter <juraj@lutter.sk>.
2021-03-02 18:30:34 +03:00
Valentin Bartenev
cac762ab7e Python: multiple values in the "path" option. 2020-12-22 17:53:41 +03:00
Axel Duch
e3af18834d Router: matching regular expressions support. 2020-11-17 15:03:30 +00:00
Valentin Bartenev
fb80502513 HTTP parser: allowed more characters in header field names.
Previously, all requests that contained in header field names characters other
than alphanumeric, or "-", or "_" were rejected with a 400 "Bad Request" error
response.

Now, the parser allows the same set of characters as specified in RFC 7230,
including: "!", "#", "$", "%", "&", "'", "*", "+", ".", "^", "`", "|", and "~".
Header field names that contain only these characters are considered valid.

Also, there's a new option introduced: "discard_unsafe_fields".  It accepts
boolean value and it is set to "true" by default.

When this option is "true", all header field names that contain characters
in valid range, but other than alphanumeric or "-" are skipped during parsing.
When the option is "false", these header fields aren't skipped.

Requests with non-valid characters in header field names according to
RFC 7230 are rejected regardless of "discard_unsafe_fields" setting.

This closes #422 issue on GitHub.
2020-11-17 16:50:06 +03:00