Age | Commit message (Collapse) | Author | Files | Lines |
|
This closes #645 issue on GitHub.
(Also moved a changelog line that was misplaced in a previous commit.)
|
|
In src/nxt_http_route_addr.c::nxt_http_route_addr_pattern_parse() there
was potentially undefined behaviour when shifting a 32 bit value by 32
bits, this could happen if cidr_prefix was 0.
Promote the shiftee to unsigned long long to avoid this issue.
|
|
Allow $dollar (or ${dollar}) to translate to a literal $ to allow
support for sub-delimiters in URIs.
It is possible to have URLs like
https://example.com/path/15$1588/9925$2976.html
and thus it would be useful to be able to specify them in various bits
of the unit config such as the location setting.
However this hadn't been possible due to $ being used to denote
variables for substitution. E.g $host.
As was noted in the below GitHub issue it was suggested by @VBart to
use $sign to represent a literal $, however I feel $dollar is more
appropriate so we have a variable named after the thing it represents,
also @tippexs found[0] that &dollar is used in HTML to represent a $, so
there is some somewhat related precedent.
(The other idea to use $$ was rejected in my original pull-request[1]
for this issue.)
This means the above URL could be specified as
https://example.com/path/15${dollar}1588/9925${dollar}2976.html
in the unit config.
This is done by adding a variable called 'dollar' which is loaded into
the variables hash table which translates into a literal $.
This is then handled in nxt_var_next_part() where variables are parsed
for lookup and $dollar is set for substitution by a literal '$'. Actual
variable substitution happens in nxt_var_query_finish().
[0]: https://github.com/nginx/unit/pull/693#issuecomment-1130412323
[1]: https://github.com/nginx/unit/pull/693
Closes: https://github.com/nginx/unit/issues/675
|
|
|
|
|
|
The #endif was misplaced by accident during a refactor:
<https://github.com/nginx/unit/commit/029942f4eb7196c2cff0d0e26bc6ff274138f7d8>.
clang(1)'s -Wunreachable-code-break (implied by -Weverything) catches
that, but it is only produced for code compiled without support
for Unix sockets, which is probably the reason it was undetected:
no-one seems to be compiling Unit without Unix sockets support (at
least with clang(1)).
|
|
User-space programs should use the SYS_*form, as documented in
syscall(2). That also adds compatibility to non-Linux systems.
|
|
posix_spawn(3POSIX) was introduced by POSIX.1d
(IEEE Std 1003.1d-1999), and was later consolidated in
POSIX.1-2001, requiring it in all POSIX-compliant systems.
It's safe to assume it's always available, more than 20 years
after its standardization.
Link: <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/spawn.h.html>
|
|
This commit adds the following variables:
$remote_addr, $time_local, $request_line, $status,
$body_bytes_sent, $header_referer, $header_user_agent.
|
|
This commit adds the variables $arg_NAME, $header_NAME, and $cookie_NAME.
|
|
No functional changes.
|
|
Closes: <https://github.com/nginx/unit/issues/676>
|
|
As was pointed out by the cppcheck[0] static code analysis utility there
was a useless assignment in nxt_unit_request_read(). The size parameter
is passed in by value and was being modified without being used again.
[0]: https://cppcheck.sourceforge.io/
|
|
As was pointed out by the cppcheck[0] static code analysis utility, lib
was being set in nxt_unit_shm_open() regardless of platform when in fact
it's only used when (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN).
Move the variable declaration & definition to be within the
#if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN)
block.
[0]: https://cppcheck.sourceforge.io/
|
|
In src/nxt_sockaddr.c::nxt_job_sockaddr_inet_parse() there is a check
that port > 0 then there is a check that port < 1 || port > 65535, well
we _know_ it can't be less than 1.
|
|
As was pointed out by the cppcheck[0] static code analysis utility we
can mark a couple of variables as 'const'. This acts as a hint to the
compiler about our intentions and the compiler will tell us when we
deviate from them.
[0]: https://cppcheck.sourceforge.io/
|
|
As was pointed out by the cppcheck[0] static code analysis utility we
can mark numerous function parameters as 'const'. This acts as a hint to
the compiler about our intentions and the compiler will tell us when we
deviate from them.
[0]: https://cppcheck.sourceforge.io/
|
|
The code for finding the extension made a few assumptions that are
no longer true. It didn't account for pathnames that didn't
contain '/', including the empty string, or the NULL string. That
code was used with "share", which always had a '/', but now it's
also used with "index", which should not have a '/' in it.
This fix works by limiting the search to the beginning of the
string, so that if no '/' is found in it, it doesn't continue
searching before the beginning of the string.
This also happens to work for NULL. It is technically Undefined
Behavior, as we rely on `NULL + 0 == NULL` and `NULL - NULL == 0`.
But that is the only sane behavior for an implementation, and all
existing POSIX implementations will Just Work for this code.
Relying on this UB is useful, because we don't need to add an
explicit check for NULL, and therefore we have faster code.
Although the current code can't have a NULL, I expect that when we
add support for variables in the index, it will be NULL in some
cases.
Link: <https://stackoverflow.com/q/67291052/6872717>
The same code seems to be defined behavior in C++, which normally
will share implementation in the compiler for these cases, and
therefore it is really unlikely to be in trouble.
Link: <https://stackoverflow.com/q/59409034/6872717>
|
|
|
|
This makes the replacement of forwarded request header
like client_ip and protocol more generic.
It's a prerequirement for protocol replacement.
No functional changes.
|
|
No functional changes.
|
|
No functional changes.
|
|
The message tracking is unused since 1d84b9e4b459 commit.
This fixes the issue found by Coverity (CID 376263).
|
|
No functional changes.
|
|
No functional changes.
|
|
No functional changes.
|
|
Before Node.js v16.14.0 the "format" value in defaultResolve
was ignored so error was hidden. For more information see:
https://github.com/nodejs/node/pull/40980
|
|
|
|
This supports a new variable $request_uri that contains the path
and the query (See RFC 3986, section 3). Its contents are percent
encoded. This is useful for example to redirect HTTP to HTTPS:
{
"return": "301",
"location": "https://$host$request_uri"
}
When <http://example.com/foo%23bar?baz> is requested, the server
redirects to <https://example.com/foo%23bar?baz>.
===
Testing:
//diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c
//index 82c9156..adeb3a1 100644
//--- a/src/nxt_http_return.c
//+++ b/src/nxt_http_return.c
//@@ -196,6 +196,7 @@ nxt_http_return_send_ready(nxt_task_t *task,
void *obj, void *data)
// field->value = ctx->encoded.start;
// field->value_length = ctx->encoded.length;
// }
//+ fprintf(stderr, "ALX: target[%1$i]: <%2$.*1$s>\n",
(int)r->target.length, r->target.start);
//
// r->state = &nxt_http_return_send_state;
//
{
"listeners": {
"*:81": {
"pass": "routes/ru"
}
},
"routes": {
"ru": [{
"action": {
"return": 301,
"location": "$request_uri"
}
}]
}
}
$ curl -i http://localhost:81/*foo%2Abar?baz#arg
HTTP/1.1 301 Moved Permanently
Location: /*foo%2Abar?baz
Server: Unit/1.27.0
Date: Mon, 30 May 2022 16:04:30 GMT
Content-Length: 0
$ sudo cat /usr/local/unit.log | grep ALX
ALX: target[15]: </*foo%2Abar?baz>
|
|
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."
}
|
|
Before this patch, if "index" was a file, but not a regular file
nor a directory, so it may have been for example a FIFO, Unit
returned 404. But if "index" was a directory, Unit returned 301.
For consistency, this patch makes Unit return 404 for every
non-regular file, including directories.
|
|
Casts are usually very dangerous, disabling most compiler warnings
and basically removing type safety. This change adds 'const' to a
pointer where we don't need to write, improving type safety, and
that also allows removing some casts.
|
|
No functional changes.
|
|
|
|
nxt_str_null() setted the loc.start pointer to NULL, which was
being passed to memcpy(3) through nxt_debug(). That caused
Undefined Behavior, so we now pass an empty string.
|
|
An empty string in Location was being handled specially by not sending a
Location header. This may occur after variable resolution, so we need to
consider this scenario.
The obsolete RFC 2616 defined the Location header as consisting of an absolute
URI <https://www.rfc-editor.org/rfc/rfc2616#section-14.30>, which cannot be an
empty string. However, the current RFC 7231 allows the Location to be a
relative URI <https://www.rfc-editor.org/rfc/rfc7231#section-7.1.2>, and a
relative URI may be an empty string <https://stackoverflow.com/a/43338457>.
Due to these considerations, this patch allows sending an empty Location header
without handling this case specially. This behavior will probably be more
straightforward to users, too. It also simplifies the code, which is now more
readable, fast, and conformant to the current RFC. We're skipping an
allocation at request time in a common case such as "action": {"return": 404}
|
|
Having a configurable index filename will require adding an index
field to this structure. The most natural name for that field is
'index', so the current index field should be renamed to allow for
that. A sensible name is 'share_idx', since it's the index of the
shares array in 'nxt_http_static_conf_t'.
Instead of 'share_index' I opted for the shorter 'share_idx'.
Also, when 'index' allows an array of filenames in a following
commit, another similar variable 'index_idx' should be created,
and having a different prefix and suffix seems more readable than
for example 'index_index'.
|
|
This closes #654 issue on Github.
|
|
A new behaviour was introduced in OpenSSL 1.1.1e, when a peer does not send
close_notify before closing the connection. Previously, it was to return
SSL_ERROR_SYSCALL with errno 0, known since at least OpenSSL 0.9.7, and is
handled gracefully in unitd. Now it returns SSL_ERROR_SSL with a distinct
reason SSL_R_UNEXPECTED_EOF_WHILE_READING ("unexpected eof while reading").
This leads to critical errors seen in nginx within various routines such as
SSL_do_handshake(), SSL_read(), SSL_shutdown(). The behaviour was restored
in OpenSSL 1.1.1f, but presents in OpenSSL 3.0 by default.
Use of the SSL_OP_IGNORE_UNEXPECTED_EOF option added in OpenSSL 3.0 allows
setting a compatible behaviour to return SSL_ERROR_ZERO_RETURN:
https://git.openssl.org/?p=openssl.git;a=commitdiff;h=09b90e0
See for additional details: https://github.com/openssl/openssl/issues/11381
|
|
The macro is used to suppress deprecation warnings with OpenSSL 3.0.
Unlike OPENSSL_API_COMPAT, it works well with OpenSSL built with no-deprecated.
In particular, it doesn't unhide various macros in OpenSSL includes, which are
meant to be hidden under OPENSSL_NO_DEPRECATED.
|
|
|
|
We had a mix of styles for declaring function-like macros:
Style A:
#define \
foo() \
do { \
... \
} while (0)
Style B:
#define foo() \
do { \
... \
} while (0)
We had a similar number of occurences of each style:
$ grep -rnI '^\w*(.*\\' | wc -l
244
$ grep -rn 'define.*(.*)' | wc -l
239
(Those regexes aren't perfect, but a very decent approximation.)
Real examples:
$ find src -type f | xargs sed -n '/^nxt_double_is_zero/,/^$/p'
nxt_double_is_zero(f) \
(fabs(f) <= FLT_EPSILON)
$ find src -type f | xargs sed -n '/define nxt_http_field_set/,/^$/p'
#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; \
} while (0)
I'd like to standardize on a single style for them, and IMO,
having the identifier in the same line as #define is a better
option for the following reasons:
- Programmers are used to `#define foo() ...` (readability).
- One less line of code.
- The program for finding them is really simple (see below).
function grep_ngx_func()
{
if (($# != 1)); then
>&2 echo "Usage: ${FUNCNAME[0]} <func>";
return 1;
fi;
find src -type f \
| grep '\.[ch]$' \
| xargs grep -l "$1" \
| sort \
| xargs pcregrep -Mn "(?s)^\$[\w\s*]+?^$1\(.*?^}";
find src -type f \
| grep '\.[ch]$' \
| xargs grep -l "$1" \
| sort \
| xargs pcregrep -Mn "(?s)define $1\(.*?^$" \
| sed -E '1s/^[^:]+:[0-9]+:/&\n\n/';
}
$ grep_ngx_func
Usage: grep_ngx_func <func>
$ grep_ngx_func nxt_http_field_set
src/nxt_http.h:98:
#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; \
} while (0)
$ grep_ngx_func nxt_sprintf
src/nxt_sprintf.c:56:
u_char * nxt_cdecl
nxt_sprintf(u_char *buf, u_char *end, const char *fmt, ...)
{
u_char *p;
va_list args;
va_start(args, fmt);
p = nxt_vsprintf(buf, end, fmt, args);
va_end(args);
return p;
}
................
Scripted change:
................
$ find src -type f \
| grep '\.[ch]$' \
| xargs sed -i '/define *\\$/{N;s/ *\\\n/ /;s/ //}'
|
|
............
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
|
|
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.
|
|
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 '^ [^ *+]';
|
|
The previous commit added more generic APIs for handling
NXT_CONF_VALUE_ARRAY and non-NXT_CONF_VALUE_ARRAY together.
Modify calling code to remove special cases for arrays and
non-arrays, taking special care that the path for non arrays is
logically equivalent to the previous special cased code.
Use the now-generic array code only.
|
|
Similar to how C pointers to variables can always be considered as
pointers to the first element of an array of size 1 (see the
following code for an example of how they are equivalent),
treating non-NXT_CONF_VALUE_ARRAY as if they were
NXT_CONF_VALUE_ARRAYs of size 1 allows for simpler and more
generic code.
void foo(ptrdiff_t sz, int arr[sz])
{
for (ptrdiff_t i = 0; i < sz; i++)
arr[i] = 0;
}
void bar(void)
{
int x;
int y[1];
foo(1, &x);
foo(1, y);
}
nxt_conf_array_elements_count_or_1():
Similar to nxt_conf_array_elements_count().
Return a size of 1 when input is non-array, instead of
causing undefined behavior. That value (1) makes sense
because it will be used as the limiter of a loop that
loops over the array and calls
nxt_conf_get_array_element_or_itself(), which will return
a correct element for such loops.
nxt_conf_get_array_element_or_itself():
Similar to nxt_conf_get_array_element().
Return the input pointer unmodified (i.e., a pointer to
the unique element of a hypothetical array), instead of
returning NULL, which wasn't very useful.
nxt_conf_array_qsort():
Since it's a no-op for non-arrays, this API can be reused.
|
|
That parameter is not being modified in the function. Make it
'const' to allow passing 'static const' variables.
|
|
This closes #639 issue on Github.
|
|
|