From 4f16479482f4902aecefdbcd16f3d6e3bf6b67a4 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 19 May 2022 21:18:25 +0800 Subject: HTTP: generalized uri encoding. No functional changes. --- src/nxt_http.h | 10 ++++ src/nxt_http_request.c | 83 ++++++++++++++++++++++++++++++ src/nxt_http_route.c | 136 ++++++++++++------------------------------------- 3 files changed, 126 insertions(+), 103 deletions(-) diff --git a/src/nxt_http.h b/src/nxt_http.h index d299fdd4..37c27325 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -207,6 +207,13 @@ typedef struct { } nxt_http_name_value_t; +typedef enum { + NXT_HTTP_URI_ENCODING_NONE = 0, + NXT_HTTP_URI_ENCODING, + NXT_HTTP_URI_ENCODING_PLUS +} nxt_http_uri_encoding_t; + + typedef struct nxt_http_route_s nxt_http_route_t; typedef struct nxt_http_route_rule_s nxt_http_route_rule_t; typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t; @@ -324,6 +331,9 @@ nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r); nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r); +int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, + nxt_bool_t case_sensitive, uint8_t encoding); + nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf); nxt_http_action_t *nxt_http_action_create(nxt_task_t *task, diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 04a6f7f3..0eacf627 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -1024,3 +1024,86 @@ nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length, return nv; } + + +int64_t +nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, nxt_bool_t case_sensitive, + uint8_t encoding) +{ + u_char c, *p, *src, *start, *end, plus; + uint8_t d0, d1; + uint32_t hash; + nxt_str_t str; + nxt_uint_t i; + + str.length = name->length; + + str.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(str.start == NULL)) { + return -1; + } + + p = str.start; + + hash = NXT_HTTP_FIELD_HASH_INIT; + + if (encoding == NXT_HTTP_URI_ENCODING_NONE) { + for (i = 0; i < name->length; i++) { + c = name->start[i]; + *p++ = c; + + c = case_sensitive ? c : nxt_lowcase(c); + hash = nxt_http_field_hash_char(hash, c); + } + + goto end; + } + + plus = (encoding == NXT_HTTP_URI_ENCODING_PLUS) ? ' ' : '+'; + + start = name->start; + end = start + name->length; + + for (src = start; src < end; src++) { + c = *src; + + switch (c) { + case '%': + if (nxt_slow_path(end - src <= 2)) { + return -1; + } + + d0 = nxt_hex2int[src[1]]; + d1 = nxt_hex2int[src[2]]; + src += 2; + + if (nxt_slow_path((d0 | d1) >= 16)) { + return -1; + } + + c = (d0 << 4) + d1; + *p++ = c; + break; + + case '+': + c = plus; + *p++ = c; + break; + + default: + *p++ = c; + break; + } + + c = case_sensitive ? c : nxt_lowcase(c); + hash = nxt_http_field_hash_char(hash, c); + } + + str.length = p - str.start; + +end: + + *name = str; + + return nxt_http_field_hash_end(hash) & 0xFFFF; +} diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 9200dc52..f7023997 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -40,13 +40,6 @@ typedef enum { } nxt_http_route_pattern_case_t; -typedef enum { - NXT_HTTP_ROUTE_ENCODING_NONE = 0, - NXT_HTTP_ROUTE_ENCODING_URI, - NXT_HTTP_ROUTE_ENCODING_URI_PLUS -} nxt_http_route_encoding_t; - - typedef struct { nxt_conf_value_t *host; nxt_conf_value_t *uri; @@ -169,29 +162,29 @@ static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, nxt_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); static int nxt_http_pattern_compare(const void *one, const void *two); static int nxt_http_addr_pattern_compare(const void *one, const void *two); static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, nxt_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices, nxt_str_t *test, nxt_http_route_pattern_type_t type, - nxt_http_route_encoding_t encoding, + nxt_http_uri_encoding_t encoding, nxt_http_route_pattern_case_t pattern_case); static nxt_int_t nxt_http_route_resolve(nxt_task_t *task, @@ -457,7 +450,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.scheme != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -470,7 +463,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.host != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1, NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -484,7 +477,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.uri != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_URI); + NXT_HTTP_URI_ENCODING); if (rule == NULL) { return NULL; } @@ -498,7 +491,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.method != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1, NXT_HTTP_ROUTE_PATTERN_UPCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -512,7 +505,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.headers != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.headers, NXT_HTTP_ROUTE_HEADER, 0, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (table == NULL) { return NULL; } @@ -524,7 +517,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.arguments != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.arguments, NXT_HTTP_ROUTE_ARGUMENT, 1, - NXT_HTTP_ROUTE_ENCODING_URI_PLUS); + NXT_HTTP_URI_ENCODING_PLUS); if (table == NULL) { return NULL; } @@ -536,7 +529,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.cookies != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.cookies, NXT_HTTP_ROUTE_COOKIE, 1, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (table == NULL) { return NULL; } @@ -548,7 +541,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.query != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_URI_PLUS); + NXT_HTTP_URI_ENCODING_PLUS); if (rule == NULL) { return NULL; } @@ -690,7 +683,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, static nxt_http_route_table_t * nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding) + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n; @@ -729,7 +722,7 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, static nxt_http_route_ruleset_t * nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding) + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n, next; @@ -777,12 +770,9 @@ nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, static nxt_http_route_rule_t * nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { - u_char c, *p, *src, *start, *end, plus; - uint8_t d0, d1; - uint32_t hash; - nxt_uint_t i; + int64_t hash; nxt_http_route_rule_t *rule; rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive, @@ -792,73 +782,14 @@ nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, return NULL; } - rule->u.name.length = name->length; - - p = nxt_mp_nget(mp, name->length); - if (nxt_slow_path(p == NULL)) { + hash = nxt_http_field_hash(mp, name, case_sensitive, encoding); + if (nxt_slow_path(hash == -1)) { return NULL; } - hash = NXT_HTTP_FIELD_HASH_INIT; - rule->u.name.start = p; - - if (encoding == NXT_HTTP_ROUTE_ENCODING_NONE) { - for (i = 0; i < name->length; i++) { - c = name->start[i]; - *p++ = c; - - c = case_sensitive ? c : nxt_lowcase(c); - hash = nxt_http_field_hash_char(hash, c); - } - - goto end; - } - - plus = (encoding == NXT_HTTP_ROUTE_ENCODING_URI_PLUS) ? ' ' : '+'; - - start = name->start; - end = start + name->length; - - for (src = start; src < end; src++) { - c = *src; - - switch (c) { - case '%': - if (nxt_slow_path(end - src <= 2)) { - return NULL; - } - - d0 = nxt_hex2int[src[1]]; - d1 = nxt_hex2int[src[2]]; - src += 2; - - if (nxt_slow_path((d0 | d1) >= 16)) { - return NULL; - } - - c = (d0 << 4) + d1; - *p++ = c; - break; - - case '+': - c = plus; - *p++ = c; - break; - - default: - *p++ = c; - break; - } - - c = case_sensitive ? c : nxt_lowcase(c); - hash = nxt_http_field_hash_char(hash, c); - } - - rule->u.name.length = p - rule->u.name.start; - -end: - - rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF; + rule->u.name.hash = hash; + rule->u.name.start = name->start; + rule->u.name.length = name->length; return rule; } @@ -868,7 +799,7 @@ static nxt_http_route_rule_t * nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, nxt_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n; @@ -953,7 +884,7 @@ nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp, { return nxt_http_route_rule_create(task, mp, types, 0, NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); } @@ -992,7 +923,7 @@ static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, nxt_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { u_char c, *p, *end; nxt_str_t test, tmp; @@ -1188,15 +1119,15 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, static nxt_int_t -nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) +nxt_http_route_decode_str(nxt_str_t *str, nxt_http_uri_encoding_t encoding) { u_char *start, *end; switch (encoding) { - case NXT_HTTP_ROUTE_ENCODING_NONE: + case NXT_HTTP_URI_ENCODING_NONE: break; - case NXT_HTTP_ROUTE_ENCODING_URI: + case NXT_HTTP_URI_ENCODING: start = str->start; end = nxt_decode_uri(start, start, str->length); @@ -1207,7 +1138,7 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) str->length = end - start; break; - case NXT_HTTP_ROUTE_ENCODING_URI_PLUS: + case NXT_HTTP_URI_ENCODING_PLUS: start = str->start; end = nxt_decode_uri_plus(start, start, str->length); @@ -1228,9 +1159,8 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices, - nxt_str_t *test, - nxt_http_route_pattern_type_t type, - nxt_http_route_encoding_t encoding, + nxt_str_t *test, nxt_http_route_pattern_type_t type, + nxt_http_uri_encoding_t encoding, nxt_http_route_pattern_case_t pattern_case) { u_char *start; -- cgit From 0d2d40e23192a281adaf88ce436723c8b7f5e9d3 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 2 Jun 2022 09:36:35 +0800 Subject: Summary: Var: removing all async stuff. No functional changes. --- src/nxt_http_variables.c | 26 ++++++++++---------------- src/nxt_var.c | 13 ++++--------- src/nxt_var.h | 1 - 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index b765e177..c48f9ca3 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -7,14 +7,12 @@ #include -static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, - nxt_var_query_t *query, nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); +static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, + void *ctx); +static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, + void *ctx); +static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx); +static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx); static nxt_var_decl_t nxt_http_vars[] = { @@ -44,8 +42,7 @@ nxt_http_register_variables(void) static nxt_int_t -nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx) { nxt_http_request_t *r; @@ -58,8 +55,7 @@ nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, static nxt_int_t -nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx) +nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) { nxt_http_request_t *r; @@ -72,8 +68,7 @@ nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query, static nxt_int_t -nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) { nxt_http_request_t *r; @@ -86,8 +81,7 @@ nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, static nxt_int_t -nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx) { nxt_http_request_t *r; diff --git a/src/nxt_var.c b/src/nxt_var.c index 0a722d17..458ba678 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -494,17 +494,12 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, continue; /* NXT_DECLINED */ } - ret = nxt_var_index[index](task, query, value, query->ctx); + ret = nxt_var_index[index](task, value, query->ctx); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } value = NULL; - - if (ret != NXT_OK) { - if (nxt_slow_path(ret != NXT_AGAIN)) { - goto fail; - } - - query->waiting++; - } } query->spare = value; diff --git a/src/nxt_var.h b/src/nxt_var.h index 3b7d0c28..7fef0278 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -12,7 +12,6 @@ typedef struct nxt_var_query_s nxt_var_query_t; typedef nxt_int_t (*nxt_var_handler_t)(nxt_task_t *task, - nxt_var_query_t *query, nxt_str_t *str, void *ctx); -- cgit From df421e36b368c9595e8adedc078b69f3f0c2466b Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Tue, 7 Jun 2022 13:43:38 +0800 Subject: Router: removed unused code in nxt_router_conf_error(). No functional changes. --- src/nxt_router.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/nxt_router.c b/src/nxt_router.c index 3a32a363..48547a75 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1229,7 +1229,6 @@ static void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) { nxt_app_t *app; - nxt_queue_t new_socket_confs; nxt_socket_t s; nxt_router_t *router; nxt_queue_link_t *qlk; @@ -1252,11 +1251,6 @@ nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) nxt_free(skcf->listen); } - nxt_queue_init(&new_socket_confs); - nxt_queue_add(&new_socket_confs, &updating_sockets); - nxt_queue_add(&new_socket_confs, &pending_sockets); - nxt_queue_add(&new_socket_confs, &creating_sockets); - rtcf = tmcf->router_conf; nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { -- cgit From b4540f0960a54908a6bca9c2bd091c239ae76a53 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 7 Jun 2022 13:59:45 +0800 Subject: Removing unused tracking fields and functions. The message tracking is unused since 1d84b9e4b459 commit. This fixes the issue found by Coverity (CID 376263). --- src/nxt_port.h | 4 -- src/nxt_port_memory.c | 131 ---------------------------------------------- src/nxt_port_memory.h | 21 -------- src/nxt_port_memory_int.h | 7 --- src/nxt_port_rpc.c | 1 - src/nxt_router.c | 1 - src/nxt_unit.c | 7 --- 7 files changed, 172 deletions(-) diff --git a/src/nxt_port.h b/src/nxt_port.h index 3b66edfd..6b4d3c8f 100644 --- a/src/nxt_port.h +++ b/src/nxt_port.h @@ -174,9 +174,6 @@ typedef struct { /* More Fragments followed. */ uint8_t mf; /* 1 bit */ - - /* Message delivery tracking enabled, next chunk is tracking msg. */ - uint8_t tracking; /* 1 bit */ } nxt_port_msg_t; @@ -186,7 +183,6 @@ typedef struct { size_t share; nxt_fd_t fd[2]; nxt_port_msg_t port_msg; - uint32_t tracking_msg[2]; uint8_t close_fd; /* 1 bit */ uint8_t allocated; /* 1 bit */ } nxt_port_send_msg_t; diff --git a/src/nxt_port_memory.c b/src/nxt_port_memory.c index e799f860..0a4a6c53 100644 --- a/src/nxt_port_memory.c +++ b/src/nxt_port_memory.c @@ -539,137 +539,6 @@ nxt_port_get_port_incoming_mmap(nxt_task_t *task, nxt_pid_t spid, uint32_t id) } -nxt_int_t -nxt_port_mmap_get_tracking(nxt_task_t *task, nxt_port_mmaps_t *mmaps, - nxt_port_mmap_tracking_t *tracking, uint32_t stream) -{ - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - - nxt_debug(task, "request tracking for stream #%uD", stream); - - mmap_handler = nxt_port_mmap_get(task, mmaps, &c, 1, 1); - if (nxt_slow_path(mmap_handler == NULL)) { - return NXT_ERROR; - } - - nxt_port_mmap_handler_use(mmap_handler, 1); - - hdr = mmap_handler->hdr; - - tracking->mmap_handler = mmap_handler; - tracking->tracking = hdr->tracking + c; - - *tracking->tracking = stream; - - nxt_debug(task, "outgoing tracking allocation: %PI->%PI,%d,%d", - hdr->src_pid, hdr->dst_pid, hdr->id, c); - - return NXT_OK; -} - - -nxt_bool_t -nxt_port_mmap_tracking_cancel(nxt_task_t *task, - nxt_port_mmap_tracking_t *tracking, uint32_t stream) -{ - nxt_bool_t res; - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - - mmap_handler = tracking->mmap_handler; - - if (nxt_slow_path(mmap_handler == NULL)) { - return 0; - } - - hdr = mmap_handler->hdr; - - res = nxt_atomic_cmp_set(tracking->tracking, stream, 0); - - nxt_debug(task, "%s tracking for stream #%uD", - (res ? "cancelled" : "failed to cancel"), stream); - - if (!res) { - c = tracking->tracking - hdr->tracking; - nxt_port_mmap_set_chunk_free(hdr->free_tracking_map, c); - } - - nxt_port_mmap_handler_use(mmap_handler, -1); - - return res; -} - - -nxt_int_t -nxt_port_mmap_tracking_write(uint32_t *buf, nxt_port_mmap_tracking_t *t) -{ - nxt_port_mmap_handler_t *mmap_handler; - - mmap_handler = t->mmap_handler; - -#if (NXT_DEBUG) - { - nxt_atomic_t *tracking; - - tracking = mmap_handler->hdr->tracking; - - nxt_assert(t->tracking >= tracking); - nxt_assert(t->tracking < tracking + PORT_MMAP_CHUNK_COUNT); - } -#endif - - buf[0] = mmap_handler->hdr->id; - buf[1] = t->tracking - mmap_handler->hdr->tracking; - - return NXT_OK; -} - -nxt_bool_t -nxt_port_mmap_tracking_read(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_buf_t *b; - nxt_bool_t res; - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - nxt_port_mmap_tracking_msg_t *tracking_msg; - - b = msg->buf; - - if (nxt_buf_used_size(b) < (int) sizeof(nxt_port_mmap_tracking_msg_t)) { - nxt_debug(task, "too small message %O", nxt_buf_used_size(b)); - return 0; - } - - tracking_msg = (nxt_port_mmap_tracking_msg_t *) b->mem.pos; - - b->mem.pos += sizeof(nxt_port_mmap_tracking_msg_t); - mmap_handler = nxt_port_get_port_incoming_mmap(task, msg->port_msg.pid, - tracking_msg->mmap_id); - - if (nxt_slow_path(mmap_handler == NULL)) { - return 0; - } - - hdr = mmap_handler->hdr; - - c = tracking_msg->tracking_id; - res = nxt_atomic_cmp_set(hdr->tracking + c, msg->port_msg.stream, 0); - - nxt_debug(task, "tracking for stream #%uD %s", msg->port_msg.stream, - (res ? "received" : "already cancelled")); - - if (!res) { - nxt_port_mmap_set_chunk_free(hdr->free_tracking_map, c); - } - - return res; -} - - nxt_buf_t * nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_mmaps_t *mmaps, size_t size) { diff --git a/src/nxt_port_memory.h b/src/nxt_port_memory.h index a2cdf5dd..f1e70964 100644 --- a/src/nxt_port_memory.h +++ b/src/nxt_port_memory.h @@ -15,27 +15,6 @@ typedef struct nxt_port_mmap_handler_s nxt_port_mmap_handler_t; void nxt_port_mmaps_destroy(nxt_port_mmaps_t *port_mmaps, nxt_bool_t free_elts); -typedef struct nxt_port_mmap_tracking_s nxt_port_mmap_tracking_t; - -struct nxt_port_mmap_tracking_s { - void *mmap_handler; - nxt_atomic_t *tracking; -}; - -nxt_int_t -nxt_port_mmap_get_tracking(nxt_task_t *task, nxt_port_mmaps_t *mmaps, - nxt_port_mmap_tracking_t *tracking, uint32_t stream); - -nxt_bool_t -nxt_port_mmap_tracking_cancel(nxt_task_t *task, - nxt_port_mmap_tracking_t *tracking, uint32_t stream); - -nxt_int_t -nxt_port_mmap_tracking_write(uint32_t *buf, nxt_port_mmap_tracking_t *t); - -nxt_bool_t -nxt_port_mmap_tracking_read(nxt_task_t *task, nxt_port_recv_msg_t *msg); - /* * Allocates nxt_but_t structure from task's thread engine mem_pool, assigns * this buf 'mem' pointers to first available shared mem bucket(s). 'size' diff --git a/src/nxt_port_memory_int.h b/src/nxt_port_memory_int.h index d2524ee4..c84615d5 100644 --- a/src/nxt_port_memory_int.h +++ b/src/nxt_port_memory_int.h @@ -84,13 +84,6 @@ struct nxt_port_mmap_msg_s { }; -typedef struct nxt_port_mmap_tracking_msg_s nxt_port_mmap_tracking_msg_t; - -struct nxt_port_mmap_tracking_msg_s { - uint32_t mmap_id; /* Mmap index in nxt_process_t.outgoing. */ - nxt_chunk_id_t tracking_id; /* Tracking index. */ -}; - nxt_inline nxt_bool_t nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, nxt_chunk_id_t *c); diff --git a/src/nxt_port_rpc.c b/src/nxt_port_rpc.c index 0cac5cbb..28590933 100644 --- a/src/nxt_port_rpc.c +++ b/src/nxt_port_rpc.c @@ -512,7 +512,6 @@ nxt_port_rpc_close(nxt_task_t *task, nxt_port_t *port) msg.port_msg.mmap = 0; msg.port_msg.nf = 0; msg.port_msg.mf = 0; - msg.port_msg.tracking = 0; msg.size = 0; msg.cancelled = 0; msg.u.data = NULL; diff --git a/src/nxt_router.c b/src/nxt_router.c index 48547a75..6b69b2ce 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -5384,7 +5384,6 @@ nxt_router_app_prepare_request(nxt_task_t *task, msg.pm.mmap = 1; msg.pm.nf = 0; msg.pm.mf = 0; - msg.pm.tracking = 0; nxt_port_mmap_handler_t *mmap_handler = buf->parent; nxt_port_mmap_header_t *hdr = mmap_handler->hdr; diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 32bb07ab..f183ac6e 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -942,7 +942,6 @@ nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream, int queue_fd) msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; nxt_socket_msg_oob_init(&oob, fds); @@ -2644,7 +2643,6 @@ nxt_unit_mmap_buf_send(nxt_unit_request_info_t *req, m.msg.mmap = hdr != NULL && m.mmap_msg.size > 0; m.msg.nf = 0; m.msg.mf = 0; - m.msg.tracking = 0; rc = NXT_UNIT_ERROR; @@ -3296,7 +3294,6 @@ skip_response_send: msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; (void) nxt_unit_port_send(req->ctx, req->response_port, &msg, sizeof(msg), NULL); @@ -3619,7 +3616,6 @@ nxt_unit_send_oosm(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL); if (nxt_slow_path(res != sizeof(msg))) { @@ -3905,7 +3901,6 @@ nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, int fd) msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; nxt_socket_msg_oob_init(&oob, fds); @@ -4390,7 +4385,6 @@ nxt_unit_send_shm_ack(nxt_unit_ctx_t *ctx, pid_t pid) msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL); if (nxt_slow_path(res != sizeof(msg))) { @@ -5356,7 +5350,6 @@ nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *dst, m.msg.mmap = 0; m.msg.nf = 0; m.msg.mf = 0; - m.msg.tracking = 0; m.new_port.id = port->id.id; m.new_port.pid = port->id.pid; -- cgit From 862f51bcd834d58fadc322720107be64ba0b70b1 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 8 Jun 2022 13:12:51 +0100 Subject: Specified date of 1.27.0 release in changes.xml. --- docs/changes.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index ccd9439a..dc170e7d 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -15,7 +15,7 @@ unit-jsc-common unit-jsc8 unit-jsc10 unit-jsc11 unit-jsc13 unit-jsc14 unit-jsc15 unit-jsc16 unit-jsc17 unit-jsc18" ver="1.27.0" rev="1" - date="" time="" + date="2022-06-02" time="18:00:00 +0300" packager="Andrei Belov <defan@nginx.com>"> @@ -28,7 +28,7 @@ NGINX Unit updated to 1.27.0. -- cgit From 6a8081d71e805b12d0f7fd32ce72d60babadfc85 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Wed, 15 Jun 2022 14:27:50 +0800 Subject: Var: relocated nxt_var_is_const() and nxt_var_raw(). No functional changes. --- src/nxt_var.c | 30 +++++++++++++++--------------- src/nxt_var.h | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/nxt_var.c b/src/nxt_var.c index 458ba678..a7cbb898 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -91,21 +91,6 @@ static uint32_t nxt_var_count; static nxt_var_handler_t *nxt_var_index; -void -nxt_var_raw(nxt_var_t *var, nxt_str_t *str) -{ - str->length = var->length; - str->start = nxt_var_raw_start(var); -} - - -nxt_bool_t -nxt_var_is_const(nxt_var_t *var) -{ - return (var->vars == 0); -} - - static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { @@ -420,6 +405,21 @@ nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, } +inline void +nxt_var_raw(nxt_var_t *var, nxt_str_t *str) +{ + str->length = var->length; + str->start = nxt_var_raw_start(var); +} + + +inline nxt_bool_t +nxt_var_is_const(nxt_var_t *var) +{ + return (var->vars == 0); +} + + nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp) { diff --git a/src/nxt_var.h b/src/nxt_var.h index 7fef0278..1322d507 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -29,14 +29,14 @@ nxt_is_var(nxt_str_t *str) } -void nxt_var_raw(nxt_var_t *var, nxt_str_t *str); -nxt_bool_t nxt_var_is_const(nxt_var_t *var); - nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n); nxt_int_t nxt_var_index_init(void); nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz); nxt_int_t nxt_var_test(nxt_str_t *str, u_char *error); +void nxt_var_raw(nxt_var_t *var, nxt_str_t *str); +nxt_bool_t nxt_var_is_const(nxt_var_t *var); + nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp); void nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, -- cgit From 7e64971cbe6dcf249b586cc49bc4e7b163697d74 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Fri, 17 Jun 2022 09:46:30 +0100 Subject: Version bump. --- docs/changes.xml | 29 +++++++++++++++++++++++++++++ version | 4 ++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index dc170e7d..9f2e299f 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -5,6 +5,35 @@ + + + + +NGINX Unit updated to 1.28.0. + + + + + + + + + + + Date: Mon, 20 Jun 2022 13:11:34 +0800 Subject: Router: refactored nxt_router_conf_create(). No functional changes. --- src/nxt_router.c | 60 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/nxt_router.c b/src/nxt_router.c index 6b69b2ce..00558d94 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1488,11 +1488,11 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_tls_init_t *tls_init; nxt_conf_value_t *certificate; #endif - nxt_conf_value_t *conf, *http, *value, *websocket; + nxt_conf_value_t *root, *conf, *http, *value, *websocket; nxt_conf_value_t *applications, *application; nxt_conf_value_t *listeners, *listener; - nxt_conf_value_t *routes_conf, *static_conf, *client_ip_conf; nxt_socket_conf_t *skcf; + nxt_router_conf_t *rtcf; nxt_http_routes_t *routes; nxt_event_engine_t *engine; nxt_app_lang_module_t *lang; @@ -1516,35 +1516,36 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, static nxt_str_t websocket_path = nxt_string("/settings/http/websocket"); static nxt_str_t client_ip_path = nxt_string("/client_ip"); - conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); - if (conf == NULL) { + root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); + if (root == NULL) { nxt_alert(task, "configuration parsing error"); return NXT_ERROR; } - mp = tmcf->router_conf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; - ret = nxt_conf_map_object(mp, conf, nxt_router_conf, - nxt_nitems(nxt_router_conf), tmcf->router_conf); + ret = nxt_conf_map_object(mp, root, nxt_router_conf, + nxt_nitems(nxt_router_conf), rtcf); if (ret != NXT_OK) { nxt_alert(task, "root map error"); return NXT_ERROR; } - if (tmcf->router_conf->threads == 0) { - tmcf->router_conf->threads = nxt_ncpu; + if (rtcf->threads == 0) { + rtcf->threads = nxt_ncpu; } - static_conf = nxt_conf_get_path(conf, &static_path); + conf = nxt_conf_get_path(root, &static_path); - ret = nxt_router_conf_process_static(task, tmcf->router_conf, static_conf); + ret = nxt_router_conf_process_static(task, rtcf, conf); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } - router = tmcf->router_conf->router; + router = rtcf->router; - applications = nxt_conf_get_path(conf, &applications_path); + applications = nxt_conf_get_path(root, &applications_path); if (applications != NULL) { next = 0; @@ -1593,7 +1594,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_queue_remove(&prev->link); nxt_queue_insert_tail(&tmcf->previous, &prev->link); - ret = nxt_router_apps_hash_add(tmcf->router_conf, prev); + ret = nxt_router_apps_hash_add(rtcf, prev); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } @@ -1728,7 +1729,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_queue_insert_tail(&tmcf->apps, &app->link); - ret = nxt_router_apps_hash_add(tmcf->router_conf, app); + ret = nxt_router_apps_hash_add(rtcf, app); if (nxt_slow_path(ret != NXT_OK)) { goto app_fail; } @@ -1779,21 +1780,21 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } } - routes_conf = nxt_conf_get_path(conf, &routes_path); - if (nxt_fast_path(routes_conf != NULL)) { - routes = nxt_http_routes_create(task, tmcf, routes_conf); + conf = nxt_conf_get_path(root, &routes_path); + if (nxt_fast_path(conf != NULL)) { + routes = nxt_http_routes_create(task, tmcf, conf); if (nxt_slow_path(routes == NULL)) { return NXT_ERROR; } - tmcf->router_conf->routes = routes; + rtcf->routes = routes; } - ret = nxt_upstreams_create(task, tmcf, conf); + ret = nxt_upstreams_create(task, tmcf, root); if (nxt_slow_path(ret != NXT_OK)) { return ret; } - http = nxt_conf_get_path(conf, &http_path); + http = nxt_conf_get_path(root, &http_path); #if 0 if (http == NULL) { nxt_alert(task, "no \"http\" block"); @@ -1801,9 +1802,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } #endif - websocket = nxt_conf_get_path(conf, &websocket_path); + websocket = nxt_conf_get_path(root, &websocket_path); - listeners = nxt_conf_get_path(conf, &listeners_path); + listeners = nxt_conf_get_path(root, &listeners_path); if (listeners != NULL) { next = 0; @@ -1883,9 +1884,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, t->length = nxt_strlen(t->start); } - client_ip_conf = nxt_conf_get_path(listener, &client_ip_path); + conf = nxt_conf_get_path(listener, &client_ip_path); ret = nxt_router_conf_process_client_ip(task, tmcf, skcf, - client_ip_conf); + conf); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -1935,7 +1936,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, #endif skcf->listen->handler = nxt_http_conn_init; - skcf->router_conf = tmcf->router_conf; + skcf->router_conf = rtcf; skcf->router_conf->count++; if (lscf.pass.length != 0) { @@ -1943,8 +1944,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, /* COMPATIBILITY: listener application. */ } else if (lscf.application.length > 0) { - skcf->action = nxt_http_pass_application(task, - tmcf->router_conf, + skcf->action = nxt_http_pass_application(task, rtcf, &lscf.application); } @@ -1959,7 +1959,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, goto fail; } - value = nxt_conf_get_path(conf, &access_log_path); + value = nxt_conf_get_path(root, &access_log_path); if (value != NULL) { nxt_conf_get_string(value, &path); @@ -1988,7 +1988,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_memcpy(access_log->path.start, path.start, path.length); } - tmcf->router_conf->access_log = access_log; + rtcf->access_log = access_log; } nxt_queue_add(&deleting_sockets, &router->sockets); -- cgit From 14dfa439eed1983693d7d128cc51c5e738a487d7 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 20 Jun 2022 13:16:25 +0800 Subject: Router: introduced nxt_http_forward_t. 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. --- src/nxt_http.h | 9 +++++++-- src/nxt_http_request.c | 30 ++++++++++++++++-------------- src/nxt_router.c | 39 +++++++++++++++++---------------------- src/nxt_router.h | 4 ++-- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/nxt_http.h b/src/nxt_http.h index 37c27325..665ccdbf 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -273,10 +273,15 @@ typedef struct { } nxt_http_proto_table_t; -struct nxt_http_client_ip_s { - nxt_http_route_addr_rule_t *source; +typedef struct { nxt_str_t *header; uint32_t header_hash; +} nxt_http_forward_header_t; + + +struct nxt_http_forward_s { + nxt_http_forward_header_t client_ip; + nxt_http_route_addr_rule_t *source; uint8_t recursive; /* 1 bit */ }; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 0eacf627..3f926796 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -314,25 +314,27 @@ nxt_http_request_start(nxt_task_t *task, void *obj, void *data) static nxt_int_t nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) { - u_char *start, *p; - nxt_int_t ret, i, len; - nxt_str_t *header; - nxt_array_t *fields_arr; /* of nxt_http_field_t * */ - nxt_sockaddr_t *sa, *prev_sa; - nxt_http_field_t *f, **fields; - nxt_http_client_ip_t *client_ip; - - client_ip = r->conf->socket_conf->client_ip; - - if (client_ip == NULL) { + u_char *start, *p; + nxt_int_t ret, i, len; + nxt_str_t *header; + nxt_array_t *fields_arr; /* of nxt_http_field_t * */ + nxt_sockaddr_t *sa, *prev_sa; + nxt_http_field_t *f, **fields; + nxt_http_forward_t *forward; + nxt_http_forward_header_t *client_ip; + + forward = r->conf->socket_conf->client_ip; + + if (forward == NULL) { return NXT_OK; } - ret = nxt_http_route_addr_rule(r, client_ip->source, r->remote); + ret = nxt_http_route_addr_rule(r, forward->source, r->remote); if (ret <= 0) { return NXT_OK; } + client_ip = &forward->client_ip; header = client_ip->header; fields_arr = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_field_t *)); @@ -388,13 +390,13 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) return NXT_OK; } - if (!client_ip->recursive) { + if (!forward->recursive) { r->remote = sa; return NXT_OK; } - ret = nxt_http_route_addr_rule(r, client_ip->source, sa); + ret = nxt_http_route_addr_rule(r, forward->source, sa); if (ret <= 0 || (i == 0 && p == start)) { r->remote = sa; diff --git a/src/nxt_router.c b/src/nxt_router.c index 00558d94..8487d239 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -109,8 +109,7 @@ static nxt_int_t nxt_router_conf_create(nxt_task_t *task, static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); static nxt_int_t nxt_router_conf_process_client_ip(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf, - nxt_conf_value_t *conf); + nxt_mp_t *mp, nxt_socket_conf_t *skcf, nxt_conf_value_t *conf); static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); @@ -1885,10 +1884,12 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } conf = nxt_conf_get_path(listener, &client_ip_path); - ret = nxt_router_conf_process_client_ip(task, tmcf, skcf, - conf); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; + + if (conf != NULL) { + ret = nxt_router_conf_process_client_ip(task, mp, skcf, conf); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } } #if (NXT_TLS) @@ -2124,30 +2125,22 @@ nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, static nxt_int_t -nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, +nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_mp_t *mp, nxt_socket_conf_t *skcf, nxt_conf_value_t *conf) { char c; size_t i; - nxt_mp_t *mp; uint32_t hash; nxt_str_t header; nxt_conf_value_t *source_conf, *header_conf, *recursive_conf; - nxt_http_client_ip_t *client_ip; + nxt_http_forward_t *forward; + nxt_http_forward_header_t *client_ip; nxt_http_route_addr_rule_t *source; static nxt_str_t header_path = nxt_string("/header"); static nxt_str_t source_path = nxt_string("/source"); static nxt_str_t recursive_path = nxt_string("/recursive"); - if (conf == NULL) { - skcf->client_ip = NULL; - - return NXT_OK; - } - - mp = tmcf->router_conf->mem_pool; - source_conf = nxt_conf_get_path(conf, &source_path); header_conf = nxt_conf_get_path(conf, &header_path); recursive_conf = nxt_conf_get_path(conf, &recursive_path); @@ -2156,8 +2149,8 @@ nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf return NXT_ERROR; } - client_ip = nxt_mp_zget(mp, sizeof(nxt_http_client_ip_t)); - if (nxt_slow_path(client_ip == NULL)) { + forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t)); + if (nxt_slow_path(forward == NULL)) { return NXT_ERROR; } @@ -2166,12 +2159,14 @@ nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf return NXT_ERROR; } - client_ip->source = source; + forward->source = source; + + client_ip = &forward->client_ip; nxt_conf_get_string(header_conf, &header); if (recursive_conf != NULL) { - client_ip->recursive = nxt_conf_get_boolean(recursive_conf); + forward->recursive = nxt_conf_get_boolean(recursive_conf); } client_ip->header = nxt_str_dup(mp, NULL, &header); @@ -2190,7 +2185,7 @@ nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf client_ip->header_hash = hash; - skcf->client_ip = client_ip; + skcf->client_ip = forward; return NXT_OK; } diff --git a/src/nxt_router.h b/src/nxt_router.h index 7e337d27..b97d5c20 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -18,7 +18,7 @@ typedef struct nxt_http_request_s nxt_http_request_t; typedef struct nxt_http_action_s nxt_http_action_t; typedef struct nxt_http_routes_s nxt_http_routes_t; -typedef struct nxt_http_client_ip_s nxt_http_client_ip_t; +typedef struct nxt_http_forward_s nxt_http_forward_t; typedef struct nxt_upstream_s nxt_upstream_t; typedef struct nxt_upstreams_s nxt_upstreams_t; typedef struct nxt_router_access_log_s nxt_router_access_log_t; @@ -197,7 +197,7 @@ typedef struct { uint8_t discard_unsafe_fields; /* 1 bit */ - nxt_http_client_ip_t *client_ip; + nxt_http_forward_t *client_ip; #if (NXT_TLS) nxt_tls_conf_t *tls; -- cgit From 9d2672a701e3dcaee45bef9251ab55620d42fa42 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 20 Jun 2022 13:22:13 +0800 Subject: Router: forwared header replacement. --- docs/changes.xml | 6 ++ src/nxt_conf_validation.c | 50 +++++++++++++++ src/nxt_h1proto.c | 2 +- src/nxt_http.h | 3 +- src/nxt_http_request.c | 151 ++++++++++++++++++++++++++++++++++------------ src/nxt_http_route.c | 5 +- src/nxt_router.c | 107 +++++++++++++++++++++++--------- src/nxt_router.h | 1 + 8 files changed, 250 insertions(+), 75 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 9f2e299f..24c3f9db 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -31,6 +31,12 @@ NGINX Unit updated to 1.28.0. date="" time="" packager="Konstantin Pavlov <thresh@nginx.com>"> + + +forwarded header to replace client address and protocol. + + + diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index ee7ebe44..a5958788 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -166,6 +166,8 @@ static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); +static nxt_int_t nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt, @@ -220,6 +222,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[]; #if (NXT_TLS) static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[]; @@ -365,6 +368,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { .name = nxt_string("application"), .type = NXT_CONF_VLDT_STRING, .validator = nxt_conf_vldt_app_name, + }, { + .name = nxt_string("forwarded"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_forwarded, }, { .name = nxt_string("client_ip"), .type = NXT_CONF_VLDT_OBJECT, @@ -385,6 +392,27 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { }; +static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[] = { + { + .name = nxt_string("client_ip"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("protocol"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("source"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_addrs, + .flags = NXT_CONF_VLDT_REQUIRED + }, { + .name = nxt_string("recursive"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, + + NXT_CONF_VLDT_END +}; + + static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[] = { { .name = nxt_string("source"), @@ -2317,6 +2345,28 @@ error: } +static nxt_int_t +nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, + void *data) +{ + nxt_conf_value_t *client_ip, *protocol; + + static nxt_str_t client_ip_str = nxt_string("client_ip"); + static nxt_str_t protocol_str = nxt_string("protocol"); + + client_ip = nxt_conf_get_object_member(value, &client_ip_str, NULL); + protocol = nxt_conf_get_object_member(value, &protocol_str, NULL); + + if (client_ip == NULL && protocol == NULL) { + return nxt_conf_vldt_error(vldt, "The \"forwarded\" object must have " + "either \"client_ip\" or \"protocol\" " + "option set."); + } + + return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_forwarded_members); +} + + static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value) diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index d3340774..1473aaa0 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -490,7 +490,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) r->remote = c->remote; #if (NXT_TLS) - r->tls = c->u.tls; + r->tls = (c->u.tls != NULL); #endif r->task = c->task; diff --git a/src/nxt_http.h b/src/nxt_http.h index 665ccdbf..8fa0caad 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -162,7 +162,6 @@ struct nxt_http_request_s { nxt_sockaddr_t *remote; nxt_sockaddr_t *local; - void *tls; nxt_task_t task; nxt_timer_t timer; @@ -190,6 +189,7 @@ struct nxt_http_request_s { uint8_t pass_count; /* 8 bits */ uint8_t app_target; nxt_http_protocol_t protocol:8; /* 2 bits */ + uint8_t tls; /* 1 bit */ uint8_t logged; /* 1 bit */ uint8_t header_sent; /* 1 bit */ uint8_t inconsistent; /* 1 bit */ @@ -281,6 +281,7 @@ typedef struct { struct nxt_http_forward_s { nxt_http_forward_header_t client_ip; + nxt_http_forward_header_t protocol; nxt_http_route_addr_rule_t *source; uint8_t recursive; /* 1 bit */ }; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 3f926796..7fb86cc4 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -10,10 +10,14 @@ static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp); static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data); -static nxt_int_t nxt_http_request_client_ip(nxt_task_t *task, - nxt_http_request_t *r); +static nxt_int_t nxt_http_request_forward(nxt_task_t *task, + nxt_http_request_t *r, nxt_http_forward_t *forward); +static void nxt_http_request_forward_client_ip(nxt_http_request_t *r, + nxt_http_forward_t *forward, nxt_array_t *fields); static nxt_sockaddr_t *nxt_http_request_client_ip_sockaddr( nxt_http_request_t *r, u_char *start, size_t len); +static void nxt_http_request_forward_protocol(nxt_http_request_t *r, + nxt_http_field_t *field); static void nxt_http_request_ready(nxt_task_t *task, void *obj, void *data); static void nxt_http_request_proto_info(nxt_task_t *task, nxt_http_request_t *r); @@ -296,38 +300,46 @@ static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data) { nxt_int_t ret; + nxt_socket_conf_t *skcf; nxt_http_request_t *r; r = obj; r->state = &nxt_http_request_body_state; - ret = nxt_http_request_client_ip(task, r); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + skcf = r->conf->socket_conf; + + if (skcf->forwarded != NULL) { + ret = nxt_http_request_forward(task, r, skcf->forwarded); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } + + if (skcf->client_ip != NULL) { + ret = nxt_http_request_forward(task, r, skcf->client_ip); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } } nxt_http_request_read_body(task, r); + + return; + +fail: + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } static nxt_int_t -nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) +nxt_http_request_forward(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_forward_t *forward) { - u_char *start, *p; - nxt_int_t ret, i, len; - nxt_str_t *header; - nxt_array_t *fields_arr; /* of nxt_http_field_t * */ - nxt_sockaddr_t *sa, *prev_sa; - nxt_http_field_t *f, **fields; - nxt_http_forward_t *forward; - nxt_http_forward_header_t *client_ip; - - forward = r->conf->socket_conf->client_ip; - - if (forward == NULL) { - return NXT_OK; - } + nxt_int_t ret; + nxt_array_t *client_ip_fields; + nxt_http_field_t *f, **fields, *protocol_field; + nxt_http_forward_header_t *client_ip, *protocol; ret = nxt_http_route_addr_rule(r, forward->source, r->remote); if (ret <= 0) { @@ -335,37 +347,78 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) } client_ip = &forward->client_ip; - header = client_ip->header; + protocol = &forward->protocol; - fields_arr = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_field_t *)); - if (nxt_slow_path(fields_arr == NULL)) { - return NXT_ERROR; + if (client_ip->header != NULL) { + client_ip_fields = nxt_array_create(r->mem_pool, 1, + sizeof(nxt_http_field_t *)); + if (nxt_slow_path(client_ip_fields == NULL)) { + return NXT_ERROR; + } + + } else { + client_ip_fields = NULL; } + protocol_field = NULL; + nxt_list_each(f, r->fields) { - if (f->hash == client_ip->header_hash - && f->name_length == client_ip->header->length + if (client_ip_fields != NULL + && f->hash == client_ip->header_hash && f->value_length > 0 - && nxt_memcasecmp(f->name, header->start, header->length) == 0) + && f->name_length == client_ip->header->length + && nxt_memcasecmp(f->name, client_ip->header->start, + client_ip->header->length) == 0) { - fields = nxt_array_add(fields_arr); + fields = nxt_array_add(client_ip_fields); if (nxt_slow_path(fields == NULL)) { return NXT_ERROR; } *fields = f; } + + if (protocol->header != NULL + && protocol_field == NULL + && f->hash == protocol->header_hash + && f->value_length > 0 + && f->name_length == protocol->header->length + && nxt_memcasecmp(f->name, protocol->header->start, + protocol->header->length) == 0) + { + protocol_field = f; + } } nxt_list_loop; + if (client_ip_fields != NULL) { + nxt_http_request_forward_client_ip(r, forward, client_ip_fields); + } + + if (protocol_field != NULL) { + nxt_http_request_forward_protocol(r, protocol_field); + } + + return NXT_OK; +} + + +static void +nxt_http_request_forward_client_ip(nxt_http_request_t *r, + nxt_http_forward_t *forward, nxt_array_t *fields) +{ + u_char *start, *p; + nxt_int_t ret, i, len; + nxt_sockaddr_t *sa, *prev_sa; + nxt_http_field_t **f; + prev_sa = r->remote; - fields = (nxt_http_field_t **) fields_arr->elts; + f = (nxt_http_field_t **) fields->elts; - i = fields_arr->nelts; + i = fields->nelts; while (i-- > 0) { - f = fields[i]; - start = f->value; - len = f->value_length; + start = f[i]->value; + len = f[i]->value_length; do { for (p = start + len - 1; p > start; p--, len--) { @@ -387,20 +440,18 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) r->remote = prev_sa; } - return NXT_OK; + return; } if (!forward->recursive) { r->remote = sa; - - return NXT_OK; + return; } ret = nxt_http_route_addr_rule(r, forward->source, sa); if (ret <= 0 || (i == 0 && p == start)) { r->remote = sa; - - return NXT_OK; + return; } prev_sa = sa; @@ -408,8 +459,6 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) } while (len > 0); } - - return NXT_OK; } @@ -453,6 +502,28 @@ nxt_http_request_client_ip_sockaddr(nxt_http_request_t *r, u_char *start, } +static void +nxt_http_request_forward_protocol(nxt_http_request_t *r, + nxt_http_field_t *field) +{ + if (field->value_length == 4) { + if (nxt_memcasecmp(field->value, "http", 4) == 0) { + r->tls = 0; + } + + } else if (field->value_length == 5) { + if (nxt_memcasecmp(field->value, "https", 5) == 0) { + r->tls = 1; + } + + } else if (field->value_length == 2) { + if (nxt_memcasecmp(field->value, "on", 2) == 0) { + r->tls = 1; + } + } +} + + static const nxt_http_request_state_t nxt_http_request_body_state nxt_aligned(64) = { diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index f7023997..5a4f349e 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -1949,14 +1949,13 @@ nxt_http_route_test_argument(nxt_http_request_t *r, static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule) { - nxt_bool_t tls, https; + nxt_bool_t https; nxt_http_route_pattern_slice_t *pattern_slice; pattern_slice = rule->pattern[0].u.pattern_slices->elts; https = (pattern_slice->length == nxt_length("https")); - tls = (r->tls != NULL); - return (tls == https); + return (r->tls == https); } diff --git a/src/nxt_router.c b/src/nxt_router.c index 8487d239..a3cc0a8d 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -108,8 +108,10 @@ static nxt_int_t nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); -static nxt_int_t nxt_router_conf_process_client_ip(nxt_task_t *task, - nxt_mp_t *mp, nxt_socket_conf_t *skcf, nxt_conf_value_t *conf); +static nxt_http_forward_t *nxt_router_conf_forward(nxt_task_t *task, + nxt_mp_t *mp, nxt_conf_value_t *conf); +static nxt_int_t nxt_router_conf_forward_header(nxt_mp_t *mp, + nxt_conf_value_t *conf, nxt_http_forward_header_t *fh); static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); @@ -1513,6 +1515,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, #endif static nxt_str_t static_path = nxt_string("/settings/http/static"); static nxt_str_t websocket_path = nxt_string("/settings/http/websocket"); + static nxt_str_t forwarded_path = nxt_string("/forwarded"); static nxt_str_t client_ip_path = nxt_string("/client_ip"); root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); @@ -1883,11 +1886,20 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, t->length = nxt_strlen(t->start); } + conf = nxt_conf_get_path(listener, &forwarded_path); + + if (conf != NULL) { + skcf->forwarded = nxt_router_conf_forward(task, mp, conf); + if (nxt_slow_path(skcf->forwarded == NULL)) { + return NXT_ERROR; + } + } + conf = nxt_conf_get_path(listener, &client_ip_path); if (conf != NULL) { - ret = nxt_router_conf_process_client_ip(task, mp, skcf, conf); - if (nxt_slow_path(ret != NXT_OK)) { + skcf->client_ip = nxt_router_conf_forward(task, mp, conf); + if (nxt_slow_path(skcf->client_ip == NULL)) { return NXT_ERROR; } } @@ -2124,68 +2136,103 @@ nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, } -static nxt_int_t -nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_mp_t *mp, - nxt_socket_conf_t *skcf, nxt_conf_value_t *conf) +static nxt_http_forward_t * +nxt_router_conf_forward(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf) { - char c; - size_t i; - uint32_t hash; - nxt_str_t header; - nxt_conf_value_t *source_conf, *header_conf, *recursive_conf; + nxt_int_t ret; + nxt_conf_value_t *header_conf, *client_ip_conf, *protocol_conf; + nxt_conf_value_t *source_conf, *recursive_conf; nxt_http_forward_t *forward; - nxt_http_forward_header_t *client_ip; nxt_http_route_addr_rule_t *source; static nxt_str_t header_path = nxt_string("/header"); + static nxt_str_t client_ip_path = nxt_string("/client_ip"); + static nxt_str_t protocol_path = nxt_string("/protocol"); static nxt_str_t source_path = nxt_string("/source"); static nxt_str_t recursive_path = nxt_string("/recursive"); - source_conf = nxt_conf_get_path(conf, &source_path); header_conf = nxt_conf_get_path(conf, &header_path); + + if (header_conf != NULL) { + client_ip_conf = nxt_conf_get_path(conf, &header_path); + protocol_conf = NULL; + + } else { + client_ip_conf = nxt_conf_get_path(conf, &client_ip_path); + protocol_conf = nxt_conf_get_path(conf, &protocol_path); + } + + source_conf = nxt_conf_get_path(conf, &source_path); recursive_conf = nxt_conf_get_path(conf, &recursive_path); - if (source_conf == NULL || header_conf == NULL) { - return NXT_ERROR; + if (source_conf == NULL + || (protocol_conf == NULL && client_ip_conf == NULL)) + { + return NULL; } forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t)); if (nxt_slow_path(forward == NULL)) { - return NXT_ERROR; + return NULL; } source = nxt_http_route_addr_rule_create(task, mp, source_conf); if (nxt_slow_path(source == NULL)) { - return NXT_ERROR; + return NULL; } forward->source = source; - client_ip = &forward->client_ip; - - nxt_conf_get_string(header_conf, &header); - if (recursive_conf != NULL) { forward->recursive = nxt_conf_get_boolean(recursive_conf); } - client_ip->header = nxt_str_dup(mp, NULL, &header); - if (nxt_slow_path(client_ip->header == NULL)) { + if (client_ip_conf != NULL) { + ret = nxt_router_conf_forward_header(mp, client_ip_conf, + &forward->client_ip); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + } + + if (protocol_conf != NULL) { + ret = nxt_router_conf_forward_header(mp, protocol_conf, + &forward->protocol); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + } + + return forward; +} + + +static nxt_int_t +nxt_router_conf_forward_header(nxt_mp_t *mp, nxt_conf_value_t *conf, + nxt_http_forward_header_t *fh) +{ + char c; + size_t i; + uint32_t hash; + nxt_str_t header; + + nxt_conf_get_string(conf, &header); + + fh->header = nxt_str_dup(mp, NULL, &header); + if (nxt_slow_path(fh->header == NULL)) { return NXT_ERROR; } hash = NXT_HTTP_FIELD_HASH_INIT; - for (i = 0; i < client_ip->header->length; i++) { - c = client_ip->header->start[i]; + for (i = 0; i < fh->header->length; i++) { + c = fh->header->start[i]; hash = nxt_http_field_hash_char(hash, nxt_lowcase(c)); } hash = nxt_http_field_hash_end(hash) & 0xFFFF; - client_ip->header_hash = hash; - - skcf->client_ip = forward; + fh->header_hash = hash; return NXT_OK; } @@ -5547,7 +5594,7 @@ nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r, p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length); *p++ = '\0'; - req->tls = (r->tls != NULL); + req->tls = r->tls; req->websocket_handshake = r->websocket_handshake; req->server_name_length = r->server_name.length; diff --git a/src/nxt_router.h b/src/nxt_router.h index b97d5c20..37008f9d 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -197,6 +197,7 @@ typedef struct { uint8_t discard_unsafe_fields; /* 1 bit */ + nxt_http_forward_t *forwarded; nxt_http_forward_t *client_ip; #if (NXT_TLS) -- cgit From 045c05e4686a1fbfec58072df8d564697ebd8300 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 20 Jun 2022 17:19:35 +0800 Subject: Tests: forwarded header replacement tests. --- test/python/forwarded_header/wsgi.py | 10 ++ test/test_forwarded_header.py | 266 +++++++++++++++++++++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 test/python/forwarded_header/wsgi.py create mode 100644 test/test_forwarded_header.py diff --git a/test/python/forwarded_header/wsgi.py b/test/python/forwarded_header/wsgi.py new file mode 100644 index 00000000..44d370ab --- /dev/null +++ b/test/python/forwarded_header/wsgi.py @@ -0,0 +1,10 @@ +def application(env, start_response): + start_response( + '200', + [ + ('Content-Length', '0'), + ('Remote-Addr', env.get('REMOTE_ADDR')), + ('Url-Scheme', env.get('wsgi.url_scheme')), + ], + ) + return [] diff --git a/test/test_forwarded_header.py b/test/test_forwarded_header.py new file mode 100644 index 00000000..eb2f25f8 --- /dev/null +++ b/test/test_forwarded_header.py @@ -0,0 +1,266 @@ +from unit.applications.lang.python import TestApplicationPython + + +class TestForwardedHeader(TestApplicationPython): + prerequisites = {'modules': {'python': 'any'}} + + def forwarded_header(self, forwarded): + assert 'success' in self.conf( + { + "127.0.0.1:7081": { + "forwarded": forwarded, + "pass": "applications/forwarded_header", + }, + "[::1]:7082": { + "forwarded": forwarded, + "pass": "applications/forwarded_header", + }, + }, + 'listeners', + ), 'listeners configure' + + def get_fwd(self, sock_type='ipv4', xff=None, xfp=None): + port = 7081 if sock_type == 'ipv4' else 7082 + + headers = {'Connection': 'close'} + + if xff is not None: + headers['X-Forwarded-For'] = xff + + if xfp is not None: + headers['X-Forwarded-Proto'] = xfp + + return self.get(sock_type=sock_type, port=port, headers=headers)[ + 'headers' + ] + + def get_addr(self, *args, **kwargs): + return self.get_fwd(*args, **kwargs)['Remote-Addr'] + + def get_scheme(self, *args, **kwargs): + return self.get_fwd(*args, **kwargs)['Url-Scheme'] + + def setup_method(self): + self.load('forwarded_header') + + def test_forwarded_header_single_ip(self): + self.forwarded_header( + { + 'client_ip': 'X-Forwarded-For', + 'protocol': 'X-Forwarded-Proto', + 'source': '123.123.123.123', + } + ) + + resp = self.get_fwd(xff='1.1.1.1', xfp='https') + assert resp['Remote-Addr'] == '127.0.0.1', 'both headers addr' + assert resp['Url-Scheme'] == 'http', 'both headers proto' + + assert self.get_addr() == '127.0.0.1', 'ipv4 default addr' + assert self.get_addr('ipv6') == '::1', 'ipv6 default addr' + assert self.get_addr(xff='1.1.1.1') == '127.0.0.1', 'bad source' + assert self.get_addr(xff='blah') == '127.0.0.1', 'bad xff' + assert self.get_addr('ipv6', '1.1.1.1') == '::1', 'bad source ipv6' + + assert self.get_scheme() == 'http', 'ipv4 default proto' + assert self.get_scheme('ipv6') == 'http', 'ipv6 default proto' + assert self.get_scheme(xfp='https') == 'http', 'bad proto' + assert self.get_scheme(xfp='blah') == 'http', 'bad xfp' + assert self.get_scheme('ipv6', xfp='https') == 'http', 'bad proto ipv6' + + self.forwarded_header( + { + 'client_ip': 'X-Forwarded-For', + 'protocol': 'X-Forwarded-Proto', + 'source': '127.0.0.1', + } + ) + + resp = self.get_fwd(xff='1.1.1.1', xfp='https') + assert resp['Remote-Addr'] == '1.1.1.1', 'both headers addr 2' + assert resp['Url-Scheme'] == 'https', 'both headers proto 2' + + assert self.get_addr() == '127.0.0.1', 'ipv4 default addr 2' + assert self.get_addr('ipv6') == '::1', 'ipv6 default addr 2' + assert self.get_addr(xff='1.1.1.1') == '1.1.1.1', 'xff replace' + assert self.get_addr('ipv6', '1.1.1.1') == '::1', 'bad source ipv6 2' + + assert self.get_scheme() == 'http', 'ipv4 default proto 2' + assert self.get_scheme('ipv6') == 'http', 'ipv6 default proto 2' + assert self.get_scheme(xfp='https') == 'https', 'xfp replace' + assert self.get_scheme(xfp='on') == 'https', 'xfp replace 2' + assert ( + self.get_scheme('ipv6', xfp='https') == 'http' + ), 'bad proto ipv6 2' + + self.forwarded_header( + { + 'client_ip': 'X-Forwarded-For', + 'protocol': 'X-Forwarded-Proto', + 'source': '!127.0.0.1', + } + ) + + assert self.get_addr(xff='1.1.1.1') == '127.0.0.1', 'bad source 3' + assert self.get_addr('ipv6', '1.1.1.1') == '1.1.1.1', 'xff replace 2' + assert self.get_scheme(xfp='https') == 'http', 'bad proto 2' + assert self.get_scheme('ipv6', xfp='https') == 'https', 'xfp replace 3' + + def test_forwarded_header_ipv4(self): + self.forwarded_header( + { + 'client_ip': 'X-Forwarded-For', + 'protocol': 'X-Forwarded-Proto', + 'source': '127.0.0.1', + } + ) + + assert ( + self.get_addr(xff='8.8.8.8, 84.23.23.11') == '84.23.23.11' + ), 'xff replace' + assert ( + self.get_addr(xff='8.8.8.8, 84.23.23.11, 127.0.0.1') == '127.0.0.1' + ), 'xff replace 2' + assert ( + self.get_addr(xff=['8.8.8.8', '127.0.0.1, 10.0.1.1']) == '10.0.1.1' + ), 'xff replace multi' + + assert self.get_scheme(xfp='http, https') == 'http', 'xfp replace' + assert ( + self.get_scheme(xfp='http, https, http') == 'http' + ), 'xfp replace 2' + assert ( + self.get_scheme(xfp=['http, https', 'http', 'https']) == 'http' + ), 'xfp replace multi' + + def test_forwarded_header_ipv6(self): + self.forwarded_header( + { + 'client_ip': 'X-Forwarded-For', + 'protocol': 'X-Forwarded-Proto', + 'source': '::1', + } + ) + + assert self.get_addr(xff='1.1.1.1') == '127.0.0.1', 'bad source ipv4' + + for ip in [ + 'f607:7403:1e4b:6c66:33b2:843f:2517:da27', + '2001:db8:3c4d:15::1a2f:1a2b', + '2001::3c4d:15:1a2f:1a2b', + '::11.22.33.44', + ]: + assert self.get_addr('ipv6', ip) == ip, 'replace' + + assert self.get_scheme(xfp='https') == 'http', 'bad source ipv4' + + for proto in ['http', 'https']: + assert self.get_scheme('ipv6', xfp=proto) == proto, 'replace' + + def test_forwarded_header_recursive(self): + self.forwarded_header( + { + 'client_ip': 'X-Forwarded-For', + 'recursive': True, + 'source': ['127.0.0.1', '10.50.0.17', '10.5.2.1'], + } + ) + + assert self.get_addr(xff='1.1.1.1') == '1.1.1.1', 'xff chain' + assert ( + self.get_addr(xff='1.1.1.1, 10.5.2.1') == '1.1.1.1' + ), 'xff chain 2' + assert ( + self.get_addr(xff='8.8.8.8, 1.1.1.1, 10.5.2.1') == '1.1.1.1' + ), 'xff chain 3' + assert ( + self.get_addr(xff='10.50.0.17, 10.5.2.1, 10.5.2.1') == '10.50.0.17' + ), 'xff chain 4' + assert ( + self.get_addr(xff=['8.8.8.8', '1.1.1.1, 127.0.0.1']) == '1.1.1.1' + ), 'xff replace multi' + assert ( + self.get_addr(xff=['8.8.8.8', '1.1.1.1, 127.0.0.1', '10.5.2.1']) + == '1.1.1.1' + ), 'xff replace multi 2' + assert ( + self.get_addr(xff=['10.5.2.1', '10.50.0.17, 1.1.1.1', '10.5.2.1']) + == '1.1.1.1' + ), 'xff replace multi 3' + assert ( + self.get_addr( + xff='8.8.8.8, 2001:db8:3c4d:15::1a2f:1a2b, 127.0.0.1' + ) + == '2001:db8:3c4d:15::1a2f:1a2b' + ), 'xff chain ipv6' + + def test_forwarded_header_case_insensitive(self): + self.forwarded_header( + { + 'client_ip': 'x-forwarded-for', + 'protocol': 'x-forwarded-proto', + 'source': '127.0.0.1', + } + ) + + assert self.get_addr() == '127.0.0.1', 'ipv4 default addr' + assert self.get_addr('ipv6') == '::1', 'ipv6 default addr' + assert self.get_addr(xff='1.1.1.1') == '1.1.1.1', 'replace' + + assert self.get_scheme() == 'http', 'ipv4 default proto' + assert self.get_scheme('ipv6') == 'http', 'ipv6 default proto' + assert self.get_scheme(xfp='https') == 'https', 'replace 1' + assert self.get_scheme(xfp='oN') == 'https', 'replace 2' + + def test_forwarded_header_source_empty(self): + self.forwarded_header( + { + 'client_ip': 'X-Forwarded-For', + 'protocol': 'X-Forwarded-Proto', + 'source': [], + } + ) + + assert self.get_addr(xff='1.1.1.1') == '127.0.0.1', 'empty source xff' + assert self.get_scheme(xfp='https') == 'http', 'empty source xfp' + + def test_forwarded_header_source_range(self): + self.forwarded_header( + { + 'client_ip': 'X-Forwarded-For', + 'protocol': 'X-Forwarded-Proto', + 'source': '127.0.0.0-127.0.0.1', + } + ) + + assert self.get_addr(xff='1.1.1.1') == '1.1.1.1', 'source range' + assert self.get_addr('ipv6', '1.1.1.1') == '::1', 'source range 2' + + def test_forwarded_header_invalid(self): + assert 'error' in self.conf( + { + "127.0.0.1:7081": { + "forwarded": {"source": '127.0.0.1'}, + "pass": "applications/forwarded_header", + } + }, + 'listeners', + ), 'invalid forward' + + def check_invalid_source(source): + assert 'error' in self.conf( + { + "127.0.0.1:7081": { + "forwarded": { + "client_ip": "X-Forwarded-For", + "source": source, + }, + "pass": "applications/forwarded_header", + } + }, + 'listeners', + ), 'invalid source' + + check_invalid_source(None) + check_invalid_source('a') + check_invalid_source(['a']) -- cgit From e42c52cff68b2bf39f97b6d21b153de730e54d5a Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Mon, 20 Jun 2022 18:21:43 +0400 Subject: Switched changelogs to packaging alias instead of personal emails. --- docs/changes.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 24c3f9db..38909a42 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -16,7 +16,7 @@ unit-jsc14 unit-jsc15 unit-jsc16 unit-jsc17 unit-jsc18" ver="1.28.0" rev="1" date="" time="" - packager="Konstantin Pavlov <thresh@nginx.com>"> + packager="Nginx Packaging <nginx-packaging@f5.com>"> @@ -29,7 +29,7 @@ NGINX Unit updated to 1.28.0. + packager="Nginx Packaging <nginx-packaging@f5.com>"> -- cgit From d220eb2996513134d3553dbb4ae6b6bbf4692775 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Mon, 20 Jun 2022 10:53:24 +0400 Subject: Packages: dropped /etc/unit directory. It's never used. --- pkg/deb/debian/dirs | 1 - pkg/rpm/unit.spec.in | 2 -- 2 files changed, 3 deletions(-) diff --git a/pkg/deb/debian/dirs b/pkg/deb/debian/dirs index fdcb4340..4a6618c8 100644 --- a/pkg/deb/debian/dirs +++ b/pkg/deb/debian/dirs @@ -1,4 +1,3 @@ usr/sbin -etc/unit usr/lib/unit var/lib/unit diff --git a/pkg/rpm/unit.spec.in b/pkg/rpm/unit.spec.in index 4cbc7358..a9f47e9d 100644 --- a/pkg/rpm/unit.spec.in +++ b/pkg/rpm/unit.spec.in @@ -115,7 +115,6 @@ DESTDIR=%{buildroot} make unitd-install libunit-install manpage-install %{__mkdir} -p %{buildroot}%{_sysconfdir}/logrotate.d %{__install} -m 644 -p %{SOURCE4} \ %{buildroot}%{_sysconfdir}/logrotate.d/unit -%{__mkdir} -p %{buildroot}%{_sysconfdir}/unit %{__mkdir} -p %{buildroot}%{_datadir}/doc/unit/examples %{__install} -m 644 -p %{SOURCE3} \ %{buildroot}%{_datadir}/doc/unit/examples/example.config @@ -203,7 +202,6 @@ BANNER %defattr(-,root,root,-) %attr(0755,root,root) %{_sbindir}/unitd %attr(0755,root,root) %{_sbindir}/unitd-debug -%dir %{_sysconfdir}/unit %{_unitdir}/unit.service %{_unitdir}/unit-debug.service %dir %attr(0755,root,root) %ghost %{_localstatedir}/run/unit -- cgit From c3e40ae932f0cf9ae33166479049d2d3c9fa1615 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 6 Jun 2022 14:18:01 +0200 Subject: Static: Fixed finding the file extension. 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: 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: --- docs/changes.xml | 7 +++++++ src/nxt_http_static.c | 13 +++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 38909a42..65e9d200 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -37,6 +37,13 @@ forwarded header to replace client address and protocol. + + +an index file that didn't contain a file extension was incorrectly +handled, and caused a use-after-free bug. + + + diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 61dd0cb3..eef96c16 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -756,9 +756,7 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten) end = path->start + path->length; p = end; - for ( ;; ) { - /* There's always '/' in the beginning of the request path. */ - + while (p > path->start) { p--; ch = *p; @@ -767,11 +765,14 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten) p++; /* Fall through. */ case '.': - exten->length = end - p; - exten->start = p; - return; + goto extension; } } + +extension: + + exten->length = end - p; + exten->start = p; } -- cgit From 637a2006a6c0da5825dd6b04940e05e2c9feda5d Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Mon, 20 Jun 2022 18:20:11 +0400 Subject: Packages: cleanup targets that are not supported anymore. --- pkg/deb/Makefile | 15 ----- pkg/deb/Makefile.jsc13 | 71 ---------------------- pkg/deb/Makefile.jsc14 | 71 ---------------------- pkg/deb/Makefile.jsc15 | 71 ---------------------- pkg/deb/Makefile.python | 46 -------------- pkg/deb/Makefile.python34 | 46 -------------- pkg/deb/Makefile.python35 | 46 -------------- pkg/deb/debian.module/copyright.unit-jsc10 | 33 ---------- pkg/deb/debian.module/unit.example-jsc10-config | 15 ----- pkg/deb/debian.module/unit.example-jsc13-config | 15 ----- pkg/deb/debian.module/unit.example-jsc14-config | 15 ----- pkg/deb/debian.module/unit.example-jsc15-config | 15 ----- pkg/deb/debian.module/unit.example-jsc9-config | 15 ----- pkg/deb/debian.module/unit.example-python-config | 16 ----- .../debian.module/unit.example-python3.4-config | 16 ----- .../debian.module/unit.example-python3.5-config | 16 ----- pkg/rpm/Makefile | 45 +------------- pkg/rpm/Makefile.python | 57 ----------------- pkg/rpm/Makefile.python35 | 52 ---------------- pkg/rpm/Makefile.python38 | 57 ----------------- pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10 | 32 ---------- .../rpmbuild/SOURCES/unit.example-python35-config | 16 ----- .../rpmbuild/SOURCES/unit.example-python38-config | 16 ----- 23 files changed, 2 insertions(+), 795 deletions(-) delete mode 100644 pkg/deb/Makefile.jsc13 delete mode 100644 pkg/deb/Makefile.jsc14 delete mode 100644 pkg/deb/Makefile.jsc15 delete mode 100644 pkg/deb/Makefile.python delete mode 100644 pkg/deb/Makefile.python34 delete mode 100644 pkg/deb/Makefile.python35 delete mode 100644 pkg/deb/debian.module/copyright.unit-jsc10 delete mode 100644 pkg/deb/debian.module/unit.example-jsc10-config delete mode 100644 pkg/deb/debian.module/unit.example-jsc13-config delete mode 100644 pkg/deb/debian.module/unit.example-jsc14-config delete mode 100644 pkg/deb/debian.module/unit.example-jsc15-config delete mode 100644 pkg/deb/debian.module/unit.example-jsc9-config delete mode 100644 pkg/deb/debian.module/unit.example-python-config delete mode 100644 pkg/deb/debian.module/unit.example-python3.4-config delete mode 100644 pkg/deb/debian.module/unit.example-python3.5-config delete mode 100644 pkg/rpm/Makefile.python delete mode 100644 pkg/rpm/Makefile.python35 delete mode 100644 pkg/rpm/Makefile.python38 delete mode 100644 pkg/rpm/rpmbuild/SOURCES/COPYRIGHT.unit-jsc10 delete mode 100644 pkg/rpm/rpmbuild/SOURCES/unit.example-python35-config delete mode 100644 pkg/rpm/rpmbuild/SOURCES/unit.example-python38-config diff --git a/pkg/deb/Makefile b/pkg/deb/Makefile index 52813e37..c4f085f8 100644 --- a/pkg/deb/Makefile +++ b/pkg/deb/Makefile @@ -49,21 +49,6 @@ include Makefile.jsc17 include Makefile.jsc18 endif -# Ubuntu 21.04 -ifeq ($(CODENAME),hirsute) -include Makefile.php -include Makefile.python27 -include Makefile.python39 -include Makefile.go -include Makefile.perl -include Makefile.ruby -include Makefile.jsc-common -include Makefile.jsc11 -include Makefile.jsc15 -include Makefile.jsc16 -include Makefile.jsc17 -endif - # Ubuntu 20.04 ifeq ($(CODENAME),focal) include Makefile.php diff --git a/pkg/deb/Makefile.jsc13 b/pkg/deb/Makefile.jsc13 deleted file mode 100644 index d22944dc..00000000 --- a/pkg/deb/Makefile.jsc13 +++ /dev/null @@ -1,71 +0,0 @@ -MODULES+= jsc13 -MODULE_SUFFIX_jsc13= jsc13 - -MODULE_SUMMARY_jsc13= Java 13 module for NGINX Unit - -MODULE_VERSION_jsc13= $(VERSION) -MODULE_RELEASE_jsc13= 1 - -MODULE_CONFARGS_jsc13= java --module=java13 --home=/usr/lib/jvm/java-13-openjdk-$$\(DEB_HOST_ARCH\) --jars=/usr/share/unit-jsc-common/ -MODULE_MAKEARGS_jsc13= java13 -MODULE_INSTARGS_jsc13= java13-install - -MODULE_SOURCES_jsc13= unit.example-jsc-app \ - unit.example-jsc13-config - -BUILD_DEPENDS_jsc13= openjdk-13-jdk-headless openjdk-13-jre-headless -BUILD_DEPENDS+= $(BUILD_DEPENDS_jsc13) - -MODULE_BUILD_DEPENDS_jsc13=,openjdk-13-jdk-headless -MODULE_DEPENDS_jsc13=,openjdk-13-jre-headless,unit-jsc-common (= $(MODULE_VERSION_jsc_common)-$(MODULE_RELEASE_jsc_common)~$(CODENAME)) - -define MODULE_PREINSTALL_jsc13 - mkdir -p debian/unit-jsc13/usr/share/doc/unit-jsc13/examples/jsc-app - install -m 644 -p debian/unit.example-jsc-app debian/unit-jsc13/usr/share/doc/unit-jsc13/examples/jsc-app/index.jsp - install -m 644 -p debian/unit.example-jsc13-config debian/unit-jsc13/usr/share/doc/unit-jsc13/examples/unit.config - install -m 644 -p src/java/README.JSR-340 debian/unit-jsc13/usr/share/doc/unit-jsc13/ -endef -export MODULE_PREINSTALL_jsc13 - -define MODULE_POSTINSTALL_jsc13 - cd $$\(BUILDDIR_unit\) \&\& \ - DESTDIR=$$\(INSTALLDIR\) make java-shared-uninstall -endef -export MODULE_POSTINSTALL_jsc13 - -define MODULE_POST_jsc13 -cat < -ifeq ($(shell test `rpm --eval '0%{?rhel} -eq 6 -a 0%{?amzn} -eq 0'`; echo $$?), 0) -OSVER = centos6 -else ifeq ($(shell test `rpm --eval '0%{?rhel} -eq 7 -a 0%{?amzn} -eq 0'`; echo $$?), 0) +ifeq ($(shell test `rpm --eval '0%{?rhel} -eq 7 -a 0%{?amzn} -eq 0'`; echo $$?), 0) OSVER = centos7 else ifeq ($(shell rpm --eval "%{?rhel}"), 8) OSVER = centos8 else ifeq ($(shell rpm --eval "%{?rhel}"), 9) OSVER = centos9 -else ifeq ($(shell rpm --eval "%{?amzn}"), 1) -OSVER = amazonlinux1 else ifeq ($(shell rpm --eval "%{?amzn}"), 2) OSVER = amazonlinux2 else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1315 -a 0%{?suse_version} -lt 1330 -a 0%{?is_opensuse} -eq 1'`; echo $$?), 0) @@ -28,7 +24,7 @@ else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1330 -a 0%{?is_opensu OSVER = opensuse-tumbleweed else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1315 -a 0%{?is_opensuse} -eq 0'`; echo $$?), 0) OSVER = sles -else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 26'`; echo $$?),0) +else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 35'`; echo $$?),0) OSVER = fedora endif @@ -38,10 +34,6 @@ ifeq ($(OSVER), centos7) BUILD_DEPENDS_unit += which endif -ifeq ($(OSVER), amazonlinux1) -BUILD_DEPENDS_unit += system-rpm-config -endif - ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed sles)) BUILD_DEPENDS_unit += libxml2-tools libxslt1 libopenssl-devel else @@ -56,14 +48,6 @@ BUILD_DEPENDS = $(BUILD_DEPENDS_unit) MODULES= -ifeq ($(OSVER), centos6) -include Makefile.php -include Makefile.python -include Makefile.go -include Makefile.jsc-common -include Makefile.jsc8 -endif - ifeq ($(OSVER), centos7) include Makefile.php include Makefile.python27 @@ -96,18 +80,6 @@ include Makefile.jsc8 include Makefile.jsc11 endif -ifeq ($(OSVER), amazonlinux1) -include Makefile.php -include Makefile.python27 -include Makefile.python34 -include Makefile.python35 -include Makefile.python36 -include Makefile.go -include Makefile.perl -include Makefile.jsc-common -include Makefile.jsc8 -endif - ifeq ($(OSVER), amazonlinux2) include Makefile.php include Makefile.python27 @@ -143,20 +115,7 @@ endif ifeq ($(OSVER), fedora) include Makefile.php -ifeq ($(shell test `rpm --eval '0%{?fedora} -lt 32'`; echo $$?),0) -include Makefile.python27 -endif -ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 35'`; echo $$?),0) include Makefile.python310 -else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 33'`; echo $$?),0) -include Makefile.python39 -else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 32'`; echo $$?),0) -include Makefile.python38 -else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 29'`; echo $$?),0) -include Makefile.python37 -else -include Makefile.python36 -endif include Makefile.go include Makefile.perl include Makefile.ruby diff --git a/pkg/rpm/Makefile.python b/pkg/rpm/Makefile.python deleted file mode 100644 index 334d62c1..00000000 --- a/pkg/rpm/Makefile.python +++ /dev/null @@ -1,57 +0,0 @@ -MODULES+= python -MODULE_SUFFIX_python= python - -MODULE_SUMMARY_python= Python module for NGINX Unit - -MODULE_VERSION_python= $(VERSION) -MODULE_RELEASE_python= 1 - -MODULE_CONFARGS_python= python -MODULE_MAKEARGS_python= python -MODULE_INSTARGS_python= python-install - -MODULE_SOURCES_python= unit.example-python-app \ - unit.example-python-config - -ifeq ($(shell rpm --eval "%{?amzn}"), 1) -BUILD_DEPENDS_python= python26-devel -else -BUILD_DEPENDS_python= python-devel -endif - -BUILD_DEPENDS+= $(BUILD_DEPENDS_python) - -define MODULE_PREINSTALL_python -%{__mkdir} -p %{buildroot}%{_datadir}/doc/unit-python/examples/python-app -%{__install} -m 644 -p %{SOURCE100} \ - %{buildroot}%{_datadir}/doc/unit-python/examples/python-app/wsgi.py -%{__install} -m 644 -p %{SOURCE101} \ - %{buildroot}%{_datadir}/doc/unit-python/examples/unit.config -endef -export MODULE_PREINSTALL_python - -define MODULE_FILES_python -%{_libdir}/unit/modules/* -%{_libdir}/unit/debug-modules/* -endef -export MODULE_FILES_python - -define MODULE_POST_python -cat < Date: Thu, 16 Jun 2022 02:00:52 +0100 Subject: Constified numerous function parameters. 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/ --- src/nxt_conf.c | 10 +++++----- src/nxt_conf.h | 6 +++--- src/nxt_http.h | 5 +++-- src/nxt_http_parse.c | 26 +++++++++++++------------- src/nxt_http_parse.h | 2 +- src/nxt_http_request.c | 12 ++++++------ src/nxt_http_static.c | 4 ++-- src/nxt_mp.c | 4 ++-- src/nxt_port_memory_int.h | 2 +- src/nxt_port_socket.c | 4 ++-- src/nxt_string.c | 2 +- src/nxt_string.h | 2 +- src/nxt_unit.c | 5 +++-- 13 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/nxt_conf.c b/src/nxt_conf.c index 79e776a0..a44b8c75 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -102,7 +102,7 @@ typedef struct { static nxt_int_t nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, nxt_str_t *token); -static u_char *nxt_conf_json_skip_space(u_char *start, u_char *end); +static u_char *nxt_conf_json_skip_space(u_char *start, const u_char *end); static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, u_char *end, nxt_conf_json_error_t *error); static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, @@ -266,7 +266,7 @@ nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count) void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, - nxt_conf_value_t *value, uint32_t index) + const nxt_conf_value_t *value, uint32_t index) { nxt_conf_object_member_t *member; @@ -367,7 +367,7 @@ nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count) void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, - nxt_conf_value_t *value) + const nxt_conf_value_t *value) { array->u.array->elements[index] = *value; } @@ -1271,7 +1271,7 @@ nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end, static u_char * -nxt_conf_json_skip_space(u_char *start, u_char *end) +nxt_conf_json_skip_space(u_char *start, const u_char *end) { u_char *p, ch; @@ -2605,7 +2605,7 @@ nxt_conf_json_escape(u_char *dst, u_char *src, size_t size) void -nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line, +nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line, nxt_uint_t *column) { u_char *p; diff --git a/src/nxt_conf.h b/src/nxt_conf.h index cfbc5991..46effac4 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -109,7 +109,7 @@ size_t nxt_conf_json_length(nxt_conf_value_t *value, nxt_conf_json_pretty_t *pretty); u_char *nxt_conf_json_print(u_char *p, nxt_conf_value_t *value, nxt_conf_json_pretty_t *pretty); -void nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line, +void nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line, nxt_uint_t *column); nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt); @@ -125,7 +125,7 @@ NXT_EXPORT uint8_t nxt_conf_get_boolean(nxt_conf_value_t *value); NXT_EXPORT nxt_uint_t nxt_conf_object_members_count(nxt_conf_value_t *value); nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, - nxt_conf_value_t *value, uint32_t index); + const nxt_conf_value_t *value, uint32_t index); void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, nxt_str_t *value, uint32_t index); nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, @@ -137,7 +137,7 @@ void nxt_conf_set_member_null(nxt_conf_value_t *object, nxt_str_t *name, nxt_conf_value_t *nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, - nxt_conf_value_t *value); + const nxt_conf_value_t *value); nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp, nxt_uint_t index, nxt_str_t *value); NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count(nxt_conf_value_t *value); diff --git a/src/nxt_http.h b/src/nxt_http.h index 8fa0caad..4064a8a5 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -376,8 +376,9 @@ nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action, nxt_http_action_conf_t *acf); nxt_int_t nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash); nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, - nxt_str_t *exten, nxt_str_t *type); -nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten); + const nxt_str_t *exten, nxt_str_t *type); +nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, + const nxt_str_t *exten); nxt_http_action_t *nxt_http_application_handler(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action); diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 1ab6cc90..1bb4291f 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -8,16 +8,16 @@ static nxt_int_t nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_field_name(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_field_value(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); -static u_char *nxt_http_lookup_field_end(u_char *p, u_char *end); + u_char **pos, const u_char *end); +static u_char *nxt_http_lookup_field_end(u_char *p, const u_char *end); static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp); @@ -62,7 +62,7 @@ static const uint8_t nxt_http_target_chars[256] nxt_aligned(64) = { nxt_inline nxt_http_target_traps_e -nxt_http_parse_target(u_char **pos, u_char *end) +nxt_http_parse_target(u_char **pos, const u_char *end) { u_char *p; nxt_uint_t trap; @@ -158,7 +158,7 @@ nxt_http_parse_fields(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b) static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p, ch, *after_slash, *args; nxt_int_t rc; @@ -479,7 +479,7 @@ space_after_target: static nxt_int_t nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p, ch; @@ -517,7 +517,7 @@ nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos, static nxt_int_t nxt_http_parse_field_name(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p, c; size_t len; @@ -624,7 +624,7 @@ name_end: static nxt_int_t nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p, *start, ch; size_t len; @@ -704,7 +704,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos, static u_char * -nxt_http_lookup_field_end(u_char *p, u_char *end) +nxt_http_lookup_field_end(u_char *p, const u_char *end) { while (nxt_fast_path(end - p >= 16)) { @@ -771,7 +771,7 @@ nxt_http_lookup_field_end(u_char *p, u_char *end) static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p; nxt_http_field_t *field; diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h index 3cd9bd15..2b714464 100644 --- a/src/nxt_http_parse.h +++ b/src/nxt_http_parse.h @@ -35,7 +35,7 @@ typedef union { struct nxt_http_request_parse_s { nxt_int_t (*handler)(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); nxt_str_t method; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 7fb86cc4..8aa20e59 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -30,11 +30,11 @@ static u_char *nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now, static nxt_http_name_value_t *nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length, uint32_t hash, u_char *start, - u_char *end); + const u_char *end); static nxt_int_t nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, - u_char *end); + const u_char *end); static nxt_http_name_value_t *nxt_http_cookie(nxt_array_t *array, u_char *name, - size_t name_length, u_char *start, u_char *end); + size_t name_length, u_char *start, const u_char *end); #define NXT_HTTP_COOKIE_HASH \ @@ -949,7 +949,7 @@ nxt_http_arguments_parse(nxt_http_request_t *r) static nxt_http_name_value_t * nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length, - uint32_t hash, u_char *start, u_char *end) + uint32_t hash, u_char *start, const u_char *end) { size_t length; nxt_http_name_value_t *nv; @@ -1018,7 +1018,7 @@ nxt_http_cookies_parse(nxt_http_request_t *r) static nxt_int_t -nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) +nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, const u_char *end) { size_t name_length; u_char c, *p, *name; @@ -1067,7 +1067,7 @@ nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) static nxt_http_name_value_t * nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length, - u_char *start, u_char *end) + u_char *start, const u_char *end) { u_char c, *p; uint32_t hash; diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index eef96c16..387cdec0 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -1024,7 +1024,7 @@ typedef struct { nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, - nxt_str_t *exten, nxt_str_t *type) + const nxt_str_t *exten, nxt_str_t *type) { nxt_lvlhsh_query_t lhq; nxt_http_static_mtype_t *mtype; @@ -1049,7 +1049,7 @@ nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, nxt_str_t * -nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten) +nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, const nxt_str_t *exten) { nxt_lvlhsh_query_t lhq; nxt_http_static_mtype_t *mtype; diff --git a/src/nxt_mp.c b/src/nxt_mp.c index d0de2c0e..2bd8cdee 100644 --- a/src/nxt_mp.c +++ b/src/nxt_mp.c @@ -155,7 +155,7 @@ static void *nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size, nxt_bool_t freeable); static intptr_t nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1, nxt_rbtree_node_t *node2); -static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p); +static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p); static const char *nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster, u_char *p); @@ -830,7 +830,7 @@ nxt_mp_free(nxt_mp_t *mp, void *p) static nxt_mp_block_t * -nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p) +nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p) { nxt_mp_block_t *block; nxt_rbtree_node_t *node, *sentinel; diff --git a/src/nxt_port_memory_int.h b/src/nxt_port_memory_int.h index c84615d5..21a05b10 100644 --- a/src/nxt_port_memory_int.h +++ b/src/nxt_port_memory_int.h @@ -100,7 +100,7 @@ nxt_inline void nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, nxt_chunk_id_t c); nxt_inline nxt_chunk_id_t -nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, u_char *p) +nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, const u_char *p) { u_char *mm_start; diff --git a/src/nxt_port_socket.c b/src/nxt_port_socket.c index 2a51dfb6..5752d5ab 100644 --- a/src/nxt_port_socket.c +++ b/src/nxt_port_socket.c @@ -19,7 +19,7 @@ static uint8_t nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm, void *qbuf, nxt_buf_t *b); static nxt_int_t nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, nxt_port_send_msg_t *msg); -static nxt_port_send_msg_t *nxt_port_msg_alloc(nxt_port_send_msg_t *m); +static nxt_port_send_msg_t *nxt_port_msg_alloc(const nxt_port_send_msg_t *m); static void nxt_port_write_handler(nxt_task_t *task, void *obj, void *data); static nxt_port_send_msg_t *nxt_port_msg_first(nxt_port_t *port); nxt_inline void nxt_port_msg_close_fd(nxt_port_send_msg_t *msg); @@ -332,7 +332,7 @@ nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, static nxt_port_send_msg_t * -nxt_port_msg_alloc(nxt_port_send_msg_t *m) +nxt_port_msg_alloc(const nxt_port_send_msg_t *m) { nxt_port_send_msg_t *msg; diff --git a/src/nxt_string.c b/src/nxt_string.c index b7aef79e..4d89c23c 100644 --- a/src/nxt_string.c +++ b/src/nxt_string.c @@ -338,7 +338,7 @@ nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length) size_t -nxt_str_strip(u_char *start, u_char *end) +nxt_str_strip(const u_char *start, u_char *end) { u_char *p; diff --git a/src/nxt_string.h b/src/nxt_string.h index 80cdbb59..a8673c61 100644 --- a/src/nxt_string.h +++ b/src/nxt_string.h @@ -96,7 +96,7 @@ NXT_EXPORT u_char *nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss, size_t length); NXT_EXPORT u_char *nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length); -NXT_EXPORT size_t nxt_str_strip(u_char *start, u_char *end); +NXT_EXPORT size_t nxt_str_strip(const u_char *start, u_char *end); typedef struct { diff --git a/src/nxt_unit.c b/src/nxt_unit.c index f183ac6e..4be09061 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -196,7 +196,8 @@ static int nxt_unit_request_hash_add(nxt_unit_ctx_t *ctx, static nxt_unit_request_info_t *nxt_unit_request_hash_find( nxt_unit_ctx_t *ctx, uint32_t stream, int remove); -static char * nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level); +static char * nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, + int level); static void *nxt_unit_lvlhsh_alloc(void *data, size_t size); static void nxt_unit_lvlhsh_free(void *data, void *p); static int nxt_unit_memcasecmp(const void *p1, const void *p2, size_t length); @@ -6666,7 +6667,7 @@ static const char * nxt_unit_log_levels[] = { static char * -nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level) +nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, int level) { struct tm tm; struct timespec ts; -- cgit From 29c72085262073dc5dec1ecbde1d520da9763746 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:00:53 +0100 Subject: Marked a couple of variables 'const'. 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/ --- src/nxt_time_parse.c | 2 +- src/nxt_websocket_accept.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nxt_time_parse.c b/src/nxt_time_parse.c index 94c43289..63620b09 100644 --- a/src/nxt_time_parse.c +++ b/src/nxt_time_parse.c @@ -22,7 +22,7 @@ nxt_time_parse(const u_char *p, size_t len) nxt_uint_t year, days; const u_char *end; - static nxt_int_t mday[12] = { + static const nxt_int_t mday[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; diff --git a/src/nxt_websocket_accept.c b/src/nxt_websocket_accept.c index 05cbcb56..0e2cef58 100644 --- a/src/nxt_websocket_accept.c +++ b/src/nxt_websocket_accept.c @@ -11,8 +11,8 @@ static void nxt_websocket_base64_encode(u_char *d, const uint8_t *s, size_t len) { - u_char c0, c1, c2; - static u_char basis[] = + u_char c0, c1, c2; + static const u_char basis[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; while (len > 2) { -- cgit From 7a286ec0797df4530eeee6f463ae00b86463084b Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:00:55 +0100 Subject: Socket: removed useless port < 1 check. 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. --- src/nxt_sockaddr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 730428e4..71e50e3c 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -1090,7 +1090,7 @@ nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs) port = nxt_int_parse(host, length); if (port > 0) { - if (port < 1 || port > 65535) { + if (port > 65535) { goto invalid_port; } -- cgit From 39819143ea891b752e5f1f6c6101d0861fb18850 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:00:58 +0100 Subject: Unit: avoided needlessly setting lib in nxt_unit_shm_open(). 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/ --- src/nxt_unit.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 4be09061..9baa680f 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -3813,13 +3813,12 @@ static int nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size) { int fd; - nxt_unit_impl_t *lib; - - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); #if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN) char name[64]; + nxt_unit_impl_t *lib; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); snprintf(name, sizeof(name), NXT_SHM_PREFIX "unit.%d.%p", lib->pid, (void *) (uintptr_t) pthread_self()); #endif -- cgit From 63667e2f9c571ad4357a30e42b321bec6a97ee89 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:01:01 +0100 Subject: Unit: removed a useless assignment. 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/ --- src/nxt_unit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 9baa680f..fd086b2c 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -3076,7 +3076,6 @@ nxt_unit_request_read(nxt_unit_request_info_t *req, void *dst, size_t size) } req->content_length -= res; - size -= res; dst = nxt_pointer_to(dst, res); -- cgit From a3699557a3e4605788bb02a34de8a7979ec96629 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 30 Jun 2022 14:40:17 +0100 Subject: Tests: minor improvements. Added "go" availability check before trying to build an application. update_action() method used were possible and fixed bug with the relative path determination in test_static_chroot.py. Templates optimization and style fixes. --- test/test_static_chroot.py | 126 ++++++++++---------------------------- test/test_tls.py | 2 +- test/test_tls_sni.py | 2 +- test/unit/applications/lang/go.py | 5 ++ test/unit/applications/proto.py | 2 +- 5 files changed, 39 insertions(+), 98 deletions(-) diff --git a/test/test_static_chroot.py b/test/test_static_chroot.py index b896a9b9..e33a181c 100644 --- a/test/test_static_chroot.py +++ b/test/test_static_chroot.py @@ -14,8 +14,7 @@ class TestStaticChroot(TestApplicationProto): Path(temp_dir + '/assets/index.html').write_text('0123456789') Path(temp_dir + '/assets/dir/file').write_text('blah') - test = Path(__file__) - self.test_path = '/' + test.parent.name + '/' + test.name + self.test_path = '/' + os.path.relpath(Path(__file__)) self._load_conf( { @@ -39,26 +38,18 @@ class TestStaticChroot(TestApplicationProto): assert self.get(url='/dir/file')['status'] == 200, 'default chroot' assert self.get(url='/index.html')['status'] == 200, 'default chroot 2' - assert 'success' in self.conf( - { - "share": temp_dir + "/assets$uri", - "chroot": temp_dir + "/assets/dir", - }, - 'routes/0/action', - ), 'configure chroot' + assert 'success' in self.update_action( + temp_dir + "/assets$uri", temp_dir + "/assets/dir" + ) assert self.get(url='/dir/file')['status'] == 200, 'chroot' assert self.get(url='/index.html')['status'] == 403, 'chroot 403 2' assert self.get(url='/file')['status'] == 403, 'chroot 403' def test_share_chroot_array(self, temp_dir): - assert 'success' in self.conf( - { - "share": ["/blah", temp_dir + "/assets$uri"], - "chroot": temp_dir + "/assets/dir", - }, - 'routes/0/action', - ), 'configure share array' + assert 'success' in self.update_action( + ["/blah", temp_dir + "/assets$uri"], temp_dir + "/assets/dir" + ) assert self.get(url='/dir/file')['status'] == 200, 'share array' assert 'success' in self.update_action( @@ -66,13 +57,9 @@ class TestStaticChroot(TestApplicationProto): ) assert self.get_custom('/dir/file', 'dir') == 200, 'array variable' - assert 'success' in self.conf( - { - "share": ["/blah", "/blah2"], - "chroot": temp_dir + "/assets/dir", - }, - 'routes/0/action', - ), 'configure share array bad' + assert 'success' in self.update_action( + ["/blah", "/blah2"], temp_dir + "/assets/dir" + ) assert self.get()['status'] != 200, 'share array bad' def test_static_chroot_permission(self, is_su, temp_dir): @@ -81,58 +68,30 @@ class TestStaticChroot(TestApplicationProto): os.chmod(temp_dir + '/assets/dir', 0o100) - assert 'success' in self.conf( - { - "share": temp_dir + "/assets$uri", - "chroot": temp_dir + "/assets/dir", - }, - 'routes/0/action', + assert 'success' in self.update_action( + temp_dir + "/assets$uri", temp_dir + "/assets/dir" ), 'configure chroot' assert self.get(url='/dir/file')['status'] == 200, 'chroot' def test_static_chroot_empty(self, temp_dir): - assert 'success' in self.conf( - {"share": temp_dir + "/assets$uri", "chroot": ""}, - 'routes/0/action', - ), 'configure chroot empty absolute' - - assert ( - self.get(url='/dir/file')['status'] == 200 - ), 'chroot empty absolute' - - assert 'success' in self.conf( - {"share": ".$uri", "chroot": ""}, - 'routes/0/action', - ), 'configure chroot empty relative' + assert 'success' in self.update_action(temp_dir + "/assets$uri", "") + assert self.get(url='/dir/file')['status'] == 200, 'empty absolute' - assert ( - self.get(url=self.test_path)['status'] == 200 - ), 'chroot empty relative' + assert 'success' in self.update_action(".$uri", "") + assert self.get(url=self.test_path)['status'] == 200, 'empty relative' def test_static_chroot_relative(self, is_su, temp_dir): if is_su: pytest.skip('does\'t work under root') - assert 'success' in self.conf( - {"share": temp_dir + "/assets$uri", "chroot": "."}, - 'routes/0/action', - ), 'configure relative chroot' - + assert 'success' in self.update_action(temp_dir + "/assets$uri", ".") assert self.get(url='/dir/file')['status'] == 403, 'relative chroot' - assert 'success' in self.conf( - {"share": ".$uri"}, - 'routes/0/action', - ), 'configure relative share' - + assert 'success' in self.conf({"share": ".$uri"}, 'routes/0/action') assert self.get(url=self.test_path)['status'] == 200, 'relative share' - assert 'success' in self.conf( - {"share": ".$uri", "chroot": "."}, - 'routes/0/action', - ), 'configure relative' - + assert 'success' in self.update_action(".$uri", ".") assert self.get(url=self.test_path)['status'] == 200, 'relative' def test_static_chroot_variables(self, temp_dir): @@ -150,64 +109,41 @@ class TestStaticChroot(TestApplicationProto): assert 'success' in self.update_action( temp_dir + '/assets/dir/$host', '$uri/assets/dir' ) - assert self.get_custom(temp_dir, 'file') == 200 def test_static_chroot_variables_buildin_mid(self, temp_dir): assert 'success' in self.update_action( temp_dir + '/assets$uri', temp_dir + '/$host/dir' ) - assert self.get_custom('/dir/file', 'assets') == 200 def test_static_chroot_variables_buildin_end(self, temp_dir): assert 'success' in self.update_action( temp_dir + '/assets$uri', temp_dir + '/assets/$host' ) - assert self.get_custom('/dir/file', 'dir') == 200 def test_static_chroot_slash(self, temp_dir): - assert 'success' in self.conf( - { - "share": temp_dir + "/assets$uri", - "chroot": temp_dir + "/assets/dir/", - }, - 'routes/0/action', - ), 'configure chroot slash end' - + assert 'success' in self.update_action( + temp_dir + "/assets$uri", temp_dir + "/assets/dir/" + ) assert self.get(url='/dir/file')['status'] == 200, 'slash end' assert self.get(url='/dirxfile')['status'] == 403, 'slash end bad' - assert 'success' in self.conf( - { - "share": temp_dir + "/assets$uri", - "chroot": temp_dir + "/assets/dir", - }, - 'routes/0/action', - ), 'configure chroot no slash end' - + assert 'success' in self.update_action( + temp_dir + "/assets$uri", temp_dir + "/assets/dir" + ) assert self.get(url='/dir/file')['status'] == 200, 'no slash end' - assert 'success' in self.conf( - { - "share": temp_dir + "/assets$uri", - "chroot": temp_dir + "/assets/dir/", - }, - 'routes/0/action', - ), 'configure chroot slash end 2' - + assert 'success' in self.update_action( + temp_dir + "/assets$uri", temp_dir + "/assets/dir/" + ) assert self.get(url='/dir/file')['status'] == 200, 'slash end 2' assert self.get(url='/dirxfile')['status'] == 403, 'slash end 2 bad' - assert 'success' in self.conf( - { - "share": temp_dir + "///assets/////$uri", - "chroot": temp_dir + "//assets////dir///", - }, - 'routes/0/action', - ), 'configure chroot multiple slashes' - + assert 'success' in self.update_action( + temp_dir + "///assets/////$uri", temp_dir + "//assets////dir///" + ) assert self.get(url='/dir/file')['status'] == 200, 'multiple slashes' def test_static_chroot_invalid(self, temp_dir): diff --git a/test/test_tls.py b/test/test_tls.py index 56ee8298..85f9d3b1 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -13,7 +13,7 @@ class TestTLS(TestApplicationTLS): prerequisites = {'modules': {'python': 'any', 'openssl': 'any'}} def openssl_date_to_sec_epoch(self, date): - return self.date_to_sec_epoch(date, '%b %d %H:%M:%S %Y %Z') + return self.date_to_sec_epoch(date, '%b %d %X %Y %Z') def add_tls(self, application='empty', cert='default', port=7080): assert 'success' in self.conf( diff --git a/test/test_tls_sni.py b/test/test_tls_sni.py index dbd5d900..44cc21e1 100644 --- a/test/test_tls_sni.py +++ b/test/test_tls_sni.py @@ -18,7 +18,7 @@ class TestTLSSNI(TestApplicationTLS): ) def openssl_date_to_sec_epoch(self, date): - return self.date_to_sec_epoch(date, '%b %d %H:%M:%S %Y %Z') + return self.date_to_sec_epoch(date, '%b %d %X %Y %Z') def add_tls(self, cert='default'): assert 'success' in self.conf( diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 04af26e1..3db955f3 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -9,6 +9,11 @@ from unit.option import option class TestApplicationGo(TestApplicationProto): @staticmethod def prepare_env(script, name='app', static=False): + try: + subprocess.check_output(['which', 'go']) + except subprocess.CalledProcessError: + return None + temp_dir = option.temp_dir + '/go/' if not os.path.exists(temp_dir): diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index cd8672ba..6ba7b9b8 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -13,7 +13,7 @@ class TestApplicationProto(TestControl): def sec_epoch(self): return time.mktime(time.gmtime()) - def date_to_sec_epoch(self, date, template='%a, %d %b %Y %H:%M:%S %Z'): + def date_to_sec_epoch(self, date, template='%a, %d %b %Y %X %Z'): return time.mktime(time.strptime(date, template)) def findall(self, pattern, name='unit.log'): -- cgit From f83aef1aab992f97e0f3bc663662055a28b85ee3 Mon Sep 17 00:00:00 2001 From: Timo Stark Date: Mon, 25 Apr 2022 12:57:07 +0200 Subject: Increased readtimeout for configuration endpoint. Closes: --- docs/changes.xml | 6 ++++++ src/nxt_controller.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/changes.xml b/docs/changes.xml index 65e9d200..12ad11f8 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -44,6 +44,12 @@ handled, and caused a use-after-free bug. + + +increased the applications' startup timeout. + + + diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 7510d6f0..e1e9fade 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -725,7 +725,7 @@ static const nxt_event_conn_state_t nxt_controller_conn_read_state .timer_handler = nxt_controller_conn_read_timeout, .timer_value = nxt_controller_conn_timeout_value, - .timer_data = 60 * 1000, + .timer_data = 300 * 1000, }; -- cgit From 7b80186f097fda3d1c0758a30efa889ec89c5a9d Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 14 Jul 2022 04:31:36 +0800 Subject: Var: optimization to get rid of nxt_var_cache_find(). No functional changes. --- src/nxt_var.c | 245 ++++++++++++++++++++-------------------------------------- 1 file changed, 84 insertions(+), 161 deletions(-) diff --git a/src/nxt_var.c b/src/nxt_var.c index a7cbb898..05cd6fd2 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -26,19 +26,12 @@ typedef struct { } nxt_var_sub_t; -typedef struct { - nxt_var_t *var; - nxt_str_t *value; -} nxt_var_value_t; - - struct nxt_var_query_s { - nxt_array_t values; /* of nxt_var_value_t */ - nxt_array_t parts; /* of nxt_str_t * */ + nxt_mp_t *pool; nxt_lvlhsh_t cache; - nxt_str_t *spare; + nxt_uint_t waiting; nxt_uint_t failed; /* 1 bit */ @@ -60,15 +53,12 @@ static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); -static nxt_str_t *nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index); -static nxt_int_t nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, - nxt_str_t *value, nxt_mp_t *mp); +static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, + uint32_t index); static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, nxt_bool_t *is_var); -static void nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query); - static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, @@ -127,28 +117,22 @@ nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) static nxt_str_t * -nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index) +nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index) { + nxt_int_t ret; + nxt_str_t *value; nxt_lvlhsh_query_t lhq; - lhq.key_hash = nxt_murmur_hash2_uint32(&index); - lhq.key.length = sizeof(uint32_t); - lhq.key.start = (u_char *) &index; - lhq.proto = &nxt_var_cache_proto; - - if (nxt_lvlhsh_find(lh, &lhq) != NXT_OK) { - return NULL; - } - - return lhq.value; -} + value = query->spare; + if (value == NULL) { + value = nxt_mp_zget(query->pool, sizeof(nxt_str_t)); + if (nxt_slow_path(value == NULL)) { + return NULL; + } -static nxt_int_t -nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value, - nxt_mp_t *mp) -{ - nxt_lvlhsh_query_t lhq; + query->spare = value; + } lhq.key_hash = nxt_murmur_hash2_uint32(&index); lhq.replace = 0; @@ -156,9 +140,23 @@ nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value, lhq.key.start = (u_char *) &index; lhq.value = value; lhq.proto = &nxt_var_cache_proto; - lhq.pool = mp; + lhq.pool = query->pool; - return nxt_lvlhsh_insert(lh, &lhq); + ret = nxt_lvlhsh_insert(&query->cache, &lhq); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NULL; + } + + if (ret == NXT_OK) { + ret = nxt_var_index[index](task, value, query->ctx); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + query->spare = NULL; + } + + return lhq.value; } @@ -432,14 +430,9 @@ nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp) if (nxt_slow_path(query == NULL)) { return NXT_ERROR; } - - nxt_array_init(&query->values, mp, sizeof(nxt_var_value_t)); - nxt_array_init(&query->parts, mp, sizeof(nxt_str_t *)); - - } else { - nxt_array_reset(&query->values); } + query->pool = mp; query->ctx = ctx; *query_p = query; @@ -452,13 +445,12 @@ void nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, nxt_str_t *str) { - uint32_t index; - nxt_mp_t *mp; - nxt_str_t *value; - nxt_int_t ret; - nxt_uint_t i; - nxt_var_sub_t *subs; - nxt_var_value_t *val; + u_char *p, *src; + size_t length, last, next; + nxt_str_t *value, **part; + nxt_uint_t i; + nxt_array_t parts; + nxt_var_sub_t *subs; if (nxt_var_is_const(var)) { nxt_var_raw(var, str); @@ -469,48 +461,63 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, return; } - mp = query->values.mem_pool; + nxt_memzero(&parts, sizeof(nxt_array_t)); + nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *)); + subs = nxt_var_subs(var); - value = query->spare; + + length = var->length; for (i = 0; i < var->vars; i++) { + value = nxt_var_cache_value(task, query, subs[i].index); + if (nxt_slow_path(value == NULL)) { + goto fail; + } - if (value == NULL) { - value = nxt_mp_zget(mp, sizeof(nxt_str_t)); - if (nxt_slow_path(value == NULL)) { - goto fail; - } + part = nxt_array_add(&parts); + if (nxt_slow_path(part == NULL)) { + goto fail; } - index = subs[i].index; + *part = value; - ret = nxt_var_cache_add(&query->cache, index, value, mp); + length += value->length - subs[i].length; + } - if (ret != NXT_OK) { - if (nxt_slow_path(ret == NXT_ERROR)) { - goto fail; - } + p = nxt_mp_nget(query->pool, length + var->strz); + if (nxt_slow_path(p == NULL)) { + goto fail; + } - continue; /* NXT_DECLINED */ - } + str->length = length; + str->start = p; - ret = nxt_var_index[index](task, value, query->ctx); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; + part = parts.elts; + src = nxt_var_raw_start(var); + + last = 0; + + for (i = 0; i < var->vars; i++) { + next = subs[i].position; + + if (next != last) { + p = nxt_cpymem(p, &src[last], next - last); } - value = NULL; + p = nxt_cpymem(p, part[i]->start, part[i]->length); + + last = next + subs[i].length; } - query->spare = value; + if (last != var->length) { + p = nxt_cpymem(p, &src[last], var->length - last); + } - val = nxt_array_add(&query->values); - if (nxt_slow_path(val == NULL)) { - goto fail; + if (var->strz) { + *p = '\0'; } - val->var = var; - val->value = str; + nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str); return; @@ -529,7 +536,9 @@ nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, query->error = error; if (query->waiting == 0) { - nxt_var_query_finish(task, query); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); } } @@ -541,94 +550,8 @@ nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, query->failed |= failed; if (--query->waiting == 0) { - nxt_var_query_finish(task, query); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); } } - - -static void -nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query) -{ - u_char *p, *src; - size_t length, last, next; - nxt_str_t *str, **part; - nxt_var_t *var; - nxt_uint_t i, j; - nxt_var_sub_t *subs; - nxt_var_value_t *val; - - if (query->failed) { - goto done; - } - - val = query->values.elts; - - for (i = 0; i < query->values.nelts; i++) { - var = val[i].var; - - subs = nxt_var_subs(var); - length = var->length; - - for (j = 0; j < var->vars; j++) { - str = nxt_var_cache_find(&query->cache, subs[j].index); - - nxt_assert(str != NULL); - - part = nxt_array_add(&query->parts); - - if (nxt_slow_path(part == NULL)) { - query->failed = 1; - goto done; - } - - *part = str; - - length += str->length - subs[j].length; - } - - p = nxt_mp_nget(query->values.mem_pool, length + var->strz); - if (nxt_slow_path(p == NULL)) { - query->failed = 1; - goto done; - } - - val[i].value->length = length; - val[i].value->start = p; - - part = query->parts.elts; - src = nxt_var_raw_start(var); - - last = 0; - - for (j = 0; j < var->vars; j++) { - next = subs[j].position; - - if (next != last) { - p = nxt_cpymem(p, &src[last], next - last); - } - - p = nxt_cpymem(p, part[j]->start, part[j]->length); - - last = next + subs[j].length; - } - - if (last != var->length) { - p = nxt_cpymem(p, &src[last], var->length - last); - } - - if (var->strz) { - *p = '\0'; - } - - nxt_array_reset(&query->parts); - - nxt_debug(task, "var: \"%*s\" -> \"%V\"", var->length, src, - val[i].value); - } - -done: - - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - query->failed ? query->error : query->ready, - task, query->ctx, query->data); -} -- cgit From 45b89e32577eef18e473d0c7ae24562e7efedcc0 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 14 Jul 2022 04:32:49 +0800 Subject: Var: dynamic variables support. This commit adds the variables $arg_NAME, $header_NAME, and $cookie_NAME. --- docs/changes.xml | 6 ++ src/nxt_conf.h | 1 + src/nxt_conf_validation.c | 7 +- src/nxt_http.h | 7 +- src/nxt_http_request.c | 54 +++++++++++++ src/nxt_http_return.c | 7 +- src/nxt_http_route.c | 14 ++-- src/nxt_http_static.c | 8 +- src/nxt_http_variables.c | 187 ++++++++++++++++++++++++++++++++++++++++------ src/nxt_router.c | 5 ++ src/nxt_router.h | 1 + src/nxt_var.c | 131 ++++++++++++++++++++++++++++++-- src/nxt_var.h | 28 +++++-- 13 files changed, 407 insertions(+), 49 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 12ad11f8..13a66672 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -37,6 +37,12 @@ forwarded header to replace client address and protocol. + + +ability to get dynamic variables. + + + an index file that didn't contain a file extension was incorrectly diff --git a/src/nxt_conf.h b/src/nxt_conf.h index 46effac4..f95b61c1 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -72,6 +72,7 @@ typedef struct { nxt_mp_t *pool; nxt_str_t error; void *ctx; + nxt_array_t *var_fields; /* of nxt_var_field_t */ nxt_mp_t *conf_pool; nxt_uint_t ver; } nxt_conf_validation_t; diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index a5958788..47164e92 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -1210,6 +1210,11 @@ nxt_conf_validate(nxt_conf_validation_t *vldt) { nxt_int_t ret; + vldt->var_fields = nxt_array_create(vldt->pool, 4, sizeof(nxt_var_field_t)); + if (nxt_slow_path(vldt->var_fields == NULL)) { + return NXT_ERROR; + } + ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT); if (ret != NXT_OK) { return ret; @@ -1342,7 +1347,7 @@ nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name, { u_char error[NXT_MAX_ERROR_STR]; - if (nxt_var_test(value, error) != NXT_OK) { + if (nxt_var_test(value, vldt->var_fields, error) != NXT_OK) { return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.", error, name); } diff --git a/src/nxt_http.h b/src/nxt_http.h index 4064a8a5..c2e85840 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -339,6 +339,9 @@ nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r); int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, nxt_bool_t case_sensitive, uint8_t encoding); +int64_t nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name); +int64_t nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name); +int64_t nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name); nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf); @@ -369,8 +372,8 @@ nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf, nxt_upstream_t ***upstream_joint); -nxt_int_t nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, - nxt_http_action_conf_t *acf); +nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf, + nxt_http_action_t *action, nxt_http_action_conf_t *acf); nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action, nxt_http_action_conf_t *acf); diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 8aa20e59..5f8fd8f7 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -1180,3 +1180,57 @@ end: return nxt_http_field_hash_end(hash) & 0xFFFF; } + + +int64_t +nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name) +{ + return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_PLUS); +} + + +int64_t +nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name) +{ + u_char c, *p; + uint32_t i, hash; + nxt_str_t str; + + str.length = name->length; + + str.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(str.start == NULL)) { + return -1; + } + + p = str.start; + hash = NXT_HTTP_FIELD_HASH_INIT; + + for (i = 0; i < name->length; i++) { + c = name->start[i]; + + if (c >= 'A' && c <= 'Z') { + *p = c | 0x20; + + } else if (c == '_') { + *p = '-'; + + } else { + *p = c; + } + + hash = nxt_http_field_hash_char(hash, *p); + p++; + } + + *name = str; + + return nxt_http_field_hash_end(hash) & 0xFFFF; +} + + +int64_t +nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name) +{ + return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_NONE); +} diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c index 82c91568..9f3c4fc5 100644 --- a/src/nxt_http_return.c +++ b/src/nxt_http_return.c @@ -32,12 +32,15 @@ static const nxt_http_request_state_t nxt_http_return_send_state; nxt_int_t -nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, +nxt_http_return_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, nxt_http_action_conf_t *acf) { + nxt_mp_t *mp; nxt_str_t str; nxt_http_return_conf_t *conf; + mp = rtcf->mem_pool; + conf = nxt_mp_zget(mp, sizeof(nxt_http_return_conf_t)); if (nxt_slow_path(conf == NULL)) { return NXT_ERROR; @@ -54,7 +57,7 @@ nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, nxt_conf_get_string(acf->location, &str); - conf->location = nxt_var_compile(&str, mp, 0); + conf->location = nxt_var_compile(&str, mp, rtcf->var_fields, 0); if (nxt_slow_path(conf->location == NULL)) { return NXT_ERROR; } diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 5a4f349e..e00c37fe 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -643,6 +643,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_mp_t *mp; nxt_int_t ret; nxt_str_t pass; + nxt_router_conf_t *rtcf; nxt_http_action_conf_t acf; nxt_memzero(&acf, sizeof(acf)); @@ -655,10 +656,11 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_memzero(action, sizeof(nxt_http_action_t)); - mp = tmcf->router_conf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; if (acf.ret != NULL) { - return nxt_http_return_init(mp, action, &acf); + return nxt_http_return_init(rtcf, action, &acf); } if (acf.share != NULL) { @@ -671,7 +673,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_get_string(acf.pass, &pass); - action->u.var = nxt_var_compile(&pass, mp, 0); + action->u.var = nxt_var_compile(&pass, mp, rtcf->var_fields, 0); if (nxt_slow_path(action->u.var == NULL)) { return NXT_ERROR; } @@ -1484,16 +1486,18 @@ nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, { nxt_mp_t *mp; nxt_int_t ret; + nxt_router_conf_t *rtcf; nxt_http_action_t *action; - mp = tmcf->router_conf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; action = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); if (nxt_slow_path(action == NULL)) { return NULL; } - action->u.var = nxt_var_compile(pass, mp, 0); + action->u.var = nxt_var_compile(pass, mp, rtcf->var_fields, 0); if (nxt_slow_path(action->u.var == NULL)) { return NULL; } diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 387cdec0..19393f2c 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -79,9 +79,11 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_str_t str, *ret; nxt_var_t *var; nxt_conf_value_t *cv; + nxt_router_conf_t *rtcf; nxt_http_static_conf_t *conf; - mp = tmcf->router_conf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t)); if (nxt_slow_path(conf == NULL)) { @@ -102,7 +104,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, cv = nxt_conf_get_array_element_or_itself(acf->share, i); nxt_conf_get_string(cv, &str); - var = nxt_var_compile(&str, mp, 1); + var = nxt_var_compile(&str, mp, rtcf->var_fields, 1); if (nxt_slow_path(var == NULL)) { return NXT_ERROR; } @@ -128,7 +130,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_str_t chr, shr; nxt_bool_t is_const; - conf->chroot = nxt_var_compile(&acf->chroot, mp, 1); + conf->chroot = nxt_var_compile(&acf->chroot, mp, rtcf->var_fields, 1); if (nxt_slow_path(conf->chroot == NULL)) { return NXT_ERROR; } diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index c48f9ca3..79e66668 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -8,29 +8,47 @@ static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, - void *ctx); + void *ctx, uint16_t field); static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, - void *ctx); -static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx); + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); static nxt_var_decl_t nxt_http_vars[] = { - { nxt_string("method"), - &nxt_http_var_method, - 0 }, - - { nxt_string("request_uri"), - &nxt_http_var_request_uri, - 0 }, - - { nxt_string("uri"), - &nxt_http_var_uri, - 0 }, - - { nxt_string("host"), - &nxt_http_var_host, - 0 }, + { + .name = nxt_string("method"), + .handler = nxt_http_var_method, + }, { + .name = nxt_string("request_uri"), + .handler = nxt_http_var_request_uri, + }, { + .name = nxt_string("uri"), + .handler = nxt_http_var_uri, + }, { + .name = nxt_string("host"), + .handler = nxt_http_var_host, + }, { + .name = nxt_string("arg"), + .handler = nxt_http_var_arg, + .field_hash = nxt_http_argument_hash, + }, { + .name = nxt_string("header"), + .handler = nxt_http_var_header, + .field_hash = nxt_http_header_hash, + }, { + .name = nxt_string("cookie"), + .handler = nxt_http_var_cookie, + .field_hash = nxt_http_cookie_hash, + }, }; @@ -42,7 +60,7 @@ nxt_http_register_variables(void) static nxt_int_t -nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx) +nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -55,7 +73,8 @@ nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx) static nxt_int_t -nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) +nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) { nxt_http_request_t *r; @@ -68,7 +87,7 @@ nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) static nxt_int_t -nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) +nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -81,7 +100,7 @@ nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) static nxt_int_t -nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx) +nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -91,3 +110,125 @@ nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx) return NXT_OK; } + + +static nxt_int_t +nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_array_t *args; + nxt_var_field_t *vf; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + args = nxt_http_arguments_parse(r); + if (nxt_slow_path(args == NULL)) { + return NXT_ERROR; + } + + start = args->elts; + nv = start + args->nelts - 1; + + while (nv >= start) { + + if (vf->hash == nv->hash + && vf->name.length == nv->name_length + && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + { + str->start = nv->value; + str->length = nv->value_length; + + return NXT_OK; + } + + nv--; + } + + nxt_str_null(str); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_var_field_t *vf; + nxt_http_field_t *f; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + nxt_list_each(f, r->fields) { + + if (vf->hash == f->hash + && vf->name.length == f->name_length + && nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0) + { + str->start = f->value; + str->length = f->value_length; + + return NXT_OK; + } + + } nxt_list_loop; + + nxt_str_null(str); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_array_t *cookies; + nxt_var_field_t *vf; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *end; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return NXT_ERROR; + } + + nv = cookies->elts; + end = nv + cookies->nelts; + + while (nv < end) { + + if (vf->hash == nv->hash + && vf->name.length == nv->name_length + && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + { + str->start = nv->value; + str->length = nv->value_length; + + return NXT_OK; + } + + nv++; + } + + nxt_str_null(str); + + return NXT_OK; +} diff --git a/src/nxt_router.c b/src/nxt_router.c index a3cc0a8d..e84b3d9a 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1004,6 +1004,11 @@ nxt_router_temp_conf(nxt_task_t *task) rtcf->mem_pool = mp; + rtcf->var_fields = nxt_array_create(mp, 4, sizeof(nxt_var_field_t)); + if (nxt_slow_path(rtcf->var_fields == NULL)) { + goto fail; + } + tmp = nxt_mp_create(1024, 128, 256, 32); if (nxt_slow_path(tmp == NULL)) { goto fail; diff --git a/src/nxt_router.h b/src/nxt_router.h index 37008f9d..8c21a70a 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -43,6 +43,7 @@ typedef struct { uint32_t threads; nxt_mp_t *mem_pool; + nxt_array_t *var_fields; /* of nxt_var_field_t */ nxt_router_t *router; nxt_http_routes_t *routes; diff --git a/src/nxt_var.c b/src/nxt_var.c index 05cd6fd2..d3057764 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -52,6 +52,11 @@ struct nxt_var_query_s { static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); +static nxt_var_decl_t *nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, + uint32_t *index); +static nxt_var_field_t *nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, + uint32_t hash); + static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index); @@ -109,6 +114,117 @@ nxt_var_hash_find(nxt_str_t *name) } +static nxt_var_decl_t * +nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, uint32_t *index) +{ + u_char *p, *end; + int64_t hash; + uint16_t field; + nxt_str_t str; + nxt_var_decl_t *decl; + nxt_var_field_t *f; + + f = NULL; + field = 0; + decl = nxt_var_hash_find(name); + + if (decl == NULL) { + p = name->start; + end = p + name->length; + + while (p < end) { + if (*p++ == '_') { + break; + } + } + + if (p == end) { + return NULL; + } + + str.start = name->start; + str.length = p - 1 - name->start; + + decl = nxt_var_hash_find(&str); + + if (decl != NULL) { + str.start = p; + str.length = end - p; + + hash = decl->field_hash(fields->mem_pool, &str); + if (nxt_slow_path(hash == -1)) { + return NULL; + } + + f = nxt_var_field_add(fields, &str, (uint32_t) hash); + if (nxt_slow_path(f == NULL)) { + return NULL; + } + + field = f->index; + } + } + + if (decl != NULL) { + if (decl->field_hash != NULL && f == NULL) { + return NULL; + } + + if (index != NULL) { + *index = (decl->index << 16) | field; + } + } + + return decl; +} + + +static nxt_var_field_t * +nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, uint32_t hash) +{ + nxt_uint_t i; + nxt_var_field_t *field; + + field = fields->elts; + + for (i = 0; i < fields->nelts; i++) { + if (field[i].hash == hash + && nxt_strstr_eq(&field[i].name, name)) + { + return field; + } + } + + field = nxt_array_add(fields); + if (nxt_slow_path(field == NULL)) { + return NULL; + } + + field->name = *name; + field->hash = hash; + field->index = fields->nelts - 1; + + return field; +} + + +nxt_var_field_t * +nxt_var_field_get(nxt_array_t *fields, uint16_t index) +{ + nxt_uint_t nfields; + nxt_var_field_t *field; + + field = fields->elts; + nfields = fields->nelts; + + if (nfields > 0 && index <= nfields) { + return &field[index]; + } + + return NULL; +} + + static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) { @@ -148,7 +264,8 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index) } if (ret == NXT_OK) { - ret = nxt_var_index[index](task, value, query->ctx); + ret = nxt_var_index[index >> 16](task, value, query->ctx, + index & 0xffff); if (nxt_slow_path(ret != NXT_OK)) { return NULL; } @@ -213,10 +330,12 @@ nxt_var_index_init(void) nxt_var_t * -nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) +nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, + nxt_bool_t strz) { u_char *p, *end, *next, *src; size_t size; + uint32_t index; nxt_var_t *var; nxt_str_t part; nxt_uint_t n; @@ -267,12 +386,12 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) next = nxt_var_next_part(p, end - p, &part, &is_var); if (is_var) { - decl = nxt_var_hash_find(&part); + decl = nxt_var_decl_get(&part, fields, &index); if (nxt_slow_path(decl == NULL)) { return NULL; } - subs[n].index = decl->index; + subs[n].index = index; subs[n].length = next - p; subs[n].position = p - str->start; @@ -287,7 +406,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) nxt_int_t -nxt_var_test(nxt_str_t *str, u_char *error) +nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) { u_char *p, *end, *next; nxt_str_t part; @@ -308,7 +427,7 @@ nxt_var_test(nxt_str_t *str, u_char *error) } if (is_var) { - decl = nxt_var_hash_find(&part); + decl = nxt_var_decl_get(&part, fields, NULL); if (decl == NULL) { nxt_sprintf(error, error + NXT_MAX_ERROR_STR, diff --git a/src/nxt_var.h b/src/nxt_var.h index 1322d507..3c38be36 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -13,15 +13,25 @@ typedef struct nxt_var_query_s nxt_var_query_t; typedef nxt_int_t (*nxt_var_handler_t)(nxt_task_t *task, nxt_str_t *str, - void *ctx); + void *ctx, uint16_t field); + +typedef int64_t (*nxt_var_field_hash_t)(nxt_mp_t *mp, nxt_str_t *str); typedef struct { - nxt_str_t name; - nxt_var_handler_t handler; - uint32_t index; + nxt_str_t name; + nxt_var_handler_t handler; + nxt_var_field_hash_t field_hash; + uint32_t index; } nxt_var_decl_t; +typedef struct { + nxt_str_t name; + uint16_t hash; + uint32_t index; +} nxt_var_field_t; + + nxt_inline nxt_bool_t nxt_is_var(nxt_str_t *str) { @@ -31,11 +41,15 @@ nxt_is_var(nxt_str_t *str) nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n); nxt_int_t nxt_var_index_init(void); -nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz); -nxt_int_t nxt_var_test(nxt_str_t *str, u_char *error); -void nxt_var_raw(nxt_var_t *var, nxt_str_t *str); +nxt_var_field_t *nxt_var_field_get(nxt_array_t *fields, uint16_t index); + +nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, + nxt_bool_t strz); +nxt_int_t nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error); + nxt_bool_t nxt_var_is_const(nxt_var_t *var); +void nxt_var_raw(nxt_var_t *var, nxt_str_t *str); nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp); -- cgit From d358b1d4480e64ae63cefcf97c4bd89dd968ea44 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 14 Jul 2022 11:50:41 +0100 Subject: Tests: added tests for dynamic variables. --- test/test_variables.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/test/test_variables.py b/test/test_variables.py index 71553685..577408f6 100644 --- a/test/test_variables.py +++ b/test/test_variables.py @@ -18,6 +18,7 @@ class TestVariables(TestApplicationProto): "GETGET": [{"action": {"return": 207}}], "localhost": [{"action": {"return": 208}}], "9?q#a": [{"action": {"return": 209}}], + "blah": [{"action": {"return": 210}}], }, }, ), 'configure routes' @@ -124,6 +125,80 @@ class TestVariables(TestApplicationProto): update_pass("applications") assert self.get(url='/3')['status'] == 404 + def test_variables_dynamic(self): + self.conf_routes("\"routes/$header_foo$arg_foo$cookie_foo\"") + + self.get( + url='/?foo=h', + headers={'Foo': 'b', 'Cookie': 'foo=la', 'Connection': 'close'}, + )['status'] = 210 + + def test_variables_dynamic_headers(self): + def check_header(header, status=210): + assert ( + self.get(headers={header: "blah", 'Connection': 'close'})[ + 'status' + ] + == status + ) + + self.conf_routes("\"routes/$header_foo_bar\"") + check_header('foo-bar') + check_header('Foo-Bar') + check_header('foo_bar', 404) + check_header('Foo', 404) + check_header('Bar', 404) + check_header('foobar', 404) + + self.conf_routes("\"routes/$header_Foo_Bar\"") + check_header('Foo-Bar') + check_header('foo-bar') + check_header('foo_bar', 404) + check_header('foobar', 404) + + self.conf_routes("\"routes/$header_foo-bar\"") + check_header('foo_bar', 404) + + def test_variables_dynamic_arguments(self): + self.conf_routes("\"routes/$arg_foo_bar\"") + assert self.get(url='/?foo_bar=blah')['status'] == 210 + assert self.get(url='/?foo_b%61r=blah')['status'] == 210 + assert self.get(url='/?bar&foo_bar=blah&foo')['status'] == 210 + assert self.get(url='/?Foo_bar=blah')['status'] == 404 + assert self.get(url='/?foo-bar=blah')['status'] == 404 + assert self.get()['status'] == 404 + assert self.get(url='/?foo_bar=')['status'] == 404 + assert self.get(url='/?foo_bar=l&foo_bar=blah')['status'] == 210 + assert self.get(url='/?foo_bar=blah&foo_bar=l')['status'] == 404 + + self.conf_routes("\"routes/$arg_foo_b%61r\"") + assert self.get(url='/?foo_b=blah')['status'] == 404 + assert self.get(url='/?foo_bar=blah')['status'] == 404 + + self.conf_routes("\"routes/$arg_f!~\"") + assert self.get(url='/?f=blah')['status'] == 404 + assert self.get(url='/?f!~=blah')['status'] == 404 + + def test_variables_dynamic_cookies(self): + def check_cookie(cookie, status=210): + assert ( + self.get( + headers={ + 'Host': 'localhost', + 'Cookie': cookie, + 'Connection': 'close', + }, + )['status'] + == status + ), 'match cookie' + + self.conf_routes("\"routes/$cookie_foo_bar\"") + check_cookie('foo_bar=blah', 210) + check_cookie('fOo_bar=blah', 404) + assert self.get()['status'] == 404 + check_cookie('foo_bar', 404) + check_cookie('foo_bar=', 404) + def test_variables_invalid(self): def check_variables(routes): assert 'error' in self.conf( @@ -137,3 +212,10 @@ class TestVariables(TestApplicationProto): check_variables("\"routes$uriblah\"") check_variables("\"routes${uri\"") check_variables("\"routes${{uri}\"") + check_variables("\"routes$ar\"") + check_variables("\"routes$arg\"") + check_variables("\"routes$arg_\"") + check_variables("\"routes$cookie\"") + check_variables("\"routes$cookie_\"") + check_variables("\"routes$header\"") + check_variables("\"routes$header_\"") -- cgit From 8c5e2d5ce5cc31649f8900621d1b92d66100a687 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 14 Jul 2022 04:34:05 +0800 Subject: HTTP: added more variables. This commit adds the following variables: $remote_addr, $time_local, $request_line, $status, $body_bytes_sent, $header_referer, $header_user_agent. --- docs/changes.xml | 6 ++ src/nxt_http_variables.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+) diff --git a/docs/changes.xml b/docs/changes.xml index 13a66672..f8745641 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -43,6 +43,12 @@ ability to get dynamic variables. + + +more http variables support. + + + an index file that didn't contain a file extension was incorrectly diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index 79e66668..837ef7b0 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -15,6 +15,22 @@ static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field); static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, const char *format); +static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field); static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, @@ -36,6 +52,27 @@ static nxt_var_decl_t nxt_http_vars[] = { }, { .name = nxt_string("host"), .handler = nxt_http_var_host, + }, { + .name = nxt_string("remote_addr"), + .handler = nxt_http_var_remote_addr, + }, { + .name = nxt_string("time_local"), + .handler = nxt_http_var_time_local, + }, { + .name = nxt_string("request_line"), + .handler = nxt_http_var_request_line, + }, { + .name = nxt_string("status"), + .handler = nxt_http_var_status, + }, { + .name = nxt_string("body_bytes_sent"), + .handler = nxt_http_var_body_bytes_sent, + }, { + .name = nxt_string("header_referer"), + .handler = nxt_http_var_referer, + }, { + .name = nxt_string("header_user_agent"), + .handler = nxt_http_var_user_agent, }, { .name = nxt_string("arg"), .handler = nxt_http_var_arg, @@ -112,6 +149,204 @@ nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) } +static nxt_int_t +nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + str->length = r->remote->address_length; + str->start = nxt_sockaddr_address(r->remote); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t) -1, + nxt_http_log_date, + "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", + nxt_length("31/Dec/1986:19:40:00 +0300"), + NXT_THREAD_TIME_LOCAL, + NXT_THREAD_TIME_SEC, + }; + + r = ctx; + + str->length = date_cache.size; + + str->start = nxt_mp_nget(r->mem_pool, str->length); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + str->length = nxt_thread_time_string(task->thread, &date_cache, str->start) + - str->start; + + return NXT_OK; +} + + +static u_char * +nxt_http_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, + size_t size, const char *format) +{ + u_char sign; + time_t gmtoff; + + static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + gmtoff = nxt_timezone(tm) / 60; + + if (gmtoff < 0) { + gmtoff = -gmtoff; + sign = '-'; + + } else { + sign = '+'; + } + + return nxt_sprintf(buf, buf + size, format, + tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, gmtoff / 60, gmtoff % 60); +} + + +static nxt_int_t +nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + size_t length; + u_char *p, *start; + nxt_http_request_t *r; + + r = ctx; + + length = r->method->length + 1 + r->target.length + 1 + r->version.length; + + start = nxt_mp_nget(r->mem_pool, length); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } + + p = start; + + if (r->method->length != 0) { + p = nxt_cpymem(p, r->method->start, r->method->length); + + if (r->target.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->target.start, r->target.length); + + if (r->version.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->version.start, r->version.length); + } + } + + } else { + *p++ = '-'; + } + + str->start = start; + str->length = p - start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_off_t bytes; + nxt_http_request_t *r; + + r = ctx; + + str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); + + str->length = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O", + bytes) - str->start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + str->start = nxt_mp_nget(r->mem_pool, 3); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + str->length = nxt_sprintf(str->start, str->start + 3, "%03d", r->status) + - str->start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + if (r->referer != NULL) { + str->start = r->referer->value; + str->length = r->referer->value_length; + + } else { + nxt_str_null(str); + } + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + if (r->user_agent != NULL) { + str->start = r->user_agent->value; + str->length = r->user_agent->value_length; + + } else { + nxt_str_null(str); + } + + return NXT_OK; +} + + static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { -- cgit From 26a5af8591ca79eb32ca5d510d8be06527b12fc1 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 18 Jul 2022 12:46:35 +0200 Subject: Removed duplicate handling of './configure --help'. That is already handled in auto/options. It is better suited there, since it's an option, and not a module, and also because it makes use of variables declared there. --- configure | 5 ----- 1 file changed, 5 deletions(-) diff --git a/configure b/configure index bc21e579..ea86e18e 100755 --- a/configure +++ b/configure @@ -48,11 +48,6 @@ NXT_GROUP= nxt_module=${1:-""} case $nxt_module in - --help) - . auto/help - exit 0 - ;; - ""|--*) ;; -- cgit From c8d9106a0d3217c385f6afe572d904d9d77b8c8b Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 19 Jun 2022 14:20:05 +0200 Subject: Removed code used when NXT_HAVE_POSIX_SPAWN is false. 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: --- auto/unix | 15 --------------- src/nxt_process.c | 48 ------------------------------------------------ src/nxt_unix.h | 2 -- 3 files changed, 65 deletions(-) diff --git a/auto/unix b/auto/unix index 7c241650..45c6a139 100644 --- a/auto/unix +++ b/auto/unix @@ -178,21 +178,6 @@ if [ $nxt_found = no ]; then fi -nxt_feature="posix_spawn()" -nxt_feature_name=NXT_HAVE_POSIX_SPAWN -nxt_feature_run= -nxt_feature_incs= -nxt_feature_libs= -nxt_feature_test="#include - #include - - int main(int argc, char *argv[]) { - (void) posix_spawn(NULL, \"\", NULL, NULL, argv, NULL); - return 0; - }" -. auto/feature - - # NetBSD 1.0, OpenBSD 1.0, FreeBSD 2.2 setproctitle(). nxt_feature="setproctitle()" diff --git a/src/nxt_process.c b/src/nxt_process.c index 82e66a99..98636bbe 100644 --- a/src/nxt_process.c +++ b/src/nxt_process.c @@ -798,8 +798,6 @@ nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process) } -#if (NXT_HAVE_POSIX_SPAWN) - /* * Linux glibc 2.2 posix_spawn() is implemented via fork()/execve(). * Linux glibc 2.4 posix_spawn() without file actions and spawn @@ -834,52 +832,6 @@ nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp) return pid; } -#else - -nxt_pid_t -nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp) -{ - nxt_pid_t pid; - - /* - * vfork() is better than fork() because: - * it is faster several times; - * its execution time does not depend on private memory mapping size; - * it has lesser chances to fail due to the ENOMEM error. - */ - - pid = vfork(); - - switch (pid) { - - case -1: - nxt_alert(task, "vfork() failed while executing \"%s\" %E", - name, nxt_errno); - break; - - case 0: - /* A child. */ - nxt_debug(task, "execve(\"%s\")", name); - - (void) execve(name, argv, envp); - - nxt_alert(task, "execve(\"%s\") failed %E", name, nxt_errno); - - exit(1); - nxt_unreachable(); - break; - - default: - /* A parent. */ - nxt_debug(task, "vfork(): %PI", pid); - break; - } - - return pid; -} - -#endif - nxt_int_t nxt_process_daemon(nxt_task_t *task) diff --git a/src/nxt_unix.h b/src/nxt_unix.h index d8eaabc3..6bc6be5e 100644 --- a/src/nxt_unix.h +++ b/src/nxt_unix.h @@ -156,9 +156,7 @@ #include #include #include -#if (NXT_HAVE_POSIX_SPAWN) #include -#endif #include #include /* offsetof() */ #include -- cgit From 0d15cbd5b6136d8a92a23895bd83eb322aa633ea Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 19 Jun 2022 16:55:14 +0200 Subject: Removed unnecessary include. Some OSes, as Linux, provide FIONBIO in . Others, such as the BSDs and Illumos, provide it in , but they all include that header from , so for this test, we can simplify and just include . --- auto/sockets | 7 ------- 1 file changed, 7 deletions(-) diff --git a/auto/sockets b/auto/sockets index e6ef326d..e344a3db 100644 --- a/auto/sockets +++ b/auto/sockets @@ -225,12 +225,6 @@ nxt_feature_test="#include }" . auto/feature -if [ $nxt_found = yes ]; then - NXT_SYS_FILIO_H="#include " -else - NXT_SYS_FILIO_H= -fi - nxt_feature="ioctl(FIONBIO)" nxt_feature_name=NXT_HAVE_FIONBIO @@ -239,7 +233,6 @@ nxt_feature_incs= nxt_feature_libs= nxt_feature_test="#include #include - $NXT_SYS_FILIO_H #include int main() { -- cgit From 5015b05fc495bf3e87f8decfd1617a4a399939d4 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sat, 18 Jun 2022 15:59:12 +0200 Subject: Replaced Linux syscall macros by libc macros. User-space programs should use the SYS_*form, as documented in syscall(2). That also adds compatibility to non-Linux systems. --- auto/isolation | 4 ++-- src/nxt_clone.c | 4 ++-- src/nxt_isolation.c | 2 +- src/nxt_process.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/auto/isolation b/auto/isolation index fd35f8ed..4ade6a38 100644 --- a/auto/isolation +++ b/auto/isolation @@ -21,7 +21,7 @@ nxt_feature_test="#include #include int main() { - return __NR_clone | SIGCHLD; + return SYS_clone | SIGCHLD; }" . auto/feature @@ -68,7 +68,7 @@ nxt_feature_libs= nxt_feature_test="#include int main() { - return __NR_pivot_root; + return SYS_pivot_root; }" . auto/feature diff --git a/src/nxt_clone.c b/src/nxt_clone.c index aa952a54..a9b39ac1 100644 --- a/src/nxt_clone.c +++ b/src/nxt_clone.c @@ -14,9 +14,9 @@ pid_t nxt_clone(nxt_int_t flags) { #if defined(__s390x__) || defined(__s390__) || defined(__CRIS__) - return syscall(__NR_clone, NULL, flags); + return syscall(SYS_clone, NULL, flags); #else - return syscall(__NR_clone, flags, NULL); + return syscall(SYS_clone, flags, NULL); #endif } diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index e3cb1f22..7bb8dbfd 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -1003,7 +1003,7 @@ fail: nxt_inline int nxt_pivot_root(const char *new_root, const char *old_root) { - return syscall(__NR_pivot_root, new_root, old_root); + return syscall(SYS_pivot_root, new_root, old_root); } diff --git a/src/nxt_process.h b/src/nxt_process.h index 694f457e..642c3419 100644 --- a/src/nxt_process.h +++ b/src/nxt_process.h @@ -19,7 +19,7 @@ * fork(2) calls. As we use clone(2) for container, it returns the wrong pid. */ #define nxt_getpid() \ - syscall(__NR_getpid) + syscall(SYS_getpid) #else #define nxt_getpid() \ getpid() -- cgit From 6ba39ccf9b862f56155aa4b391063bf548ce6574 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 23 Jun 2022 13:25:04 +0200 Subject: Fixed incorrect code. The #endif was misplaced by accident during a refactor: . 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)). --- src/nxt_sockaddr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 71e50e3c..e8dee83a 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -208,8 +208,8 @@ nxt_getsockname(nxt_task_t *task, nxt_mp_t *mp, nxt_socket_t s) #if (NXT_HAVE_UNIX_DOMAIN) case AF_UNIX: length = nxt_length("unix:") + socklen; -#endif break; +#endif case AF_INET: length = NXT_INET_ADDR_STR_LEN; -- cgit From 14857442c638d39dc0ece60087991916884cd113 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 1 Jul 2022 14:42:35 +0200 Subject: Added missing inline keyword. --- src/nxt_nncq.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nxt_nncq.h b/src/nxt_nncq.h index 20e7ecff..6c9ab326 100644 --- a/src/nxt_nncq.h +++ b/src/nxt_nncq.h @@ -85,7 +85,7 @@ nxt_nncq_empty(nxt_nncq_t const volatile *q) } -static void +static inline void nxt_nncq_init(nxt_nncq_t volatile *q) { q->head = NXT_NNCQ_SIZE; @@ -94,7 +94,7 @@ nxt_nncq_init(nxt_nncq_t volatile *q) } -static void +static inline void nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val) { nxt_nncq_cycle_t e_cycle, t_cycle; @@ -128,7 +128,7 @@ nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val) } -static nxt_nncq_atomic_t +static inline nxt_nncq_atomic_t nxt_nncq_dequeue(nxt_nncq_t volatile *q) { nxt_nncq_cycle_t e_cycle, h_cycle; -- cgit From 3422e81ab6794b6f2a4a1fb237923bab11ae2b18 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 1 Jul 2022 14:42:35 +0200 Subject: Added missing inline keyword. --- src/nxt_nvbcq.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nxt_nvbcq.h b/src/nxt_nvbcq.h index 2b019dcc..e164615b 100644 --- a/src/nxt_nvbcq.h +++ b/src/nxt_nvbcq.h @@ -64,7 +64,7 @@ nxt_nvbcq_empty(nxt_nvbcq_t const volatile *q) } -static void +static inline void nxt_nvbcq_init(nxt_nvbcq_t volatile *q) { nxt_nvbcq_atomic_t i; @@ -79,7 +79,7 @@ nxt_nvbcq_init(nxt_nvbcq_t volatile *q) } -static void +static inline void nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val) { nxt_nvbcq_atomic_t t, h, i; @@ -110,7 +110,7 @@ nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val) } -static nxt_nvbcq_atomic_t +static inline nxt_nvbcq_atomic_t nxt_nvbcq_dequeue(nxt_nvbcq_t volatile *q) { nxt_nvbcq_atomic_t h, t, i, e; -- cgit From a1cda6455f5ab0b361d403bd7c183ebec92fb59a Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 19 Jul 2022 17:34:32 +0100 Subject: Tests: added tests for more HTTP variables. --- test/test_variables.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/test_variables.py b/test/test_variables.py index 577408f6..ccd0839b 100644 --- a/test/test_variables.py +++ b/test/test_variables.py @@ -19,6 +19,10 @@ class TestVariables(TestApplicationProto): "localhost": [{"action": {"return": 208}}], "9?q#a": [{"action": {"return": 209}}], "blah": [{"action": {"return": 210}}], + "127.0.0.1": [{"action": {"return": 211}}], + "::1": [{"action": {"return": 212}}], + "referer-value": [{"action": {"return": 213}}], + "MSIE": [{"action": {"return": 214}}], }, }, ), 'configure routes' @@ -63,6 +67,53 @@ class TestVariables(TestApplicationProto): check_host('www.localhost', 404) check_host('localhost1', 404) + def test_variables_remote_addr(self): + self.conf_routes("\"routes/$remote_addr\"") + assert self.get()['status'] == 211 + + assert 'success' in self.conf( + {"[::1]:7080": {"pass": "routes/$remote_addr"}}, 'listeners' + ) + assert self.get(sock_type='ipv6')['status'] == 212 + + def test_variables_header_referer(self): + self.conf_routes("\"routes/$header_referer\"") + + def check_referer(referer, status=213): + assert ( + self.get( + headers={ + 'Host': 'localhost', + 'Connection': 'close', + 'Referer': referer, + } + )['status'] + == status + ) + + check_referer('referer-value') + check_referer('', 404) + check_referer('no', 404) + + def test_variables_header_user_agent(self): + self.conf_routes("\"routes/$header_user_agent\"") + + def check_user_agent(user_agent, status=214): + assert ( + self.get( + headers={ + 'Host': 'localhost', + 'Connection': 'close', + 'User-Agent': user_agent, + } + )['status'] + == status + ) + + check_user_agent('MSIE') + check_user_agent('', 404) + check_user_agent('no', 404) + def test_variables_many(self): self.conf_routes("\"routes$uri$method\"") assert self.get(url='/5')['status'] == 206, 'many' -- cgit From eebaff42eaef94f67f2232fc551f6d43c90c2e5c Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Fri, 6 May 2022 19:41:02 +0100 Subject: Var: added a $dollar variable that translates to a '$'. 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 --- docs/changes.xml | 7 +++++++ src/nxt_http_variables.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/docs/changes.xml b/docs/changes.xml index f8745641..66965311 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -62,6 +62,13 @@ increased the applications' startup timeout. + + +added a new variable, $dollar, that translates to a literal "$" during +variable substitution. + + + diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index 837ef7b0..5a632b24 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -7,6 +7,8 @@ #include +static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field); static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, @@ -41,6 +43,9 @@ static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, static nxt_var_decl_t nxt_http_vars[] = { { + .name = nxt_string("dollar"), + .handler = nxt_http_var_dollar, + }, { .name = nxt_string("method"), .handler = nxt_http_var_method, }, { @@ -96,6 +101,15 @@ nxt_http_register_variables(void) } +static nxt_int_t +nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_str_set(str, "$"); + + return NXT_OK; +} + + static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { -- cgit From 02659b1ee3b041d1f4046ac440ea6755455230a1 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 20 Jul 2022 19:05:29 +0100 Subject: Tests: added tests for translating $dollar into a literal $. If you need to specify a $ in a URI you can now use '$dollar' or '${dollar}'. Added some tests for the above to test_variables.py setting a Location string. --- test/test_variables.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/test_variables.py b/test/test_variables.py index ccd0839b..2ddfdc0a 100644 --- a/test/test_variables.py +++ b/test/test_variables.py @@ -114,6 +114,27 @@ class TestVariables(TestApplicationProto): check_user_agent('', 404) check_user_agent('no', 404) + def test_variables_dollar(self): + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes"}}, + "routes": [{"action": {"return": 301}}], + } + ) + + def check_dollar(location, expect): + assert 'success' in self.conf( + '"' + location + '"', + 'routes/0/action/location', + ) + assert self.get()['headers']['Location'] == expect + + check_dollar( + 'https://${host}${uri}path${dollar}dollar', + 'https://localhost/path$dollar', + ) + check_dollar('path$dollar${dollar}', 'path$$') + def test_variables_many(self): self.conf_routes("\"routes$uri$method\"") assert self.get(url='/5')['status'] == 206, 'many' -- cgit From c1cea3c97d5dfc260a54cab67b7dc1637a3deb59 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 15 Jun 2022 16:20:01 +0100 Subject: Router: avoided undefined behaviour. 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. --- src/nxt_http_route_addr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c index 2907a902..985fb737 100644 --- a/src/nxt_http_route_addr.c +++ b/src/nxt_http_route_addr.c @@ -233,7 +233,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, } addr.length = delim - addr.start; - inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFF << (32 - cidr_prefix))); + inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFFULL << (32 - cidr_prefix))); inet->start = nxt_inet_addr(addr.start, addr.length) & inet->end; if (nxt_slow_path(inet->start == INADDR_NONE)) { -- cgit From 6e36584a2e9bad0e7c4f96d68c527992deadc650 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 28 Feb 2022 12:12:30 +0100 Subject: Supporting UNIX sockets in address matching. This closes #645 issue on GitHub. (Also moved a changelog line that was misplaced in a previous commit.) --- docs/changes.xml | 19 ++++++++++++------- src/nxt_conf_validation.c | 5 +++++ src/nxt_http_route.c | 7 +++++++ src/nxt_http_route_addr.c | 10 ++++++++++ src/nxt_http_route_addr.h | 1 + 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 66965311..8c4b5cf0 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -31,6 +31,12 @@ NGINX Unit updated to 1.28.0. date="" time="" packager="Nginx Packaging <nginx-packaging@f5.com>"> + + +supporting UNIX sockets in address matching. + + + forwarded header to replace client address and protocol. @@ -49,6 +55,12 @@ more http variables support. + + +added a new variable, $dollar, that translates to a literal "$" during + + + an index file that didn't contain a file extension was incorrectly @@ -62,13 +74,6 @@ increased the applications' startup timeout. - - -added a new variable, $dollar, that translates to a literal "$" during -variable substitution. - - - diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 47164e92..8c532914 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -2157,6 +2157,11 @@ nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, return nxt_conf_vldt_error(vldt, "The \"address\" does not support " "IPv6 with your configuration."); + case NXT_ADDR_PATTERN_NO_UNIX_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" does not support " + "UNIX domain sockets with your " + "configuration."); + default: return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown " "format."); diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index e00c37fe..cdc9077f 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -1818,6 +1818,13 @@ nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, break; #endif +#if (NXT_HAVE_UNIX_DOMAIN) + case AF_UNIX: + + match = (base->addr_family == AF_UNIX); + break; +#endif + default: match = 0; break; diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c index 985fb737..34455af4 100644 --- a/src/nxt_http_route_addr.c +++ b/src/nxt_http_route_addr.c @@ -41,6 +41,16 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, base->negative = 0; } + if (nxt_str_eq(&addr, "unix", 4)) { +#if (NXT_HAVE_UNIX_DOMAIN) + base->addr_family = AF_UNIX; + + return NXT_OK; +#else + return NXT_ADDR_PATTERN_NO_UNIX_ERROR; +#endif + } + if (nxt_slow_path(addr.length < 2)) { return NXT_ADDR_PATTERN_LENGTH_ERROR; } diff --git a/src/nxt_http_route_addr.h b/src/nxt_http_route_addr.h index 3b1e1da3..2deda6f8 100644 --- a/src/nxt_http_route_addr.h +++ b/src/nxt_http_route_addr.h @@ -26,6 +26,7 @@ enum { NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR, NXT_ADDR_PATTERN_CIDR_ERROR, NXT_ADDR_PATTERN_NO_IPv6_ERROR, + NXT_ADDR_PATTERN_NO_UNIX_ERROR, }; -- cgit From 91ffd08d119b50d7491827aa6da83006c86076d9 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 26 Jul 2022 16:58:15 +0200 Subject: Fixed line removed by accident. When fixing conflicts in the changelog, a line was removed by accident. Signed-off-by: Alejandro Colomar --- docs/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changes.xml b/docs/changes.xml index 8c4b5cf0..ae8478cd 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -58,6 +58,7 @@ more http variables support. added a new variable, $dollar, that translates to a literal "$" during +variable substitution. -- cgit From 9b4b4925b38333b8d7795331d27db9811f43d72a Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 9 Jun 2022 14:39:59 +0200 Subject: Ruby: fixed contents of SCRIPT_NAME. Having the basename of the script pathname was incorrect. While we don't have something more accurate, the best thing to do is to have it empty (which should be the right thing most of the time). This closes #715 issue on GitHub. The bug was introduced in git commit 0032543fa65f454c471c968998190b027c1ff270 'Ruby: added the Rack environment parameter "SCRIPT_NAME".'. --- docs/changes.xml | 6 ++++++ src/ruby/nxt_ruby.c | 46 +++++-------------------------------------- src/ruby/nxt_ruby.h | 1 - test/test_ruby_application.py | 2 +- 4 files changed, 12 insertions(+), 43 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index ae8478cd..158f98e9 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -75,6 +75,12 @@ increased the applications' startup timeout. + + +force SCRIPT_NAME in Ruby to always be an empty string. + + + diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 8f4afd35..4df77499 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -29,7 +29,6 @@ typedef struct { static nxt_int_t nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data); static VALUE nxt_ruby_init_basic(VALUE arg); -static VALUE nxt_ruby_script_basename(nxt_str_t *script); static VALUE nxt_ruby_hook_procs_load(VALUE path); static VALUE nxt_ruby_hook_register(VALUE arg); @@ -50,7 +49,7 @@ static void *nxt_ruby_thread_create_gvl(void *rctx); static VALUE nxt_ruby_thread_func(VALUE arg); static void *nxt_ruby_unit_run(void *ctx); static void nxt_ruby_ubf(void *ctx); -static int nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c); +static int nxt_ruby_init_threads(nxt_ruby_app_conf_t *c); static void nxt_ruby_join_threads(nxt_unit_ctx_t *ctx, nxt_ruby_app_conf_t *c); @@ -261,7 +260,7 @@ static nxt_int_t nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) { int state, rc; - VALUE res, path, script; + VALUE res, path; nxt_ruby_ctx_t ruby_ctx; nxt_unit_ctx_t *unit_ctx; nxt_unit_init_t ruby_unit_init; @@ -283,10 +282,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) ruby_options(2, argv); ruby_script("NGINX_Unit"); - script = nxt_ruby_script_basename(&c->script); - ruby_ctx.env = Qnil; - ruby_ctx.script = script; ruby_ctx.io_input = Qnil; ruby_ctx.io_error = Qnil; ruby_ctx.thread = Qnil; @@ -356,7 +352,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) goto fail; } - rc = nxt_ruby_init_threads(script, c); + rc = nxt_ruby_init_threads(c); if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { goto fail; } @@ -424,37 +420,6 @@ fail: } -static VALUE -nxt_ruby_script_basename(nxt_str_t *script) -{ - size_t len; - u_char *p, *last; - - last = NULL; - p = script->start + script->length; - - while (p > script->start) { - - if (p[-1] == '/') { - last = p; - break; - } - - p--; - } - - if (last != NULL) { - len = script->length - (last - script->start); - - } else { - last = script->start; - len = script->length; - } - - return rb_str_new((const char *) last, len); -} - - static VALUE nxt_ruby_init_basic(VALUE arg) { @@ -598,7 +563,7 @@ nxt_ruby_rack_env_create(VALUE arg) rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MAJOR)); rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MINOR)); - rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rctx->script); + rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rb_str_new("", 0)); rb_hash_aset(hash_env, rb_str_new2("rack.version"), version); rb_hash_aset(hash_env, rb_str_new2("rack.input"), rctx->io_input); rb_hash_aset(hash_env, rb_str_new2("rack.errors"), rctx->io_error); @@ -1393,7 +1358,7 @@ nxt_ruby_ubf(void *ctx) static int -nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c) +nxt_ruby_init_threads(nxt_ruby_app_conf_t *c) { int state; uint32_t i; @@ -1415,7 +1380,6 @@ nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c) rctx = &nxt_ruby_ctxs[i]; rctx->env = Qnil; - rctx->script = script; rctx->io_input = Qnil; rctx->io_error = Qnil; rctx->thread = Qnil; diff --git a/src/ruby/nxt_ruby.h b/src/ruby/nxt_ruby.h index 3bdd567a..26430021 100644 --- a/src/ruby/nxt_ruby.h +++ b/src/ruby/nxt_ruby.h @@ -22,7 +22,6 @@ typedef struct { VALUE env; - VALUE script; VALUE io_input; VALUE io_error; VALUE thread; diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index 95c75d47..b3e02406 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -44,7 +44,7 @@ class TestRubyApplication(TestApplicationRuby): 'Request-Method': 'POST', 'Request-Uri': '/', 'Http-Host': 'localhost', - 'Script-Name': 'config.ru', + 'Script-Name': '', 'Server-Protocol': 'HTTP/1.1', 'Custom-Header': 'blah', 'Rack-Version': '13', -- cgit From 2bd4a455278dbce756c1dc8be07515f73d611e3b Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 28 Jul 2022 11:00:15 +0800 Subject: Ruby: fixed segfault on SIGTERM signal. This closes #562 issue on GitHub. --- docs/changes.xml | 6 ++++++ src/ruby/nxt_ruby.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 158f98e9..3ff434aa 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -81,6 +81,12 @@ force SCRIPT_NAME in Ruby to always be an empty string. + + +the ruby application process could crash if it's interrupted by SIGTERM signal. + + + diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 4df77499..07d02dce 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -377,8 +377,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) } } - rc = (intptr_t) rb_thread_call_without_gvl(nxt_ruby_unit_run, unit_ctx, - nxt_ruby_ubf, unit_ctx); + rc = (intptr_t) rb_thread_call_without_gvl2(nxt_ruby_unit_run, unit_ctx, + nxt_ruby_ubf, unit_ctx); if (nxt_ruby_hook_procs != Qnil) { rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_shutdown, &state); -- cgit From 8761501b4845656a0f2e5c0e7bf98f948c45fb5f Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 14 Jul 2022 11:14:20 +0800 Subject: Log: split access log from nxt_router.c. No functional changes. --- auto/sources | 1 + src/nxt_router.c | 443 +------------------------------------------ src/nxt_router.h | 16 ++ src/nxt_router_access_log.c | 446 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 471 insertions(+), 435 deletions(-) create mode 100644 src/nxt_router_access_log.c diff --git a/auto/sources b/auto/sources index 27a45edc..65a83f45 100644 --- a/auto/sources +++ b/auto/sources @@ -84,6 +84,7 @@ NXT_LIB_SRCS=" \ src/nxt_signal_handlers.c \ src/nxt_controller.c \ src/nxt_router.c \ + src/nxt_router_access_log.c \ src/nxt_h1proto.c \ src/nxt_http_request.c \ src/nxt_http_response.c \ diff --git a/src/nxt_router.c b/src/nxt_router.c index e84b3d9a..e1f4f6da 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -92,15 +92,10 @@ static void nxt_router_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); static void nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); -static void nxt_router_access_log_reopen_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); -static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); static void nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf); -static void nxt_router_conf_error(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf); static void nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); @@ -201,27 +196,6 @@ static void nxt_router_req_headers_ack_handler(nxt_task_t *task, static void nxt_router_listen_socket_release(nxt_task_t *task, nxt_socket_conf_t *skcf); -static void nxt_router_access_log_writer(nxt_task_t *task, - nxt_http_request_t *r, nxt_router_access_log_t *access_log); -static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); -static void nxt_router_access_log_open(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf); -static void nxt_router_access_log_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); -static void nxt_router_access_log_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); -static void nxt_router_access_log_use(nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log); -static void nxt_router_access_log_release(nxt_task_t *task, - nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); -static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, - void *data); -static void nxt_router_access_log_reopen_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); -static void nxt_router_access_log_reopen_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); - static void nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); static void nxt_router_app_port_error(nxt_task_t *task, @@ -271,7 +245,7 @@ static void nxt_router_get_mmap_handler(nxt_task_t *task, extern const nxt_http_request_state_t nxt_http_websocket; -static nxt_router_t *nxt_router; +nxt_router_t *nxt_router; static const nxt_str_t http_prefix = nxt_string("HTTP_"); static const nxt_str_t empty_prefix = nxt_string(""); @@ -1075,7 +1049,7 @@ nxt_router_app_need_start(nxt_app_t *app) } -static void +void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) { nxt_int_t ret; @@ -1231,7 +1205,7 @@ nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) } -static void +void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) { nxt_app_t *app; @@ -1483,7 +1457,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_mp_t *mp, *app_mp; uint32_t next, next_target; nxt_int_t ret; - nxt_str_t name, path, target; + nxt_str_t name, target; nxt_app_t *app, *prev; nxt_str_t *t, *s, *targets; nxt_uint_t n, i; @@ -1503,7 +1477,6 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_event_engine_t *engine; nxt_app_lang_module_t *lang; nxt_router_app_conf_t apcf; - nxt_router_access_log_t *access_log; nxt_router_listener_conf_t lscf; static nxt_str_t http_path = nxt_string("/settings/http"); @@ -1793,6 +1766,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (nxt_slow_path(routes == NULL)) { return NXT_ERROR; } + rtcf->routes = routes; } @@ -1980,33 +1954,10 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, value = nxt_conf_get_path(root, &access_log_path); if (value != NULL) { - nxt_conf_get_string(value, &path); - - access_log = router->access_log; - - if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { - nxt_router_access_log_use(&router->lock, access_log); - - } else { - access_log = nxt_malloc(sizeof(nxt_router_access_log_t) - + path.length); - if (access_log == NULL) { - nxt_alert(task, "failed to allocate access log structure"); - goto fail; - } - - access_log->fd = -1; - access_log->handler = &nxt_router_access_log_writer; - access_log->count = 1; - - access_log->path.length = path.length; - access_log->path.start = (u_char *) access_log - + sizeof(nxt_router_access_log_t); - - nxt_memcpy(access_log->path.start, path.start, path.length); + ret = nxt_router_access_log_create(task, rtcf, value); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; } - - rtcf->access_log = access_log; } nxt_queue_add(&deleting_sockets, &router->sockets); @@ -3759,384 +3710,6 @@ nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) } -static void -nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_t *access_log) -{ - size_t size; - u_char *buf, *p; - nxt_off_t bytes; - - static nxt_time_string_t date_cache = { - (nxt_atomic_uint_t) -1, - nxt_router_access_log_date, - "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", - nxt_length("31/Dec/1986:19:40:00 +0300"), - NXT_THREAD_TIME_LOCAL, - NXT_THREAD_TIME_SEC, - }; - - size = r->remote->address_length - + 6 /* ' - - [' */ - + date_cache.size - + 3 /* '] "' */ - + r->method->length - + 1 /* space */ - + r->target.length - + 1 /* space */ - + r->version.length - + 2 /* '" ' */ - + 3 /* status */ - + 1 /* space */ - + NXT_OFF_T_LEN - + 2 /* ' "' */ - + (r->referer != NULL ? r->referer->value_length : 1) - + 3 /* '" "' */ - + (r->user_agent != NULL ? r->user_agent->value_length : 1) - + 2 /* '"\n' */ - ; - - buf = nxt_mp_nget(r->mem_pool, size); - if (nxt_slow_path(buf == NULL)) { - return; - } - - p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), - r->remote->address_length); - - p = nxt_cpymem(p, " - - [", 6); - - p = nxt_thread_time_string(task->thread, &date_cache, p); - - p = nxt_cpymem(p, "] \"", 3); - - if (r->method->length != 0) { - p = nxt_cpymem(p, r->method->start, r->method->length); - - if (r->target.length != 0) { - *p++ = ' '; - p = nxt_cpymem(p, r->target.start, r->target.length); - - if (r->version.length != 0) { - *p++ = ' '; - p = nxt_cpymem(p, r->version.start, r->version.length); - } - } - - } else { - *p++ = '-'; - } - - p = nxt_cpymem(p, "\" ", 2); - - p = nxt_sprintf(p, p + 3, "%03d", r->status); - - *p++ = ' '; - - bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); - - p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); - - p = nxt_cpymem(p, " \"", 2); - - if (r->referer != NULL) { - p = nxt_cpymem(p, r->referer->value, r->referer->value_length); - - } else { - *p++ = '-'; - } - - p = nxt_cpymem(p, "\" \"", 3); - - if (r->user_agent != NULL) { - p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); - - } else { - *p++ = '-'; - } - - p = nxt_cpymem(p, "\"\n", 2); - - nxt_fd_write(access_log->fd, buf, p - buf); -} - - -static u_char * -nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, - size_t size, const char *format) -{ - u_char sign; - time_t gmtoff; - - static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - gmtoff = nxt_timezone(tm) / 60; - - if (gmtoff < 0) { - gmtoff = -gmtoff; - sign = '-'; - - } else { - sign = '+'; - } - - return nxt_sprintf(buf, buf + size, format, - tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, - tm->tm_hour, tm->tm_min, tm->tm_sec, - sign, gmtoff / 60, gmtoff % 60); -} - - -static void -nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) -{ - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *router_port; - nxt_runtime_t *rt; - nxt_router_access_log_t *access_log; - - access_log = tmcf->router_conf->access_log; - - b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } - - b->completion_handler = nxt_buf_dummy_completion; - - nxt_buf_cpystr(b, &access_log->path); - *b->mem.free++ = '\0'; - - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - - stream = nxt_port_rpc_register_handler(task, router_port, - nxt_router_access_log_ready, - nxt_router_access_log_error, - -1, tmcf); - if (nxt_slow_path(stream == 0)) { - goto fail; - } - - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, - stream, router_port->id, b); - - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, router_port, stream); - goto fail; - } - - return; - -fail: - - nxt_router_conf_error(task, tmcf); -} - - -static void -nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_temp_conf_t *tmcf; - nxt_router_access_log_t *access_log; - - tmcf = data; - - access_log = tmcf->router_conf->access_log; - - access_log->fd = msg->fd[0]; - - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_router_conf_apply, task, tmcf, NULL); -} - - -static void -nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_temp_conf_t *tmcf; - - tmcf = data; - - nxt_router_conf_error(task, tmcf); -} - - -static void -nxt_router_access_log_use(nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log) -{ - if (access_log == NULL) { - return; - } - - nxt_thread_spin_lock(lock); - - access_log->count++; - - nxt_thread_spin_unlock(lock); -} - - -static void -nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log) -{ - if (access_log == NULL) { - return; - } - - nxt_thread_spin_lock(lock); - - if (--access_log->count != 0) { - access_log = NULL; - } - - nxt_thread_spin_unlock(lock); - - if (access_log != NULL) { - - if (access_log->fd != -1) { - nxt_fd_close(access_log->fd); - } - - nxt_free(access_log); - } -} - - -typedef struct { - nxt_mp_t *mem_pool; - nxt_router_access_log_t *access_log; -} nxt_router_access_log_reopen_t; - - -static void -nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_mp_t *mp; - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *router_port; - nxt_runtime_t *rt; - nxt_router_access_log_t *access_log; - nxt_router_access_log_reopen_t *reopen; - - access_log = nxt_router->access_log; - - if (access_log == NULL) { - return; - } - - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return; - } - - reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); - if (nxt_slow_path(reopen == NULL)) { - goto fail; - } - - reopen->mem_pool = mp; - reopen->access_log = access_log; - - b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } - - b->completion_handler = nxt_router_access_log_reopen_completion; - - nxt_buf_cpystr(b, &access_log->path); - *b->mem.free++ = '\0'; - - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - - stream = nxt_port_rpc_register_handler(task, router_port, - nxt_router_access_log_reopen_ready, - nxt_router_access_log_reopen_error, - -1, reopen); - if (nxt_slow_path(stream == 0)) { - goto fail; - } - - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, - stream, router_port->id, b); - - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, router_port, stream); - goto fail; - } - - nxt_mp_retain(mp); - - return; - -fail: - - nxt_mp_destroy(mp); -} - - -static void -nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b; - - b = obj; - mp = b->data; - - nxt_mp_release(mp); -} - - -static void -nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_access_log_t *access_log; - nxt_router_access_log_reopen_t *reopen; - - reopen = data; - - access_log = reopen->access_log; - - if (access_log == nxt_router->access_log) { - - if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { - nxt_alert(task, "dup2(%FD, %FD) failed %E", - msg->fd[0], access_log->fd, nxt_errno); - } - } - - nxt_fd_close(msg->fd[0]); - nxt_mp_release(reopen->mem_pool); -} - - -static void -nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_access_log_reopen_t *reopen; - - reopen = data; - - nxt_mp_release(reopen->mem_pool); -} - - static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) { diff --git a/src/nxt_router.h b/src/nxt_router.h index 8c21a70a..18fb60b0 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -237,7 +237,23 @@ nxt_int_t nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name, nxt_str_t *target, nxt_http_action_t *action); void nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev, nxt_socket_conf_joint_t *joint); + +void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); +void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf); void nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint); +nxt_int_t nxt_router_access_log_create(nxt_task_t *task, + nxt_router_conf_t *rtcf, nxt_conf_value_t *value); +void nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf); +void nxt_router_access_log_use(nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log); +void nxt_router_access_log_release(nxt_task_t *task, + nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); +void nxt_router_access_log_reopen_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg); + + +extern nxt_router_t *nxt_router; + #endif /* _NXT_ROUTER_H_INCLUDED_ */ diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c new file mode 100644 index 00000000..d92e80c3 --- /dev/null +++ b/src/nxt_router_access_log.c @@ -0,0 +1,446 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Valentin V. Bartenev + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include + + +static void nxt_router_access_log_writer(nxt_task_t *task, + nxt_http_request_t *r, nxt_router_access_log_t *access_log); +static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, const char *format); +static void nxt_router_access_log_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, + void *data); +static void nxt_router_access_log_reopen_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_reopen_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); + + +nxt_int_t +nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, + nxt_conf_value_t *value) +{ + nxt_str_t path; + nxt_router_t *router; + nxt_router_access_log_t *access_log; + + router = nxt_router; + + nxt_conf_get_string(value, &path); + + access_log = router->access_log; + + if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { + nxt_router_access_log_use(&router->lock, access_log); + + } else { + access_log = nxt_malloc(sizeof(nxt_router_access_log_t) + + path.length); + if (access_log == NULL) { + nxt_alert(task, "failed to allocate access log structure"); + return NXT_ERROR; + } + + access_log->fd = -1; + access_log->handler = &nxt_router_access_log_writer; + access_log->count = 1; + + access_log->path.length = path.length; + access_log->path.start = (u_char *) access_log + + sizeof(nxt_router_access_log_t); + + nxt_memcpy(access_log->path.start, path.start, path.length); + } + + rtcf->access_log = access_log; + + return NXT_OK; +} + + +static void +nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, + nxt_router_access_log_t *access_log) +{ + size_t size; + u_char *buf, *p; + nxt_off_t bytes; + + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t) -1, + nxt_router_access_log_date, + "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", + nxt_length("31/Dec/1986:19:40:00 +0300"), + NXT_THREAD_TIME_LOCAL, + NXT_THREAD_TIME_SEC, + }; + + size = r->remote->address_length + + 6 /* ' - - [' */ + + date_cache.size + + 3 /* '] "' */ + + r->method->length + + 1 /* space */ + + r->target.length + + 1 /* space */ + + r->version.length + + 2 /* '" ' */ + + 3 /* status */ + + 1 /* space */ + + NXT_OFF_T_LEN + + 2 /* ' "' */ + + (r->referer != NULL ? r->referer->value_length : 1) + + 3 /* '" "' */ + + (r->user_agent != NULL ? r->user_agent->value_length : 1) + + 2 /* '"\n' */ + ; + + buf = nxt_mp_nget(r->mem_pool, size); + if (nxt_slow_path(buf == NULL)) { + return; + } + + p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), + r->remote->address_length); + + p = nxt_cpymem(p, " - - [", 6); + + p = nxt_thread_time_string(task->thread, &date_cache, p); + + p = nxt_cpymem(p, "] \"", 3); + + if (r->method->length != 0) { + p = nxt_cpymem(p, r->method->start, r->method->length); + + if (r->target.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->target.start, r->target.length); + + if (r->version.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->version.start, r->version.length); + } + } + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\" ", 2); + + p = nxt_sprintf(p, p + 3, "%03d", r->status); + + *p++ = ' '; + + bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); + + p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); + + p = nxt_cpymem(p, " \"", 2); + + if (r->referer != NULL) { + p = nxt_cpymem(p, r->referer->value, r->referer->value_length); + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\" \"", 3); + + if (r->user_agent != NULL) { + p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\"\n", 2); + + nxt_fd_write(access_log->fd, buf, p - buf); +} + + +static u_char * +nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, + size_t size, const char *format) +{ + u_char sign; + time_t gmtoff; + + static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + gmtoff = nxt_timezone(tm) / 60; + + if (gmtoff < 0) { + gmtoff = -gmtoff; + sign = '-'; + + } else { + sign = '+'; + } + + return nxt_sprintf(buf, buf + size, format, + tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, gmtoff / 60, gmtoff % 60); +} + + +void +nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) +{ + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; + + access_log = tmcf->router_conf->access_log; + + b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } + + b->completion_handler = nxt_buf_dummy_completion; + + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; + + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + stream = nxt_port_rpc_register_handler(task, router_port, + nxt_router_access_log_ready, + nxt_router_access_log_error, + -1, tmcf); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); + + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } + + return; + +fail: + + nxt_router_conf_error(task, tmcf); +} + + +static void +nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_temp_conf_t *tmcf; + nxt_router_access_log_t *access_log; + + tmcf = data; + + access_log = tmcf->router_conf->access_log; + + access_log->fd = msg->fd[0]; + + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_router_conf_apply, task, tmcf, NULL); +} + + +static void +nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_temp_conf_t *tmcf; + + tmcf = data; + + nxt_router_conf_error(task, tmcf); +} + + +void +nxt_router_access_log_use(nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) +{ + if (access_log == NULL) { + return; + } + + nxt_thread_spin_lock(lock); + + access_log->count++; + + nxt_thread_spin_unlock(lock); +} + + +void +nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) +{ + if (access_log == NULL) { + return; + } + + nxt_thread_spin_lock(lock); + + if (--access_log->count != 0) { + access_log = NULL; + } + + nxt_thread_spin_unlock(lock); + + if (access_log != NULL) { + + if (access_log->fd != -1) { + nxt_fd_close(access_log->fd); + } + + nxt_free(access_log); + } +} + + +typedef struct { + nxt_mp_t *mem_pool; + nxt_router_access_log_t *access_log; +} nxt_router_access_log_reopen_t; + + +void +nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) +{ + nxt_mp_t *mp; + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; + nxt_router_access_log_reopen_t *reopen; + + access_log = nxt_router->access_log; + + if (access_log == NULL) { + return; + } + + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return; + } + + reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); + if (nxt_slow_path(reopen == NULL)) { + goto fail; + } + + reopen->mem_pool = mp; + reopen->access_log = access_log; + + b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } + + b->completion_handler = nxt_router_access_log_reopen_completion; + + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; + + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + stream = nxt_port_rpc_register_handler(task, router_port, + nxt_router_access_log_reopen_ready, + nxt_router_access_log_reopen_error, + -1, reopen); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); + + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } + + nxt_mp_retain(mp); + + return; + +fail: + + nxt_mp_destroy(mp); +} + + +static void +nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data) +{ + nxt_mp_t *mp; + nxt_buf_t *b; + + b = obj; + mp = b->data; + + nxt_mp_release(mp); +} + + +static void +nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_access_log_t *access_log; + nxt_router_access_log_reopen_t *reopen; + + reopen = data; + + access_log = reopen->access_log; + + if (access_log == nxt_router->access_log) { + + if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { + nxt_alert(task, "dup2(%FD, %FD) failed %E", + msg->fd[0], access_log->fd, nxt_errno); + } + } + + nxt_fd_close(msg->fd[0]); + nxt_mp_release(reopen->mem_pool); +} + + +static void +nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_access_log_reopen_t *reopen; + + reopen = data; + + nxt_mp_release(reopen->mem_pool); +} -- cgit From 3f8cf62c03a55b9767f0c75b3df6a1a40252b19a Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 28 Jul 2022 11:05:04 +0800 Subject: Log: customizable access log format. --- docs/changes.xml | 6 ++ src/nxt_conf_validation.c | 81 +++++++++++++++- src/nxt_http_request.c | 9 +- src/nxt_http_static.c | 5 +- src/nxt_router.h | 4 +- src/nxt_router_access_log.c | 230 ++++++++++++++++++++++---------------------- src/nxt_var.c | 25 ++++- src/nxt_var.h | 8 +- 8 files changed, 238 insertions(+), 130 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 3ff434aa..68498278 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -62,6 +62,12 @@ variable substitution. + + +customizable access log format. + + + an index file that didn't contain a file extension was incorrectly diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 8c532914..3e89d775 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -202,6 +202,8 @@ static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); +static nxt_int_t nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); @@ -241,6 +243,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[]; #if (NXT_HAVE_ISOLATION_ROOTFS) static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[]; #endif +static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { @@ -270,7 +273,8 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { .u.object = nxt_conf_vldt_upstream, }, { .name = nxt_string("access_log"), - .type = NXT_CONF_VLDT_STRING, + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_access_log, }, NXT_CONF_VLDT_END @@ -1205,6 +1209,19 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = { }; +static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[] = { + { + .name = nxt_string("path"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("format"), + .type = NXT_CONF_VLDT_STRING, + }, + + NXT_CONF_VLDT_END +}; + + nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt) { @@ -3090,3 +3107,65 @@ nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, return NXT_OK; } + + +typedef struct { + nxt_str_t path; + nxt_str_t format; +} nxt_conf_vldt_access_log_conf_t; + + +static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = { + { + nxt_string("path"), + NXT_CONF_MAP_STR, + offsetof(nxt_conf_vldt_access_log_conf_t, path), + }, + + { + nxt_string("format"), + NXT_CONF_MAP_STR, + offsetof(nxt_conf_vldt_access_log_conf_t, format), + }, +}; + + +static nxt_int_t +nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, + void *data) +{ + nxt_int_t ret; + nxt_conf_vldt_access_log_conf_t conf; + + static nxt_str_t format_str = nxt_string("format"); + + if (nxt_conf_type(value) == NXT_CONF_STRING) { + return NXT_OK; + } + + ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_access_log_members); + if (ret != NXT_OK) { + return ret; + } + + nxt_memzero(&conf, sizeof(nxt_conf_vldt_access_log_conf_t)); + + ret = nxt_conf_map_object(vldt->pool, value, + nxt_conf_vldt_access_log_map, + nxt_nitems(nxt_conf_vldt_access_log_map), + &conf); + if (ret != NXT_OK) { + return ret; + } + + if (conf.path.length == 0) { + return nxt_conf_vldt_error(vldt, + "The \"path\" string must not be empty."); + } + + if (nxt_is_var(&conf.format)) { + return nxt_conf_vldt_var(vldt, &format_str, &conf.format); + } + + return NXT_OK; +} diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 5f8fd8f7..a16340de 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -791,6 +791,7 @@ nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data) void nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) { + nxt_var_t *log_format; nxt_http_proto_t proto; nxt_http_request_t *r; nxt_http_protocol_t protocol; @@ -800,20 +801,22 @@ nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) r = obj; proto.any = data; - nxt_debug(task, "http request close handler"); - conf = r->conf; if (!r->logged) { r->logged = 1; access_log = conf->socket_conf->router_conf->access_log; + log_format = conf->socket_conf->router_conf->log_format; if (access_log != NULL) { - access_log->handler(task, r, access_log); + access_log->handler(task, r, access_log, log_format); + return; } } + nxt_debug(task, "http request close handler"); + r->proto.any = NULL; if (r->body != NULL && nxt_buf_is_file(r->body) diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 19393f2c..0507e038 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -104,7 +104,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, cv = nxt_conf_get_array_element_or_itself(acf->share, i); nxt_conf_get_string(cv, &str); - var = nxt_var_compile(&str, mp, rtcf->var_fields, 1); + var = nxt_var_compile(&str, mp, rtcf->var_fields, NXT_VAR_STRZ); if (nxt_slow_path(var == NULL)) { return NXT_ERROR; } @@ -130,7 +130,8 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_str_t chr, shr; nxt_bool_t is_const; - conf->chroot = nxt_var_compile(&acf->chroot, mp, rtcf->var_fields, 1); + conf->chroot = nxt_var_compile(&acf->chroot, mp, rtcf->var_fields, + NXT_VAR_STRZ); if (nxt_slow_path(conf->chroot == NULL)) { return NXT_ERROR; } diff --git a/src/nxt_router.h b/src/nxt_router.h index 18fb60b0..a6add219 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -53,6 +53,7 @@ typedef struct { nxt_lvlhsh_t apps_hash; nxt_router_access_log_t *access_log; + nxt_var_t *log_format; } nxt_router_conf_t; @@ -223,7 +224,8 @@ typedef struct { struct nxt_router_access_log_s { void (*handler)(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_t *access_log); + nxt_router_access_log_t *access_log, + nxt_var_t *format); nxt_fd_t fd; nxt_str_t path; uint32_t count; diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c index d92e80c3..dc2a6687 100644 --- a/src/nxt_router_access_log.c +++ b/src/nxt_router_access_log.c @@ -10,10 +10,25 @@ #include +typedef struct { + nxt_str_t path; + nxt_str_t format; +} nxt_router_access_log_conf_t; + + +typedef struct { + nxt_str_t text; + nxt_router_access_log_t *access_log; +} nxt_router_access_log_ctx_t; + + static void nxt_router_access_log_writer(nxt_task_t *task, - nxt_http_request_t *r, nxt_router_access_log_t *access_log); -static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); + nxt_http_request_t *r, nxt_router_access_log_t *access_log, + nxt_var_t *format); +static void nxt_router_access_log_write_ready(nxt_task_t *task, void *obj, + void *data); +static void nxt_router_access_log_write_error(nxt_task_t *task, void *obj, + void *data); static void nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); static void nxt_router_access_log_error(nxt_task_t *task, @@ -26,26 +41,63 @@ static void nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); +static nxt_conf_map_t nxt_router_access_log_conf[] = { + { + nxt_string("path"), + NXT_CONF_MAP_STR, + offsetof(nxt_router_access_log_conf_t, path), + }, + + { + nxt_string("format"), + NXT_CONF_MAP_STR, + offsetof(nxt_router_access_log_conf_t, format), + }, +}; + + nxt_int_t nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, nxt_conf_value_t *value) { - nxt_str_t path; - nxt_router_t *router; - nxt_router_access_log_t *access_log; + u_char *p; + nxt_int_t ret; + nxt_str_t str; + nxt_var_t *format; + nxt_router_t *router; + nxt_router_access_log_t *access_log; + nxt_router_access_log_conf_t alcf; - router = nxt_router; + static nxt_str_t log_format_str = nxt_string("$remote_addr - - " + "[$time_local] \"$request_line\" $status $body_bytes_sent " + "\"$header_referer\" \"$header_user_agent\""); + + alcf.format = log_format_str; - nxt_conf_get_string(value, &path); + if (nxt_conf_type(value) == NXT_CONF_STRING) { + nxt_conf_get_string(value, &alcf.path); + + } else { + ret = nxt_conf_map_object(rtcf->mem_pool, value, + nxt_router_access_log_conf, + nxt_nitems(nxt_router_access_log_conf), + &alcf); + if (ret != NXT_OK) { + nxt_alert(task, "access log map error"); + return NXT_ERROR; + } + } + + router = nxt_router; access_log = router->access_log; - if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { + if (access_log != NULL && nxt_strstr_eq(&alcf.path, &access_log->path)) { nxt_router_access_log_use(&router->lock, access_log); } else { access_log = nxt_malloc(sizeof(nxt_router_access_log_t) - + path.length); + + alcf.path.length); if (access_log == NULL) { nxt_alert(task, "failed to allocate access log structure"); return NXT_ERROR; @@ -55,14 +107,32 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, access_log->handler = &nxt_router_access_log_writer; access_log->count = 1; - access_log->path.length = path.length; + access_log->path.length = alcf.path.length; access_log->path.start = (u_char *) access_log + sizeof(nxt_router_access_log_t); - nxt_memcpy(access_log->path.start, path.start, path.length); + nxt_memcpy(access_log->path.start, alcf.path.start, alcf.path.length); + } + + str.length = alcf.format.length + 1; + + str.start = nxt_malloc(str.length); + if (str.start == NULL) { + nxt_alert(task, "failed to allocate log format structure"); + return NXT_ERROR; + } + + p = nxt_cpymem(str.start, alcf.format.start, alcf.format.length); + *p = '\n'; + + format = nxt_var_compile(&str, rtcf->mem_pool, rtcf->var_fields, + NXT_VAR_LOGGING); + if (nxt_slow_path(format == NULL)) { + return NXT_ERROR; } rtcf->access_log = access_log; + rtcf->log_format = format; return NXT_OK; } @@ -70,130 +140,56 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, static void nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_t *access_log) + nxt_router_access_log_t *access_log, nxt_var_t *format) { - size_t size; - u_char *buf, *p; - nxt_off_t bytes; - - static nxt_time_string_t date_cache = { - (nxt_atomic_uint_t) -1, - nxt_router_access_log_date, - "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", - nxt_length("31/Dec/1986:19:40:00 +0300"), - NXT_THREAD_TIME_LOCAL, - NXT_THREAD_TIME_SEC, - }; - - size = r->remote->address_length - + 6 /* ' - - [' */ - + date_cache.size - + 3 /* '] "' */ - + r->method->length - + 1 /* space */ - + r->target.length - + 1 /* space */ - + r->version.length - + 2 /* '" ' */ - + 3 /* status */ - + 1 /* space */ - + NXT_OFF_T_LEN - + 2 /* ' "' */ - + (r->referer != NULL ? r->referer->value_length : 1) - + 3 /* '" "' */ - + (r->user_agent != NULL ? r->user_agent->value_length : 1) - + 2 /* '"\n' */ - ; - - buf = nxt_mp_nget(r->mem_pool, size); - if (nxt_slow_path(buf == NULL)) { + nxt_int_t ret; + nxt_router_access_log_ctx_t *ctx; + + ctx = nxt_mp_get(r->mem_pool, sizeof(nxt_router_access_log_ctx_t)); + if (nxt_slow_path(ctx == NULL)) { return; } - p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), - r->remote->address_length); + ctx->access_log = access_log; - p = nxt_cpymem(p, " - - [", 6); + if (nxt_var_is_const(format)) { + nxt_var_raw(format, &ctx->text); - p = nxt_thread_time_string(task->thread, &date_cache, p); - - p = nxt_cpymem(p, "] \"", 3); - - if (r->method->length != 0) { - p = nxt_cpymem(p, r->method->start, r->method->length); - - if (r->target.length != 0) { - *p++ = ' '; - p = nxt_cpymem(p, r->target.start, r->target.length); - - if (r->version.length != 0) { - *p++ = ' '; - p = nxt_cpymem(p, r->version.start, r->version.length); - } - } + nxt_router_access_log_write_ready(task, r, ctx); } else { - *p++ = '-'; - } - - p = nxt_cpymem(p, "\" ", 2); - - p = nxt_sprintf(p, p + 3, "%03d", r->status); - - *p++ = ' '; - - bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); - - p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); - - p = nxt_cpymem(p, " \"", 2); - - if (r->referer != NULL) { - p = nxt_cpymem(p, r->referer->value, r->referer->value_length); + ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + return; + } - } else { - *p++ = '-'; - } + nxt_var_query(task, r->var_query, format, &ctx->text); + nxt_var_query_resolve(task, r->var_query, ctx, + nxt_router_access_log_write_ready, + nxt_router_access_log_write_error); + } +} - p = nxt_cpymem(p, "\" \"", 3); - if (r->user_agent != NULL) { - p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); +static void +nxt_router_access_log_write_ready(nxt_task_t *task, void *obj, void *data) +{ + nxt_http_request_t *r; + nxt_router_access_log_ctx_t *ctx; - } else { - *p++ = '-'; - } + r = obj; + ctx = data; - p = nxt_cpymem(p, "\"\n", 2); + nxt_fd_write(ctx->access_log->fd, ctx->text.start, ctx->text.length); - nxt_fd_write(access_log->fd, buf, p - buf); + nxt_http_request_close_handler(task, r, r->proto.any); } -static u_char * -nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, - size_t size, const char *format) +static void +nxt_router_access_log_write_error(nxt_task_t *task, void *obj, void *data) { - u_char sign; - time_t gmtoff; - - static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - gmtoff = nxt_timezone(tm) / 60; - - if (gmtoff < 0) { - gmtoff = -gmtoff; - sign = '-'; - - } else { - sign = '+'; - } - return nxt_sprintf(buf, buf + size, format, - tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, - tm->tm_hour, tm->tm_min, tm->tm_sec, - sign, gmtoff / 60, gmtoff % 60); } diff --git a/src/nxt_var.c b/src/nxt_var.c index d3057764..f55a2d30 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -9,7 +9,7 @@ struct nxt_var_s { size_t length; nxt_uint_t vars; - uint8_t strz; /* 1 bit */ + nxt_var_flags_t flags; u_char data[]; /* @@ -331,11 +331,12 @@ nxt_var_index_init(void) nxt_var_t * nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, - nxt_bool_t strz) + nxt_var_flags_t flags) { u_char *p, *end, *next, *src; size_t size; uint32_t index; + nxt_bool_t strz; nxt_var_t *var; nxt_str_t part; nxt_uint_t n; @@ -343,6 +344,8 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, nxt_var_sub_t *subs; nxt_var_decl_t *decl; + strz = (flags & NXT_VAR_STRZ) != 0; + n = 0; p = str->start; @@ -368,7 +371,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, var->length = str->length; var->vars = n; - var->strz = strz; + var->flags = flags; subs = nxt_var_subs(var); src = nxt_var_raw_start(var); @@ -568,6 +571,7 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, size_t length, last, next; nxt_str_t *value, **part; nxt_uint_t i; + nxt_bool_t strz, logging; nxt_array_t parts; nxt_var_sub_t *subs; @@ -583,6 +587,9 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, nxt_memzero(&parts, sizeof(nxt_array_t)); nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *)); + strz = (var->flags & NXT_VAR_STRZ) != 0; + logging = (var->flags & NXT_VAR_LOGGING) != 0; + subs = nxt_var_subs(var); length = var->length; @@ -601,9 +608,13 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, *part = value; length += value->length - subs[i].length; + + if (logging && value->start == NULL) { + length += 1; + } } - p = nxt_mp_nget(query->pool, length + var->strz); + p = nxt_mp_nget(query->pool, length + strz); if (nxt_slow_path(p == NULL)) { goto fail; } @@ -625,6 +636,10 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, p = nxt_cpymem(p, part[i]->start, part[i]->length); + if (logging && part[i]->start == NULL) { + *p++ = '-'; + } + last = next + subs[i].length; } @@ -632,7 +647,7 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, p = nxt_cpymem(p, &src[last], var->length - last); } - if (var->strz) { + if (strz) { *p = '\0'; } diff --git a/src/nxt_var.h b/src/nxt_var.h index 3c38be36..cc7ff502 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -32,6 +32,12 @@ typedef struct { } nxt_var_field_t; +typedef enum { + NXT_VAR_STRZ = 1 << 0, + NXT_VAR_LOGGING = 1 << 1, +} nxt_var_flags_t; + + nxt_inline nxt_bool_t nxt_is_var(nxt_str_t *str) { @@ -45,7 +51,7 @@ nxt_int_t nxt_var_index_init(void); nxt_var_field_t *nxt_var_field_get(nxt_array_t *fields, uint16_t index); nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, - nxt_bool_t strz); + nxt_var_flags_t flags); nxt_int_t nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error); nxt_bool_t nxt_var_is_const(nxt_var_t *var); -- cgit From 69e690affe94eb37308d1eb551b34cd32323aae1 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 28 Jul 2022 14:12:19 +0100 Subject: Tests: added flags to search functions in proto.py. Also removed unnesessary re.compile() calls. --- test/test_tls.py | 5 +---- test/unit/applications/proto.py | 12 ++++++------ test/unit/http.py | 4 +--- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/test/test_tls.py b/test/test_tls.py index 85f9d3b1..5d4cead3 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -1,5 +1,4 @@ import io -import re import ssl import subprocess import time @@ -620,9 +619,7 @@ basicConstraints = critical,CA:TRUE""" skip_alert(r'process .* %s.* exited on signal 9' % app_id) self.wait_for_record( - re.compile( - r' (?!' + app_id + r'#)(\d+)#\d+ "mirror" application started' - ) + r' (?!' + app_id + r'#)(\d+)#\d+ "mirror" application started' ) resp = self.post_ssl( diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index 6ba7b9b8..f04ee408 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -16,18 +16,18 @@ class TestApplicationProto(TestControl): def date_to_sec_epoch(self, date, template='%a, %d %b %Y %X %Z'): return time.mktime(time.strptime(date, template)) - def findall(self, pattern, name='unit.log'): + def findall(self, pattern, name='unit.log', flags=re.M): with Log.open(name) as f: - return re.findall(pattern, f.read()) + return re.findall(pattern, f.read(), flags) - def search_in_log(self, pattern, name='unit.log'): + def search_in_log(self, pattern, name='unit.log', flags=re.M): with Log.open(name) as f: - return re.search(pattern, f.read()) + return re.search(pattern, f.read(), flags) - def wait_for_record(self, pattern, name='unit.log', wait=150): + def wait_for_record(self, pattern, name='unit.log', wait=150, flags=re.M): with Log.open(name) as f: for i in range(wait): - found = re.search(pattern, f.read()) + found = re.search(pattern, f.read(), flags) if found is not None: break diff --git a/test/unit/http.py b/test/unit/http.py index b4a1a17b..522d2ea6 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -209,9 +209,7 @@ class TestHTTP: return {} headers_text, body = m.group(1), m.group(2) - - p = re.compile('(.*?)\x0d\x0a?', re.M | re.S) - headers_lines = p.findall(headers_text) + headers_lines = re.findall('(.*?)\x0d\x0a?', headers_text, re.M | re.S) status = re.search( r'^HTTP\/\d\.\d\s(\d+)|$', headers_lines.pop(0) -- cgit From 698680d8942feed023cdcfe85e9ca5b67261de2e Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 28 Jul 2022 14:13:03 +0100 Subject: Tests: added tests for the log format. Also added tests for the following variables: $request_line, $time_local, $bytes_sent, and $status. --- test/test_access_log.py | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/test/test_access_log.py b/test/test_access_log.py index 5d242a1a..f7343d21 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -15,6 +15,15 @@ class TestAccessLog(TestApplicationPython): '"' + option.temp_dir + '/access.log"', 'access_log' ), 'access_log configure' + def set_format(self, format): + assert 'success' in self.conf( + { + 'path': option.temp_dir + '/access.log', + 'format': format, + }, + 'access_log', + ), 'access_log format' + def wait_for_record(self, pattern, name='access.log'): return super().wait_for_record(pattern, name) @@ -263,3 +272,74 @@ Connection: close self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log') is not None ), 'change' + + def test_access_log_format(self): + self.load('empty') + + def check_format(format, expect, url='/'): + self.set_format(format) + + assert self.get(url=url)['status'] == 200 + assert self.wait_for_record(expect) is not None, 'found' + + format = 'BLAH\t0123456789' + check_format(format, format) + check_format('$uri $status $uri $status', '/ 200 / 200') + + def test_access_log_variables(self): + self.load('mirror') + + # $time_local + + self.set_format('$uri $time_local $uri') + assert self.get(url='/time_local')['status'] == 200 + assert self.wait_for_record('/time_local') is not None, 'time log' + date = self.search_in_log( + r'^\/time_local (.*) \/time_local$', 'access.log' + )[1] + assert ( + abs( + self.date_to_sec_epoch(date, '%d/%b/%Y:%X %z') + - time.mktime(time.localtime()) + ) + < 5 + ), '$time_local' + + # $request_line + + self.set_format('$request_line') + assert self.get(url='/r_line')['status'] == 200 + assert self.wait_for_record(r'^GET \/r_line HTTP\/1\.1$') is not None + + # $body_bytes_sent + + self.set_format('$uri $body_bytes_sent') + body = '0123456789' * 50 + self.post( + url='/bbs', + headers={ + 'Host': 'localhost', + 'Connection': 'close', + 'Content-Type': 'text/html', + }, + body=body, + read_timeout=1, + ) + assert ( + self.wait_for_record(r'^\/bbs ' + str(len(body)) + r'$') is not None + ), '$body_bytes_sent' + + def test_access_log_incorrect(self, skip_alert): + skip_alert(r'failed to apply new conf') + + assert 'error' in self.conf( + option.temp_dir + '/blah/access.log' 'access_log/path', + ), 'access_log path incorrect' + + assert 'error' in self.conf( + { + 'path': option.temp_dir + '/access.log', + 'format': '$remote_add', + }, + 'access_log', + ), 'access_log format incorrect' -- cgit From 2c0888f69c247c82fc02ba207aa19fa00acf4b5e Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 19 Jun 2022 12:48:01 +0200 Subject: Including iff it exists. With NXT_HAVE_PIVOT_ROOT, we had issues in MacOS. Headers should normally be included unconditionally, except of course if they don't exist. This fixes part of the #737 issue on GitHub. --- auto/isolation | 13 +++++++++++++ src/nxt_isolation.c | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/auto/isolation b/auto/isolation index 4ade6a38..6debdc3b 100644 --- a/auto/isolation +++ b/auto/isolation @@ -73,6 +73,19 @@ nxt_feature_test="#include . auto/feature +nxt_feature="" +nxt_feature_name=NXT_HAVE_MNTENT_H +nxt_feature_run=no +nxt_feature_incs= +nxt_feature_libs= +nxt_feature_test="#include + + int main(void) { + return 0; + }" +. auto/feature + + nxt_feature="prctl(PR_SET_NO_NEW_PRIVS)" nxt_feature_name=NXT_HAVE_PR_SET_NO_NEW_PRIVS0 nxt_feature_run=no diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index 7bb8dbfd..5a0714ff 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -7,7 +7,7 @@ #include #include -#if (NXT_HAVE_PIVOT_ROOT) +#if (NXT_HAVE_MNTENT_H) #include #endif -- cgit From 418bc208d08dbc4a0a3511e503c946ab6ac71c39 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 2 Aug 2022 19:39:55 +0200 Subject: Rejecting non-Linux pivot_root(2). Some non-Linux systems implement pivot_root(2), even if they don't document that. An example is MacOS: $ grepc pivot_root / 2>/dev/null .../sys/sysproto.h:3012: int pivot_root(struct proc *, struct pivot_root_args *, int *); Since the prototype of the syscall differs from that of Linux, we can't use that syscall. Let's make sure the test only detects pivot_root(2) under Linux. Also, rename the feature macro to make clear that it's only about Linux's pivot_root(2). This closes #737 issue on GitHub. --- auto/isolation | 5 ++++- src/nxt_isolation.c | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/auto/isolation b/auto/isolation index 6debdc3b..384f7ef1 100644 --- a/auto/isolation +++ b/auto/isolation @@ -61,11 +61,14 @@ fi nxt_feature="Linux pivot_root()" -nxt_feature_name=NXT_HAVE_PIVOT_ROOT +nxt_feature_name=NXT_HAVE_LINUX_PIVOT_ROOT nxt_feature_run=no nxt_feature_incs= nxt_feature_libs= nxt_feature_test="#include + #if !defined(__linux__) + # error + #endif int main() { return SYS_pivot_root; diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index 5a0714ff..796da4c6 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -45,7 +45,7 @@ static int nxt_cdecl nxt_isolation_mount_compare(const void *v1, const void *v2); static void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process); -#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) +#if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) static nxt_int_t nxt_isolation_pivot_root(nxt_task_t *task, const char *rootfs); static nxt_int_t nxt_isolation_make_private_mount(nxt_task_t *task, const char *rootfs); @@ -752,7 +752,7 @@ undo: } -#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) +#if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process) @@ -1007,7 +1007,7 @@ nxt_pivot_root(const char *new_root, const char *old_root) } -#else /* !(NXT_HAVE_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */ +#else /* !(NXT_HAVE_LINUX_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */ nxt_int_t -- cgit From e5d835e1593389b1490def9ec9c031156e2a74a4 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 8 Aug 2022 10:32:24 +0100 Subject: Tests: added tests with UNIX sockets in "source". --- test/test_client_ip.py | 27 ++++++++++++++++++++++++++- test/test_routing.py | 14 +++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/test/test_client_ip.py b/test/test_client_ip.py index 24436351..50aa6afc 100644 --- a/test/test_client_ip.py +++ b/test/test_client_ip.py @@ -1,4 +1,5 @@ from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestClientIP(TestApplicationPython): @@ -15,15 +16,27 @@ class TestClientIP(TestApplicationPython): "client_ip": options, "pass": "applications/client_ip", }, + "unix:" + + option.temp_dir + + "/sock": { + "client_ip": options, + "pass": "applications/client_ip", + }, }, 'listeners', ), 'listeners configure' def get_xff(self, xff, sock_type='ipv4'): - port = 7081 if sock_type == 'ipv4' else 7082 + address = { + 'ipv4': ('127.0.0.1', 7081), + 'ipv6': ('::1', 7082), + 'unix': (option.temp_dir + '/sock', None), + } + (addr, port) = address[sock_type] return self.get( sock_type=sock_type, + addr=addr, port=port, headers={'Connection': 'close', 'X-Forwarded-For': xff}, )['body'] @@ -85,6 +98,18 @@ class TestClientIP(TestApplicationPython): ]: assert self.get_xff(ip, 'ipv6') == ip, 'replace' + def test_client_ip_unix(self, temp_dir): + self.client_ip({'header': 'X-Forwarded-For', 'source': 'unix'}) + + assert self.get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4' + assert self.get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6' + + for ip in [ + '1.1.1.1', + '::11.22.33.44', + ]: + assert self.get_xff(ip, 'unix') == ip, 'replace' + def test_client_ip_recursive(self): self.client_ip( { diff --git a/test/test_routing.py b/test/test_routing.py index fda429a4..3649b37c 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1723,18 +1723,26 @@ class TestRouting(TestApplicationPython): addr = temp_dir + '/sock' assert 'success' in self.conf( - {"unix:" + addr: {"pass": "routes"}}, 'listeners' + { + "127.0.0.1:7081": {"pass": "routes"}, + "unix:" + addr: {"pass": "routes"}, + }, + 'listeners', ), 'source listeners configure' self.route_match({"source": "!0.0.0.0/0"}) assert ( self.get(sock_type='unix', addr=addr)['status'] == 200 - ), 'unix ipv4' + ), 'unix ipv4 neg' self.route_match({"source": "!::/0"}) assert ( self.get(sock_type='unix', addr=addr)['status'] == 200 - ), 'unix ipv6' + ), 'unix ipv6 neg' + + self.route_match({"source": "unix"}) + assert self.get(port=7081)['status'] == 404, 'unix ipv4' + assert self.get(sock_type='unix', addr=addr)['status'] == 200, 'unix' def test_routes_match_source(self): self.route_match({"source": "::"}) -- cgit From c7543311ca70c0855721a67ac8b0408ba35f5378 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 31 Mar 2022 23:12:21 +0200 Subject: Python: supporting UNIX sockets. This closes #635 issue on GitHub. --- src/python/nxt_python_asgi.c | 46 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 91af8f4b..172fd60b 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -30,6 +30,8 @@ static void nxt_py_asgi_close_handler(nxt_unit_request_info_t *req); static PyObject *nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req); static PyObject *nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port); +static PyObject *nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, + uint8_t len, uint16_t port); static PyObject *nxt_py_asgi_create_header(nxt_unit_field_t *f); static PyObject *nxt_py_asgi_create_subprotocols(nxt_unit_field_t *f); @@ -663,7 +665,7 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) SET_ITEM(scope, query_string, v) Py_DECREF(v); - v = nxt_py_asgi_create_address(&r->remote, r->remote_length, 0); + v = nxt_py_asgi_create_ip_address(&r->remote, r->remote_length, 0); if (nxt_slow_path(v == NULL)) { nxt_unit_req_alert(req, "Python failed to create 'client' pair"); goto fail; @@ -735,6 +737,48 @@ fail: static PyObject * nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) +{ + size_t prefix_len; + nxt_str_t addr; + PyObject *pair, *v; + + addr.length = len; + addr.start = nxt_unit_sptr_get(sptr); + + prefix_len = nxt_length("unix:"); + if (!nxt_str_start(&addr, "unix:", prefix_len)) { + return nxt_py_asgi_create_ip_address(sptr, len, port); + } + +#if NXT_HAVE_UNIX_DOMAIN + pair = PyTuple_New(2); + if (nxt_slow_path(pair == NULL)) { + return NULL; + } + + addr.start += prefix_len; + addr.length -= prefix_len; + + v = PyString_FromStringAndSize((const char *) addr.start, addr.length); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(pair); + + return NULL; + } + + PyTuple_SET_ITEM(pair, 0, v); + PyTuple_SET_ITEM(pair, 1, Py_None); + + return pair; + +#else + return NULL; +#endif +} + + +static PyObject * +nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) { char *p, *s; PyObject *pair, *v; -- cgit From d37b76232e9b513d109e61e4d5cb562541ed935c Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 5 Aug 2022 12:47:17 +0200 Subject: Put changes entry in the correct position. --- docs/changes.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 68498278..c32716de 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -31,6 +31,12 @@ NGINX Unit updated to 1.28.0. date="" time="" packager="Nginx Packaging <nginx-packaging@f5.com>"> + + +increased the applications' startup timeout. + + + supporting UNIX sockets in address matching. @@ -75,12 +81,6 @@ handled, and caused a use-after-free bug. - - -increased the applications' startup timeout. - - - force SCRIPT_NAME in Ruby to always be an empty string. -- cgit From 900828cc4b92e95b4810c00df9759ab9a07429c7 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Thu, 17 Feb 2022 12:33:46 +0000 Subject: Fixing isolated process PID manipulation. Registering an isolated PID in the global PID hash is wrong because it can be duplicated. Isolated processes are stored only in the children list until the response for the WHOAMI message is processed and the global PID is discovered. To remove isolated siblings, a pointer to the children list is introduced in the nxt_process_init_t struct. This closes #633 issue on GitHub. --- docs/changes.xml | 7 +++++ src/nxt_application.c | 75 ++++++++++++++++++++++++++++++++++++++++----------- src/nxt_process.c | 34 ++++++++++++++++++++--- src/nxt_process.h | 2 ++ src/nxt_runtime.c | 13 +++++---- test/test_tls.py | 2 +- 6 files changed, 108 insertions(+), 25 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index c32716de..f4f5dbf0 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -93,6 +93,13 @@ the ruby application process could crash if it's interrupted by SIGTERM signal. + + +when isolated PID numbers reach the prototype process host PID, +the prototype crashed. + + + diff --git a/src/nxt_application.c b/src/nxt_application.c index 594574b1..556f1ffb 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -23,6 +23,13 @@ #endif +#ifdef WCOREDUMP +#define NXT_WCOREDUMP(s) WCOREDUMP(s) +#else +#define NXT_WCOREDUMP(s) 0 +#endif + + typedef struct { nxt_app_type_t type; nxt_str_t version; @@ -636,6 +643,8 @@ nxt_proto_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) process->data.app = nxt_app_conf; process->stream = msg->port_msg.stream; + init->siblings = &nxt_proto_children; + ret = nxt_process_start(task, process); if (nxt_slow_path(ret == NXT_ERROR)) { nxt_process_use(task, process, -1); @@ -711,15 +720,19 @@ nxt_proto_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) nxt_debug(task, "app process %PI (aka %PI) is created", isolated_pid, pid); - nxt_runtime_process_remove(task->thread->runtime, process); - process->pid = pid; - nxt_runtime_process_add(task, process); - } else { nxt_debug(task, "app process %PI is created", isolated_pid); } + + if (!process->registered) { + nxt_assert(!nxt_queue_is_empty(&process->ports)); + + nxt_runtime_process_add(task, process); + + nxt_port_use(task, nxt_process_port_first(process), -1); + } } @@ -753,7 +766,11 @@ nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data) int status; nxt_err_t err; nxt_pid_t pid; + nxt_port_t *port; nxt_process_t *process; + nxt_runtime_t *rt; + + rt = task->thread->runtime; nxt_debug(task, "proto sigchld handler signo:%d (%s)", (int) (uintptr_t) obj, data); @@ -783,32 +800,58 @@ nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data) return; } + process = nxt_proto_process_remove(task, pid); + if (WTERMSIG(status)) { -#ifdef WCOREDUMP - nxt_alert(task, "app process (isolated %PI) exited on signal %d%s", - pid, WTERMSIG(status), - WCOREDUMP(status) ? " (core dumped)" : ""); -#else - nxt_alert(task, "app process (isolated %PI) exited on signal %d", - pid, WTERMSIG(status)); -#endif + if (rt->is_pid_isolated) { + nxt_alert(task, "app process %PI (isolated %PI) " + "exited on signal %d%s", + process != NULL ? process->pid : 0, + pid, WTERMSIG(status), + NXT_WCOREDUMP(status) ? " (core dumped)" : ""); + + } else { + nxt_alert(task, "app process %PI exited on signal %d%s", + pid, WTERMSIG(status), + NXT_WCOREDUMP(status) ? " (core dumped)" : ""); + } } else { - nxt_trace(task, "app process (isolated %PI) exited with code %d", - pid, WEXITSTATUS(status)); + if (rt->is_pid_isolated) { + nxt_trace(task, "app process %PI (isolated %PI) " + "exited with code %d", + process != NULL ? process->pid : 0, + pid, WEXITSTATUS(status)); + + } else { + nxt_trace(task, "app process %PI exited with code %d", + pid, WEXITSTATUS(status)); + } } - process = nxt_proto_process_remove(task, pid); if (process == NULL) { continue; } + if (process->registered) { + port = NULL; + + } else { + nxt_assert(!nxt_queue_is_empty(&process->ports)); + + port = nxt_process_port_first(process); + } + if (process->state != NXT_PROCESS_STATE_CREATING) { nxt_port_remove_notify_others(task, process); } nxt_process_close_ports(task, process); + if (port != NULL) { + nxt_port_use(task, port, -1); + } + if (nxt_proto_exiting && nxt_queue_is_empty(&nxt_proto_children)) { nxt_process_quit(task, 0); return; @@ -1122,7 +1165,7 @@ nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process) break; default: - nxt_debug(task, "process (isolated %PI) failed to add", + nxt_alert(task, "process (isolated %PI) failed to add", process->isolated_pid); break; } diff --git a/src/nxt_process.c b/src/nxt_process.c index 98636bbe..738a03bf 100644 --- a/src/nxt_process.c +++ b/src/nxt_process.c @@ -296,6 +296,16 @@ nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process) } nxt_runtime_process_loop; + if (init->siblings != NULL) { + nxt_queue_each(p, init->siblings, nxt_process_t, link) { + + nxt_debug(task, "remove sibling process %PI", p->pid); + + nxt_process_close_ports(task, p); + + } nxt_queue_loop; + } + return NXT_OK; } @@ -303,8 +313,9 @@ nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process) static nxt_pid_t nxt_process_create(nxt_task_t *task, nxt_process_t *process) { - nxt_int_t ret; - nxt_pid_t pid; + nxt_int_t ret; + nxt_pid_t pid; + nxt_runtime_t *rt; #if (NXT_HAVE_CLONE) pid = nxt_clone(SIGCHLD | process->isolation.clone.flags); @@ -352,7 +363,20 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process) process->pid = pid; process->isolated_pid = pid; - nxt_runtime_process_add(task, process); + rt = task->thread->runtime; + + if (rt->is_pid_isolated) { + /* + * Do not register process in runtime with isolated pid. + * Only global pid can be the key to avoid clash. + */ + nxt_assert(!nxt_queue_is_empty(&process->ports)); + + nxt_port_use(task, nxt_process_port_first(process), 1); + + } else { + nxt_runtime_process_add(task, process); + } return pid; } @@ -960,6 +984,8 @@ nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process) { nxt_port_t *port; + nxt_process_use(task, process, 1); + nxt_process_port_each(process, port) { nxt_port_close(task, port); @@ -967,6 +993,8 @@ nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process) nxt_runtime_port_remove(task, port); } nxt_process_port_loop; + + nxt_process_use(task, process, -1); } diff --git a/src/nxt_process.h b/src/nxt_process.h index 642c3419..15fd4e7f 100644 --- a/src/nxt_process.h +++ b/src/nxt_process.h @@ -148,6 +148,8 @@ typedef struct { const nxt_port_handlers_t *port_handlers; const nxt_sig_event_t *signals; + + nxt_queue_t *siblings; } nxt_process_init_t; diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c index 46955f1c..d9c9f2ef 100644 --- a/src/nxt_runtime.c +++ b/src/nxt_runtime.c @@ -1408,6 +1408,7 @@ nxt_runtime_process_release(nxt_runtime_t *rt, nxt_process_t *process) nxt_assert(process->use_count == 0); nxt_assert(process->registered == 0); + nxt_assert(nxt_queue_is_empty(&process->ports)); nxt_port_mmaps_destroy(&process->incoming, 1); @@ -1579,11 +1580,11 @@ nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process) process->registered = 1; - nxt_thread_log_debug("process %PI added", process->pid); + nxt_debug(task, "process %PI added", process->pid); break; default: - nxt_thread_log_debug("process %PI failed to add", process->pid); + nxt_alert(task, "process %PI failed to add", process->pid); break; } @@ -1597,6 +1598,8 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) nxt_pid_t pid; nxt_lvlhsh_query_t lhq; + nxt_assert(process->registered != 0); + pid = process->pid; nxt_runtime_process_lhq_pid(&lhq, &pid); @@ -1608,9 +1611,9 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) { case NXT_OK: - rt->nprocesses--; + nxt_assert(lhq.value == process); - process = lhq.value; + rt->nprocesses--; process->registered = 0; @@ -1618,7 +1621,7 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) break; default: - nxt_thread_log_debug("process %PI remove failed", pid); + nxt_thread_log_alert("process %PI remove failed", pid); break; } diff --git a/test/test_tls.py b/test/test_tls.py index 5d4cead3..3fa5dabf 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -616,7 +616,7 @@ basicConstraints = critical,CA:TRUE""" subprocess.check_output(['kill', '-9', app_id]) - skip_alert(r'process .* %s.* exited on signal 9' % app_id) + skip_alert(r'process %s exited on signal 9' % app_id) self.wait_for_record( r' (?!' + app_id + r'#)(\d+)#\d+ "mirror" application started' -- cgit From 22c510066686d4f5c8cecfeb54c0b958b5f5bb3f Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Wed, 3 Aug 2022 14:42:49 +0200 Subject: Removed dead code. nxt_sockaddr_ntop() stopped being used in commit (git) 029942f4eb71. It has been replaced mostly by nxt_sockaddr_text(). commit 029942f4eb7196c2cff0d0e26bc6ff274138f7d8 Author: Igor Sysoev Date: Wed Feb 22 15:09:59 2017 +0300 I/O operations refactoring. nxt_job_sockaddr_parse() stopped being used in commit (git) 794248090a74. commit 794248090a74f31cbfcf24ea8c835df2d4d21073 Author: Igor Sysoev Date: Wed Mar 4 14:04:08 2020 +0300 Legacy upstream code removed. Also, remove functions and types used only by those two functions: nxt_job_sockaddr_unix_parse() nxt_job_sockaddr_inet6_parse() nxt_job_sockaddr_inet_parse() nxt_job_sockaddr_parse_t nxt_job_resolve() nxt_job_resolve_t --- auto/sources | 1 - src/nxt_job_resolve.c | 132 ---------------- src/nxt_job_resolve.h | 29 ---- src/nxt_main.h | 1 - src/nxt_sockaddr.c | 412 -------------------------------------------------- src/nxt_sockaddr.h | 12 -- 6 files changed, 587 deletions(-) delete mode 100644 src/nxt_job_resolve.c delete mode 100644 src/nxt_job_resolve.h diff --git a/auto/sources b/auto/sources index 65a83f45..560f3bf3 100644 --- a/auto/sources +++ b/auto/sources @@ -69,7 +69,6 @@ NXT_LIB_SRCS=" \ src/nxt_event_conn_job_sendfile.c \ src/nxt_conn_proxy.c \ src/nxt_job.c \ - src/nxt_job_resolve.c \ src/nxt_sockaddr.c \ src/nxt_listen_socket.c \ src/nxt_upstream.c \ diff --git a/src/nxt_job_resolve.c b/src/nxt_job_resolve.c deleted file mode 100644 index 0f1fb9aa..00000000 --- a/src/nxt_job_resolve.c +++ /dev/null @@ -1,132 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#include - - -void -nxt_job_resolve(nxt_job_resolve_t *jbr) -{ - int err; - u_char *host; - size_t length; - nxt_mp_t *mp; - nxt_uint_t n; - nxt_sockaddr_t *sa; - struct addrinfo hint, *res, *r; - nxt_work_handler_t handler; - - #define NXT_BUFSIZE 64 - u_char buf[NXT_BUFSIZE]; - - handler = jbr->error_handler; - res = NULL; - - length = jbr->name.length + 1; - - if (nxt_fast_path(length <= NXT_BUFSIZE)) { - host = buf; - - } else { - host = nxt_mp_alloc(jbr->job.mem_pool, length); - if (nxt_slow_path(host == NULL)) { - goto fail; - } - } - - nxt_cpystrn(host, jbr->name.start, length); - - nxt_memzero(&hint, sizeof(struct addrinfo)); - hint.ai_socktype = SOCK_STREAM; - - err = getaddrinfo((char *) host, NULL, &hint, &res); - - if (err != 0) { - nxt_thread_log_error(jbr->log_level, - "getaddrinfo(\"%s\") failed (%d: %s)", - host, err, gai_strerror(err)); - goto fail; - } - - n = 0; - for (r = res; r != NULL; r = r->ai_next) { - - switch (r->ai_addr->sa_family) { -#if (NXT_INET6) - case AF_INET6: -#endif - case AF_INET: - n++; - break; - - default: - break; - } - } - - jbr->count = n; - mp = jbr->job.mem_pool; - - jbr->sockaddrs = nxt_mp_alloc(mp, n * sizeof(nxt_sockaddr_t *)); - if (nxt_slow_path(jbr->sockaddrs == NULL)) { - goto fail; - } - - n = 0; - for (r = res; r != NULL; r = r->ai_next) { - - switch (r->ai_addr->sa_family) { -#if (NXT_INET6) - case AF_INET6: - length = NXT_INET6_ADDR_STR_LEN; - break; -#endif - case AF_INET: - length = NXT_INET_ADDR_STR_LEN; - break; - - default: - continue; - } - - sa = nxt_sockaddr_create(mp, r->ai_addr, r->ai_addrlen, length); - if (nxt_slow_path(sa == NULL)) { - goto fail; - } - - jbr->sockaddrs[n++] = sa; - - if (jbr->port != 0) { - - switch (sa->u.sockaddr.sa_family) { - case AF_INET: - sa->u.sockaddr_in.sin_port = jbr->port; - break; -#if (NXT_INET6) - case AF_INET6: - sa->u.sockaddr_in6.sin6_port = jbr->port; - break; -#endif - default: - break; - } - } - } - - handler = jbr->ready_handler; - -fail: - - if (nxt_fast_path(res != NULL)) { - freeaddrinfo(res); - } - - if (host != buf) { - nxt_mp_free(jbr->job.mem_pool, host); - } - - nxt_job_return(jbr->job.task, &jbr->job, handler); -} diff --git a/src/nxt_job_resolve.h b/src/nxt_job_resolve.h deleted file mode 100644 index fef55b99..00000000 --- a/src/nxt_job_resolve.h +++ /dev/null @@ -1,29 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#ifndef _NXT_JOB_RESOLVE_H_INCLUDED_ -#define _NXT_JOB_RESOLVE_H_INCLUDED_ - - -typedef struct { - nxt_job_t job; - nxt_str_t name; - - uint32_t log_level; /* 4 bits */ - in_port_t port; - uint16_t count; - - nxt_sockaddr_t **sockaddrs; - - nxt_work_handler_t ready_handler; - nxt_work_handler_t error_handler; -} nxt_job_resolve_t; - - -void nxt_job_resolve(nxt_job_resolve_t *jbr); - - -#endif /* _NXT_JOB_RESOLVE_H_INCLUDED_ */ diff --git a/src/nxt_main.h b/src/nxt_main.h index 7f812568..dca4b6dc 100644 --- a/src/nxt_main.h +++ b/src/nxt_main.h @@ -146,7 +146,6 @@ typedef void (*nxt_event_conn_handler_t)(nxt_thread_t *thr, nxt_conn_t *c); #include #include -#include #include #include diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index e8dee83a..8220590e 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -15,10 +15,6 @@ static nxt_sockaddr_t *nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr); static nxt_sockaddr_t *nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr); static nxt_sockaddr_t *nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr); -static nxt_int_t nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs); -static nxt_int_t nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs); -static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs); - nxt_sockaddr_t * nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_socket_t *ls) @@ -433,82 +429,6 @@ nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) } -size_t -nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf, u_char *end, nxt_bool_t port) -{ - u_char *p; - - switch (sa->u.sockaddr.sa_family) { - - case AF_INET: - p = (u_char *) &sa->u.sockaddr_in.sin_addr; - - if (port) { - p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud:%d", - p[0], p[1], p[2], p[3], - ntohs(sa->u.sockaddr_in.sin_port)); - } else { - p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud", - p[0], p[1], p[2], p[3]); - } - - return p - buf; - -#if (NXT_INET6) - - case AF_INET6: - p = buf; - - if (port) { - *p++ = '['; - } - - p = nxt_inet6_ntop(sa->u.sockaddr_in6.sin6_addr.s6_addr, p, end); - - if (port) { - p = nxt_sprintf(p, end, "]:%d", - ntohs(sa->u.sockaddr_in6.sin6_port)); - } - - return p - buf; -#endif - -#if (NXT_HAVE_UNIX_DOMAIN) - - case AF_UNIX: - -#if (NXT_LINUX) - - p = (u_char *) sa->u.sockaddr_un.sun_path; - - if (p[0] == '\0') { - size_t length; - - /* Linux abstract socket address has no trailing zero. */ - - length = sa->socklen - offsetof(struct sockaddr_un, sun_path) - 1; - p = nxt_sprintf(buf, end, "unix:\\0%*s", length, p + 1); - - } else { - p = nxt_sprintf(buf, end, "unix:%s", p); - } - -#else /* !(NXT_LINUX) */ - - p = nxt_sprintf(buf, end, "unix:%s", sa->u.sockaddr_un.sun_path); - -#endif - - return p - buf; - -#endif /* NXT_HAVE_UNIX_DOMAIN */ - - default: - return 0; - } -} - - #if (NXT_INET6) static u_char * @@ -849,338 +769,6 @@ nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr) } -void -nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs) -{ - u_char *p; - size_t length; - nxt_int_t ret; - nxt_work_handler_t handler; - - nxt_job_set_name(&jbs->resolve.job, "job sockaddr parse"); - - length = jbs->addr.length; - p = jbs->addr.start; - - if (length > 6 && nxt_memcmp(p, "unix:", 5) == 0) { - ret = nxt_job_sockaddr_unix_parse(jbs); - - } else if (length != 0 && *p == '[') { - ret = nxt_job_sockaddr_inet6_parse(jbs); - - } else { - ret = nxt_job_sockaddr_inet_parse(jbs); - } - - switch (ret) { - - case NXT_OK: - handler = jbs->resolve.ready_handler; - break; - - case NXT_ERROR: - handler = jbs->resolve.error_handler; - break; - - default: /* NXT_AGAIN */ - return; - } - - nxt_job_return(jbs->resolve.job.task, &jbs->resolve.job, handler); -} - - -static nxt_int_t -nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs) -{ -#if (NXT_HAVE_UNIX_DOMAIN) - size_t length, socklen; - u_char *path; - nxt_mp_t *mp; - nxt_sockaddr_t *sa; - - /* - * Actual sockaddr_un length can be lesser or even larger than defined - * struct sockaddr_un length (see comment in nxt_socket.h). So - * limit maximum Unix domain socket address length by defined sun_path[] - * length because some OSes accept addresses twice larger than defined - * struct sockaddr_un. Also reserve space for a trailing zero to avoid - * ambiguity, since many OSes accept Unix domain socket addresses - * without a trailing zero. - */ - const size_t max_len = sizeof(struct sockaddr_un) - - offsetof(struct sockaddr_un, sun_path) - 1; - - /* cutting "unix:" */ - length = jbs->addr.length - 5; - path = jbs->addr.start + 5; - - if (length > max_len) { - nxt_thread_log_error(jbs->resolve.log_level, - "unix domain socket \"%V\" name is too long", - &jbs->addr); - return NXT_ERROR; - } - - socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; - -#if (NXT_LINUX) - - /* - * Linux unix(7): - * - * abstract: an abstract socket address is distinguished by the fact - * that sun_path[0] is a null byte ('\0'). The socket's address in - * this namespace is given by the additional bytes in sun_path that - * are covered by the specified length of the address structure. - * (Null bytes in the name have no special significance.) - */ - if (path[0] == '\0') { - socklen--; - } - -#endif - - mp = jbs->resolve.job.mem_pool; - - jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); - - if (nxt_fast_path(jbs->resolve.sockaddrs != NULL)) { - sa = nxt_sockaddr_alloc(mp, socklen, jbs->addr.length); - - if (nxt_fast_path(sa != NULL)) { - jbs->resolve.count = 1; - jbs->resolve.sockaddrs[0] = sa; - - sa->u.sockaddr_un.sun_family = AF_UNIX; - nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length); - - return NXT_OK; - } - } - - return NXT_ERROR; - -#else /* !(NXT_HAVE_UNIX_DOMAIN) */ - - nxt_thread_log_error(jbs->resolve.log_level, - "unix domain socket \"%V\" is not supported", - &jbs->addr); - return NXT_ERROR; - -#endif -} - - -static nxt_int_t -nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs) -{ -#if (NXT_INET6) - u_char *p, *addr, *addr_end; - size_t length; - nxt_mp_t *mp; - nxt_int_t port; - nxt_sockaddr_t *sa; - struct in6_addr *in6_addr; - - length = jbs->addr.length - 1; - addr = jbs->addr.start + 1; - - addr_end = nxt_memchr(addr, ']', length); - - if (addr_end == NULL) { - goto invalid_address; - } - - mp = jbs->resolve.job.mem_pool; - - jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); - - if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) { - return NXT_ERROR; - } - - sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6), - NXT_INET6_ADDR_STR_LEN); - - if (nxt_slow_path(sa == NULL)) { - return NXT_ERROR; - } - - jbs->resolve.count = 1; - jbs->resolve.sockaddrs[0] = sa; - - in6_addr = &sa->u.sockaddr_in6.sin6_addr; - - if (nxt_inet6_addr(in6_addr, addr, addr_end - addr) != NXT_OK) { - goto invalid_address; - } - - p = addr_end + 1; - length = (addr + length) - p; - - if (length == 0) { - jbs->no_port = 1; - port = jbs->resolve.port; - goto found; - } - - if (*p == ':') { - port = nxt_int_parse(p + 1, length - 1); - - if (port >= 1 && port <= 65535) { - port = htons((in_port_t) port); - goto found; - } - } - - nxt_thread_log_error(jbs->resolve.log_level, - "invalid port in \"%V\"", &jbs->addr); - - return NXT_ERROR; - -found: - - sa->u.sockaddr_in6.sin6_family = AF_INET6; - sa->u.sockaddr_in6.sin6_port = (in_port_t) port; - - if (IN6_IS_ADDR_UNSPECIFIED(in6_addr)) { - jbs->wildcard = 1; - } - - return NXT_OK; - -invalid_address: - - nxt_thread_log_error(jbs->resolve.log_level, - "invalid IPv6 address in \"%V\"", &jbs->addr); - return NXT_ERROR; - -#else - - nxt_thread_log_error(jbs->resolve.log_level, - "IPv6 socket \"%V\" is not supported", &jbs->addr); - return NXT_ERROR; - -#endif -} - - -static nxt_int_t -nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs) -{ - u_char *p, *host; - size_t length; - nxt_mp_t *mp; - nxt_int_t port; - in_addr_t addr; - nxt_sockaddr_t *sa; - - addr = INADDR_ANY; - - length = jbs->addr.length; - host = jbs->addr.start; - - p = nxt_memchr(host, ':', length); - - if (p == NULL) { - - /* single value port, address, or host name */ - - port = nxt_int_parse(host, length); - - if (port > 0) { - if (port > 65535) { - goto invalid_port; - } - - /* "*:XX" */ - port = htons((in_port_t) port); - jbs->resolve.port = (in_port_t) port; - - } else { - jbs->no_port = 1; - - addr = nxt_inet_addr(host, length); - - if (addr == INADDR_NONE) { - jbs->resolve.name.length = length; - jbs->resolve.name.start = host; - - nxt_job_resolve(&jbs->resolve); - return NXT_AGAIN; - } - - /* "x.x.x.x" */ - port = jbs->resolve.port; - } - - } else { - - /* x.x.x.x:XX or host:XX */ - - p++; - length = (host + length) - p; - port = nxt_int_parse(p, length); - - if (port < 1 || port > 65535) { - goto invalid_port; - } - - port = htons((in_port_t) port); - - length = (p - 1) - host; - - if (length != 1 || host[0] != '*') { - addr = nxt_inet_addr(host, length); - - if (addr == INADDR_NONE) { - jbs->resolve.name.length = length; - jbs->resolve.name.start = host; - jbs->resolve.port = (in_port_t) port; - - nxt_job_resolve(&jbs->resolve); - return NXT_AGAIN; - } - - /* "x.x.x.x:XX" */ - } - } - - mp = jbs->resolve.job.mem_pool; - - jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); - if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) { - return NXT_ERROR; - } - - sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in), - NXT_INET_ADDR_STR_LEN); - - if (nxt_fast_path(sa != NULL)) { - jbs->resolve.count = 1; - jbs->resolve.sockaddrs[0] = sa; - - jbs->wildcard = (addr == INADDR_ANY); - - sa->u.sockaddr_in.sin_family = AF_INET; - sa->u.sockaddr_in.sin_port = (in_port_t) port; - sa->u.sockaddr_in.sin_addr.s_addr = addr; - - return NXT_OK; - } - - return NXT_ERROR; - -invalid_port: - - nxt_thread_log_error(jbs->resolve.log_level, - "invalid port in \"%V\"", &jbs->addr); - - return NXT_ERROR; -} - - in_addr_t nxt_inet_addr(u_char *buf, size_t length) { diff --git a/src/nxt_sockaddr.h b/src/nxt_sockaddr.h index a8f1b393..0f96f6dd 100644 --- a/src/nxt_sockaddr.h +++ b/src/nxt_sockaddr.h @@ -58,15 +58,6 @@ struct nxt_sockaddr_s { }; -typedef struct { - nxt_job_resolve_t resolve; - nxt_str_t addr; - - uint8_t wildcard; /* 1 bit */ - uint8_t no_port; /* 1 bit */ -} nxt_job_sockaddr_parse_t; - - nxt_sockaddr_t *nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_socket_t *ls); void nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c); @@ -88,12 +79,9 @@ NXT_EXPORT void nxt_sockaddr_text(nxt_sockaddr_t *sa); NXT_EXPORT uint32_t nxt_sockaddr_port_number(nxt_sockaddr_t *sa); NXT_EXPORT nxt_bool_t nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2); -NXT_EXPORT size_t nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf, - u_char *end, nxt_bool_t port); NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr); NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse_optport(nxt_mp_t *mp, nxt_str_t *addr); -NXT_EXPORT void nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs); NXT_EXPORT in_addr_t nxt_inet_addr(u_char *buf, size_t len); #if (NXT_INET6) NXT_EXPORT nxt_int_t nxt_inet6_addr(struct in6_addr *in6_addr, u_char *buf, -- cgit From c1ae86e9301b2af332baa6d3ce2164f3e52d0f1d Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 16 Aug 2022 03:11:36 +0100 Subject: Fixed UNIX sockets support for ASGI. This change was forgotten in the original implementation 282123ba4f7b. --- src/python/nxt_python_asgi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 172fd60b..4ad0857d 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -665,7 +665,7 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) SET_ITEM(scope, query_string, v) Py_DECREF(v); - v = nxt_py_asgi_create_ip_address(&r->remote, r->remote_length, 0); + v = nxt_py_asgi_create_address(&r->remote, r->remote_length, 0); if (nxt_slow_path(v == NULL)) { nxt_unit_req_alert(req, "Python failed to create 'client' pair"); goto fail; -- cgit From 6ddf14a6c10294e2200156738929014bf08f74cd Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 16 Aug 2022 03:12:12 +0100 Subject: Tests: added test for ASGI with UNIX socket. --- test/test_asgi_application.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index 60fcffc1..534bd3c0 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -60,6 +60,16 @@ custom-header: BLAH }, 'headers' assert resp['body'] == body, 'body' + def test_asgi_application_unix(self, temp_dir): + self.load('empty') + + addr = temp_dir + '/sock' + assert 'success' in self.conf( + {"unix:" + addr: {"pass": "applications/empty"}}, 'listeners' + ) + + assert self.get(sock_type='unix', addr=addr)['status'] == 200 + def test_asgi_application_query_string(self): self.load('query_string') -- cgit From 1c2f070ee226256a05ced1eaae08196a375a53b6 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Wed, 22 Jun 2022 13:33:05 +0200 Subject: Fixed include guard. For consistency, use the same pattern as in the rest of the project. --- src/nxt_isolation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nxt_isolation.h b/src/nxt_isolation.h index 88a5f9e1..b1bfc33c 100644 --- a/src/nxt_isolation.h +++ b/src/nxt_isolation.h @@ -2,8 +2,8 @@ * Copyright (C) NGINX, Inc. */ -#ifndef _NXT_ISOLATION_H_ -#define _NXT_ISOLATION_H_ +#ifndef _NXT_ISOLATION_H_INCLUDED_ +#define _NXT_ISOLATION_H_INCLUDED_ nxt_int_t nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process, @@ -15,4 +15,4 @@ nxt_int_t nxt_isolation_prepare_rootfs(nxt_task_t *task, nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process); #endif -#endif /* _NXT_ISOLATION_H_ */ +#endif /* _NXT_ISOLATION_H_INCLUDED_ */ -- cgit From d8e0768a5bae991b96328f469b8e27d8a51da9d6 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 28 Jul 2022 16:10:32 +0200 Subject: Fixed support for abstract Unix sockets. Unix domain sockets are normally backed by files in the filesystem. This has historically been problematic when closing and opening again such sockets, since SO_REUSEADDR is ignored for Unix sockets (POSIX left the behavior of SO_REUSEADDR as implementation-defined, and most --if not all-- implementations decided to just ignore this flag). Many solutions are available for this problem, but all of them have important caveats: - unlink(2) the file when it's not needed anymore. This is not easy, because the process that controls the fd may not be the same process that created the file, and may not have file permissions to remove it. Further solutions can be applied to that caveat: - unlink(2) the file right after creation. This will remove the pathname from the filesystem without closing the socket (it will continue to live until the last fd is closed). This is not useful for us, since we need the pathname of the socket as its interface. - chown(2) or chmod(2) the directory that contains the socket. For removing a file from the filesystem, a process needs write permissions in the containing directory. We could put sockets in dummy directories that can be chown(2)ed to nobody. This could be dangerous, though, as we don't control the socket names. It is our users who configure the socket name in their configuration, and so it's easy that they don't understand the many implications of not chosing an appropriate socket pathname. A user could unknowingly put the socket in a directory that is not supposed to be owned by user nobody, and if we blindly chown(2) or chmod(2) the directory, we could be creating a big security hole. - Ask the main process to remove the socket. This would require a very complex communication mechanism with the main process, which is not impossible, but let's avoid it if there are simpler solutions. - Give the child process the CAP_DAC_OVERRIDE capability. That is one of the most powerful capabilities. A process with that capability can be considered root for most practical aspects. Even if the capability is disabled for most of the lifetime of the process, there's a slight chance that a malicious actor could activate it and then easily do serious damage to the system. - unlink(2) the file right before calling bind(2). This is dangerous because another process (for example, another running instance of unitd(8)), could be using the socket, and removing the pathname from the filesystem would be problematic. To do this correctly, a lot of checks should be added before the actual unlink(2), which is error-prone, and difficult to do correctly, and atomically. - Use abstract-namespace Unix domain sockets. This is the simplest solution, as it only requires accepting a slightly different syntax (basically a @ prefix) for the socket name, to transform it into a string starting with a null byte ('\0') that the kernel can understand. The patch is minimal. Since abstract sockets live in an abstract namespace, they don't create files in the filesystem, so there's no need to remove them later. The kernel removes the name when the last fd to it has been closed. One caveat is that only Linux currently supports this kind of Unix sockets. Of course, a solution to that could be to ask other kernels to implement such a feature. Another caveat is that filesystem permissions can't be used to control access to the socket file (since, of course, there's no file). Anyone knowing the socket name can access to it. The only method to control access to it is by using network_namespaces(7). Since in unitd(8) we're using 0666 file sockets, abstract sockets should be no more insecure than that (anyone can already read/write to the listener sockets). - Ask the kernel to implement a simpler way to unlink(2) socket files when they are not needed anymore. I've suggested that to the mailing list, in: In this commit, I decided to go for the easiest/simplest solution, which is abstract sockets. In fact, we already had partial support. This commit only fixes some small bug in the existing code so that abstract Unix sockets work: - Don't chmod(2) the socket if it's an abstract one. This fixes the creation of abstract sockets, but doesn't make them usable, since we produce them with a trailing '\0' in their name. That will be fixed in the following commit. This closes #669 issue on GitHub. --- docs/changes.xml | 6 ++++++ src/nxt_main_process.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/changes.xml b/docs/changes.xml index f4f5dbf0..27fffc4c 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -37,6 +37,12 @@ increased the applications' startup timeout. + + +supporting abstract UNIX sockets. + + + supporting UNIX sockets in address matching. diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 03761a10..39a8e112 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -1187,7 +1187,9 @@ nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls) #if (NXT_HAVE_UNIX_DOMAIN) - if (sa->u.sockaddr.sa_family == AF_UNIX) { + if (sa->u.sockaddr.sa_family == AF_UNIX + && sa->u.sockaddr_un.sun_path[0] != '\0') + { char *filename; mode_t access; -- cgit From e2aec6686a4d2cf1ddc017b50dbb39baefd2d425 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 7 Aug 2022 01:08:52 +0200 Subject: 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. --- src/nxt_conf_validation.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 3e89d775..fe6c22e5 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -1480,9 +1480,14 @@ nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value) { nxt_int_t ret; + nxt_str_t str; nxt_sockaddr_t *sa; - sa = nxt_sockaddr_parse(vldt->pool, name); + if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) { + return NXT_ERROR; + } + + sa = nxt_sockaddr_parse(vldt->pool, &str); if (nxt_slow_path(sa == NULL)) { return nxt_conf_vldt_error(vldt, "The listener address \"%V\" is invalid.", -- cgit From 7e4a8a54221adf00cd3eb45a24b633ce61400570 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 28 Jul 2022 16:10:32 +0200 Subject: Disallowed abstract unix socket syntax in non-Linux systems. The previous commit added/fixed support for abstract Unix domain sockets on Linux with a leading '@' or '\0'. To be consistent in all platforms, treat those prefixes as markers for abstract sockets in all platforms, and fail if abstract sockets are not supported by the platform. That will avoid mistakes when copying a config file from a Linux system and using it in non-Linux, which would surprisingly create a normal socket. --- docs/changes.xml | 6 ++++++ src/nxt_sockaddr.c | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 27fffc4c..85749bff 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -37,6 +37,12 @@ increased the applications' startup timeout. + + +disallowed abstract Unix domain socket syntax in non-Linux systems. + + + supporting abstract UNIX sockets. diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 8220590e..86c3335e 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -601,8 +601,6 @@ nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr) socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; -#if (NXT_LINUX) - /* * Linux unix(7): * @@ -615,9 +613,12 @@ nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr) 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); -- cgit From d1cb8ab2bb27a864ec6cb21c5e64af315266100d Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 25 Aug 2022 15:50:49 +0100 Subject: Tests: added tests with abstract UNIX sockets. --- test/conftest.py | 2 + test/test_asgi_application_unix_abstract.py | 23 ++++++ test/test_configuration.py | 16 ++++ test/test_unix_abstract.py | 109 ++++++++++++++++++++++++++++ test/unit/check/unix_abstract.py | 25 +++++++ test/unit/http.py | 2 +- 6 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 test/test_asgi_application_unix_abstract.py create mode 100644 test/test_unix_abstract.py create mode 100644 test/unit/check/unix_abstract.py diff --git a/test/conftest.py b/test/conftest.py index 904abc32..ed19838c 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -20,6 +20,7 @@ from unit.check.isolation import check_isolation from unit.check.node import check_node from unit.check.regex import check_regex from unit.check.tls import check_openssl +from unit.check.unix_abstract import check_unix_abstract from unit.http import TestHTTP from unit.log import Log from unit.option import option @@ -213,6 +214,7 @@ def pytest_sessionstart(session): check_chroot() check_isolation() + check_unix_abstract() _clear_conf(unit['temp_dir'] + '/control.unit.sock') diff --git a/test/test_asgi_application_unix_abstract.py b/test/test_asgi_application_unix_abstract.py new file mode 100644 index 00000000..c4ec812f --- /dev/null +++ b/test/test_asgi_application_unix_abstract.py @@ -0,0 +1,23 @@ +from packaging import version +from unit.applications.lang.python import TestApplicationPython + + +class TestASGIApplicationUnixAbstract(TestApplicationPython): + prerequisites = { + 'modules': { + 'python': lambda v: version.parse(v) >= version.parse('3.5') + }, + 'features': ['unix_abstract'], + } + load_module = 'asgi' + + def test_asgi_application_unix_abstract(self): + self.load('empty') + + addr = '\0sock' + assert 'success' in self.conf( + {"unix:@" + addr[1:]: {"pass": "applications/empty"}}, + 'listeners', + ) + + assert self.get(sock_type='unix', addr=addr)['status'] == 200 diff --git a/test/test_configuration.py b/test/test_configuration.py index 4a9d9840..75fbb845 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -2,6 +2,7 @@ import socket import pytest from unit.control import TestControl +from unit.option import option class TestConfiguration(TestControl): @@ -226,6 +227,21 @@ class TestConfiguration(TestControl): {"*:7080": {"pass": "applications/app"}}, 'listeners' ), 'listeners no app' + def test_listeners_unix_abstract(self): + if option.system != 'Linux': + assert 'error' in self.conf( + {"unix:@sock": {"pass": "routes"}}, 'listeners' + ), 'unix abstract at' + + pytest.skip('not yet') + + assert 'error' in self.conf( + {"unix:\0sock": {"pass": "routes"}}, 'listeners' + ), 'unix abstract zero' + assert 'error' in self.conf( + {"unix:\u0000sock": {"pass": "routes"}}, 'listeners' + ), 'unix abstract zero unicode' + def test_listeners_addr(self): assert 'success' in self.try_addr("*:7080"), 'wildcard' assert 'success' in self.try_addr("127.0.0.1:7081"), 'explicit' diff --git a/test/test_unix_abstract.py b/test/test_unix_abstract.py new file mode 100644 index 00000000..195b0aa7 --- /dev/null +++ b/test/test_unix_abstract.py @@ -0,0 +1,109 @@ +from unit.applications.lang.python import TestApplicationPython +from unit.option import option + + +class TestUnixAbstract(TestApplicationPython): + prerequisites = { + 'modules': {'python': 'any'}, + 'features': ['unix_abstract'], + } + + def test_unix_abstract_source(self): + addr = '\0sock' + + def source(source): + assert 'success' in self.conf( + '"' + source + '"', 'routes/0/match/source' + ) + + assert 'success' in self.conf( + { + "listeners": { + "127.0.0.1:7080": {"pass": "routes"}, + "unix:@" + addr[1:]: {"pass": "routes"}, + }, + "routes": [ + { + "match": {"source": "!0.0.0.0/0"}, + "action": {"return": 200}, + } + ], + "applications": {}, + } + ) + + assert ( + self.get(sock_type='unix', addr=addr)['status'] == 200 + ), 'neg ipv4' + + source("!::/0") + assert ( + self.get(sock_type='unix', addr=addr)['status'] == 200 + ), 'neg ipv6' + + source("unix") + assert self.get()['status'] == 404, 'ipv4' + assert self.get(sock_type='unix', addr=addr)['status'] == 200, 'unix' + + def test_unix_abstract_client_ip(self): + def get_xff(xff, sock_type='ipv4'): + address = { + 'ipv4': ('127.0.0.1', 7080), + 'ipv6': ('::1', 7081), + 'unix': ('\0sock', None), + } + (addr, port) = address[sock_type] + + return self.get( + sock_type=sock_type, + addr=addr, + port=port, + headers={'Connection': 'close', 'X-Forwarded-For': xff}, + )['body'] + + assert 'success' in self.conf( + { + "listeners": { + "127.0.0.1:7080": { + "client_ip": { + "header": "X-Forwarded-For", + "source": "unix", + }, + "pass": "applications/client_ip", + }, + "[::1]:7081": { + "client_ip": { + "header": "X-Forwarded-For", + "source": "unix", + }, + "pass": "applications/client_ip", + }, + "unix:@sock": { + "client_ip": { + "header": "X-Forwarded-For", + "source": "unix", + }, + "pass": "applications/client_ip", + }, + }, + "applications": { + "client_ip": { + "type": self.get_application_type(), + "processes": {"spare": 0}, + "path": option.test_dir + "/python/client_ip", + "working_directory": option.test_dir + + "/python/client_ip", + "module": "wsgi", + } + }, + } + ) + + assert get_xff('1.1.1.1') == '127.0.0.1', 'bad source ipv4' + assert get_xff('1.1.1.1', 'ipv6') == '::1', 'bad source ipv6' + + for ip in [ + '1.1.1.1', + '::11.22.33.44', + ]: + assert get_xff(ip, 'unix') == ip, 'replace' diff --git a/test/unit/check/unix_abstract.py b/test/unit/check/unix_abstract.py new file mode 100644 index 00000000..5d1f629e --- /dev/null +++ b/test/unit/check/unix_abstract.py @@ -0,0 +1,25 @@ +import json + +from unit.http import TestHTTP +from unit.option import option + +http = TestHTTP() + + +def check_unix_abstract(): + available = option.available + + resp = http.put( + url='/config', + sock_type='unix', + addr=option.temp_dir + '/control.unit.sock', + body=json.dumps( + { + "listeners": {"unix:@sock": {"pass": "routes"}}, + "routes": [], + } + ), + ) + + if 'success' in resp['body']: + available['features']['unix_abstract'] = True diff --git a/test/unit/http.py b/test/unit/http.py index 522d2ea6..b29667c9 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -51,7 +51,7 @@ class TestHTTP: connect_args = addr if sock_type == 'unix' else (addr, port) try: sock.connect(connect_args) - except ConnectionRefusedError: + except (ConnectionRefusedError, FileNotFoundError): sock.close() pytest.fail('Client can\'t connect to the server.') -- cgit From b26624fc10cc1f4eb88c16ac8fb5b6b4b61895fc Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 31 Aug 2022 12:49:15 +0100 Subject: Ruby: prevented a segfault on receiving SIGINT (^C). As was reported[0] by @travisbell on GitHub, if running unit from the terminal in the foreground when hitting ^C to exit it, the ruby application processes would segfault if they were using threads. It's not 100% clear where the actual problem lies, but it _looks_ like it may be in ruby. The simplest way to deal with this for now is to just ignore SIGINT in the ruby application processes. Unit will still receive and handle it, cleanly shutting everything down. For people who want to handle SIGINT in their ruby application running under unit they can still trap SIGINT and it will override the ignore. [0]: https://github.com/nginx/unit/issues/562#issuecomment-1223229585 Closes: https://github.com/nginx/unit/issues/562 --- docs/changes.xml | 6 ++++++ src/ruby/nxt_ruby.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/docs/changes.xml b/docs/changes.xml index 85749bff..586063db 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -105,6 +105,12 @@ the ruby application process could crash if it's interrupted by SIGTERM signal. + + +prevent the ruby application processes from crashing on SIGINT (^C). + + + when isolated PID numbers reach the prototype process host PID, diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 07d02dce..f316d8a5 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -270,6 +270,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) static char *argv[2] = { (char *) "NGINX_Unit", (char *) "-e0" }; + signal(SIGINT, SIG_IGN); + conf = data->app; c = &conf->u.ruby; -- cgit From f2bab1b1be658e3456aa1cec84a1879d4b01577e Mon Sep 17 00:00:00 2001 From: Artem Konev Date: Mon, 5 Sep 2022 10:42:18 +0100 Subject: Updated the GitHub page banner. --- README.md | 2 +- docs/unitlogo.png | Bin 29600 -> 0 bytes docs/unitlogo.svg | 305 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 306 insertions(+), 1 deletion(-) delete mode 100644 docs/unitlogo.png create mode 100644 docs/unitlogo.svg diff --git a/README.md b/README.md index 2c3b7d1f..039200d6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Universal Web App Server -![NGINX Unit Logo](docs/unitlogo.png) +![NGINX Unit Logo](docs/unitlogo.svg) NGINX Unit is a lightweight and versatile open-source server that has three core capabilities: diff --git a/docs/unitlogo.png b/docs/unitlogo.png deleted file mode 100644 index dbd87fd8..00000000 Binary files a/docs/unitlogo.png and /dev/null differ diff --git a/docs/unitlogo.svg b/docs/unitlogo.svg new file mode 100644 index 00000000..a8b87b18 --- /dev/null +++ b/docs/unitlogo.svg @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit From ce26dd729e6842c9ec8cc83bf091167e4c50a1ec Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 29 Aug 2022 14:27:09 +0800 Subject: Implemented basic statistics API. --- auto/sources | 1 + docs/changes.xml | 6 ++ src/nxt_conf.c | 14 ++++ src/nxt_conf.h | 2 + src/nxt_conn.h | 23 +++++++ src/nxt_conn_accept.c | 9 ++- src/nxt_conn_close.c | 14 ++-- src/nxt_controller.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++-- src/nxt_event_engine.h | 4 ++ src/nxt_h1proto.c | 13 ++-- src/nxt_port.h | 5 ++ src/nxt_router.c | 81 ++++++++++++++++++++++++ src/nxt_status.c | 102 +++++++++++++++++++++++++++++ src/nxt_status.h | 32 ++++++++++ 14 files changed, 459 insertions(+), 16 deletions(-) create mode 100644 src/nxt_status.c create mode 100644 src/nxt_status.h diff --git a/auto/sources b/auto/sources index 560f3bf3..8548f812 100644 --- a/auto/sources +++ b/auto/sources @@ -85,6 +85,7 @@ NXT_LIB_SRCS=" \ src/nxt_router.c \ src/nxt_router_access_log.c \ src/nxt_h1proto.c \ + src/nxt_status.c \ src/nxt_http_request.c \ src/nxt_http_response.c \ src/nxt_http_error.c \ diff --git a/docs/changes.xml b/docs/changes.xml index 586063db..c3496715 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -86,6 +86,12 @@ customizable access log format. + + +basic statistics API. + + + an index file that didn't contain a file extension was incorrectly diff --git a/src/nxt_conf.c b/src/nxt_conf.c index a44b8c75..c6312f3d 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -278,6 +278,20 @@ nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, } +nxt_int_t +nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, nxt_str_t *name, + nxt_conf_value_t *value, uint32_t index) +{ + nxt_conf_object_member_t *member; + + member = &object->u.object->members[index]; + + member->value = *value; + + return nxt_conf_set_string_dup(&member->name, mp, name); +} + + void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, nxt_str_t *value, uint32_t index) diff --git a/src/nxt_conf.h b/src/nxt_conf.h index f95b61c1..c8a276c0 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -127,6 +127,8 @@ NXT_EXPORT nxt_uint_t nxt_conf_object_members_count(nxt_conf_value_t *value); nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, const nxt_conf_value_t *value, uint32_t index); +nxt_int_t nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, + nxt_str_t *name, nxt_conf_value_t *value, uint32_t index); void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, nxt_str_t *value, uint32_t index); nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, diff --git a/src/nxt_conn.h b/src/nxt_conn.h index a443601f..8a703e9a 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -160,6 +160,7 @@ struct nxt_conn_s { uint8_t block_read; /* 1 bit */ uint8_t block_write; /* 1 bit */ uint8_t delayed; /* 1 bit */ + uint8_t idle; /* 1 bit */ #define NXT_CONN_SENDFILE_OFF 0 #define NXT_CONN_SENDFILE_ON 1 @@ -294,6 +295,28 @@ NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task, } while (0) +#define nxt_conn_idle(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + nxt_queue_insert_head(&e->idle_connections, &c->link); \ + \ + c->idle = 1; \ + e->idle_conns_cnt++; \ + } while (0) + + +#define nxt_conn_active(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + nxt_queue_remove(&c->link); \ + \ + c->idle = 0; \ + e->idle_conns_cnt--; \ + } while (0) + + extern nxt_conn_io_t nxt_unix_conn_io; diff --git a/src/nxt_conn_accept.c b/src/nxt_conn_accept.c index 77c44c58..720c7b64 100644 --- a/src/nxt_conn_accept.c +++ b/src/nxt_conn_accept.c @@ -187,7 +187,8 @@ nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data) void nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c) { - nxt_conn_t *next; + nxt_conn_t *next; + nxt_event_engine_t *engine; nxt_sockaddr_text(c->remote); @@ -195,7 +196,11 @@ nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c) (size_t) c->remote->address_length, nxt_sockaddr_address(c->remote)); - nxt_queue_insert_head(&task->thread->engine->idle_connections, &c->link); + engine = task->thread->engine; + + engine->accepted_conns_cnt++; + + nxt_conn_idle(engine, c); c->listen = lev; lev->count++; diff --git a/src/nxt_conn_close.c b/src/nxt_conn_close.c index 7c130309..92bd8d1b 100644 --- a/src/nxt_conn_close.c +++ b/src/nxt_conn_close.c @@ -119,6 +119,8 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data) nxt_socket_close(task, c->socket.fd); c->socket.fd = -1; + engine->closed_conns_cnt++; + if (timers_pending == 0) { nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, @@ -137,8 +139,9 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data) static void nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data) { - nxt_conn_t *c; - nxt_timer_t *timer; + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_event_engine_t *engine; timer = obj; @@ -146,13 +149,16 @@ nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "conn close timer handler fd:%d", c->socket.fd); + engine = task->thread->engine; + if (c->socket.fd != -1) { nxt_socket_close(task, c->socket.fd); c->socket.fd = -1; + + engine->closed_conns_cnt++; } - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - c->write_state->ready_handler, + nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, task, c, c->socket.data); } diff --git a/src/nxt_controller.c b/src/nxt_controller.c index e1e9fade..09168821 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -85,6 +86,12 @@ static void nxt_controller_process_request(nxt_task_t *task, static void nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req, nxt_str_t *path); static nxt_bool_t nxt_controller_check_postpone_request(nxt_task_t *task); +static void nxt_controller_process_status(nxt_task_t *task, + nxt_controller_request_t *req); +static void nxt_controller_status_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_controller_status_response(nxt_task_t *task, + nxt_controller_request_t *req, nxt_str_t *path); #if (NXT_TLS) static void nxt_controller_process_cert(nxt_task_t *task, nxt_controller_request_t *req, nxt_str_t *path); @@ -120,6 +127,7 @@ static nxt_uint_t nxt_controller_router_ready; static nxt_controller_conf_t nxt_controller_conf; static nxt_queue_t nxt_controller_waiting_requests; static nxt_bool_t nxt_controller_waiting_init_conf; +static nxt_conf_value_t *nxt_controller_status; static const nxt_event_conn_state_t nxt_controller_conn_read_state; @@ -1035,6 +1043,7 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) static nxt_str_t certificates = nxt_string("certificates"); #endif static nxt_str_t config = nxt_string("config"); + static nxt_str_t status = nxt_string("status"); c = req->conn; path = req->parser.path; @@ -1058,6 +1067,32 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) return; } + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + if (nxt_str_start(&path, "/status", 7) + && (path.length == 7 || path.start[7] == '/')) + { + if (!nxt_str_eq(&req->parser.method, "GET", 3)) { + goto invalid_method; + } + + if (nxt_controller_status == NULL) { + nxt_controller_process_status(task, req); + return; + } + + if (path.length == 7) { + path.length = 1; + + } else { + path.length -= 7; + path.start += 7; + } + + nxt_controller_status_response(task, req, &path); + return; + } + #if (NXT_TLS) if (nxt_str_start(&path, "/certificates", 13) @@ -1085,15 +1120,18 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) return; } - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (path.length == 1 && path.start[0] == '/') { if (!nxt_str_eq(&req->parser.method, "GET", 3)) { goto invalid_method; } - count = 1; + if (nxt_controller_status == NULL) { + nxt_controller_process_status(task, req); + return; + } + + count = 2; #if (NXT_TLS) count++; #endif @@ -1114,7 +1152,8 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) nxt_conf_set_member(value, &certificates, certs, i++); #endif - nxt_conf_set_member(value, &config, nxt_controller_conf.root, i); + nxt_conf_set_member(value, &config, nxt_controller_conf.root, i++); + nxt_conf_set_member(value, &status, nxt_controller_status, i); resp.status = 200; resp.conf = value; @@ -1451,6 +1490,128 @@ nxt_controller_check_postpone_request(nxt_task_t *task) } +static void +nxt_controller_process_status(nxt_task_t *task, nxt_controller_request_t *req) +{ + uint32_t stream; + nxt_int_t rc; + nxt_port_t *router_port, *controller_port; + nxt_runtime_t *rt; + nxt_controller_response_t resp; + + if (nxt_controller_check_postpone_request(task)) { + nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); + return; + } + + rt = task->thread->runtime; + + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + nxt_assert(router_port != NULL); + nxt_assert(nxt_controller_router_ready); + + controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + + stream = nxt_port_rpc_register_handler(task, controller_port, + nxt_controller_status_handler, + nxt_controller_status_handler, + router_port->pid, req); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_STATUS, + -1, stream, controller_port->id, NULL); + + if (nxt_slow_path(rc != NXT_OK)) { + nxt_port_rpc_cancel(task, controller_port, stream); + + goto fail; + } + + nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); + return; + +fail: + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + resp.status = 500; + resp.title = (u_char *) "Failed to get status."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; +} + + +static void +nxt_controller_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_conf_value_t *status; + nxt_controller_request_t *req; + nxt_controller_response_t resp; + + nxt_debug(task, "controller status handler"); + + req = data; + + if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { + status = nxt_status_get((nxt_status_report_t *) msg->buf->mem.pos, + req->conn->mem_pool); + } else { + status = NULL; + } + + if (status == NULL) { + nxt_queue_remove(&req->link); + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + resp.status = 500; + resp.title = (u_char *) "Failed to get status."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + } + + nxt_controller_status = status; + + nxt_controller_flush_requests(task); + + nxt_controller_status = NULL; +} + + +static void +nxt_controller_status_response(nxt_task_t *task, nxt_controller_request_t *req, + nxt_str_t *path) +{ + nxt_conf_value_t *status; + nxt_controller_response_t resp; + + status = nxt_conf_get_path(nxt_controller_status, path); + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + if (status == NULL) { + resp.status = 404; + resp.title = (u_char *) "Invalid path."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; + } + + resp.status = 200; + resp.conf = status; + + nxt_controller_response(task, req, &resp); +} + + #if (NXT_TLS) static void diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 91cfc0aa..4153742d 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -483,6 +483,10 @@ struct nxt_event_engine_s { nxt_queue_t idle_connections; nxt_array_t *mem_cache; + nxt_atomic_uint_t accepted_conns_cnt; + nxt_atomic_uint_t idle_conns_cnt; + nxt_atomic_uint_t closed_conns_cnt; + nxt_queue_link_t link; // STUB: router link nxt_queue_link_t link0; diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 1473aaa0..852b4866 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -478,7 +478,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn request init"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); r = nxt_http_request_create(task); @@ -1739,7 +1739,7 @@ nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn close"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_shutdown(task, c); } @@ -1754,7 +1754,7 @@ nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn error"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_shutdown(task, c); } @@ -1801,7 +1801,8 @@ nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c) c->sent = 0; engine = task->thread->engine; - nxt_queue_insert_head(&engine->idle_connections, &c->link); + + nxt_conn_idle(engine, c); if (in == NULL) { c->read_state = &nxt_h1p_keepalive_state; @@ -1855,7 +1856,7 @@ nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p idle close"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_idle_response(task, c); } @@ -1874,7 +1875,7 @@ nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data) c = nxt_read_timer_conn(timer); c->block_read = 1; - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_idle_response(task, c); } diff --git a/src/nxt_port.h b/src/nxt_port.h index 6b4d3c8f..3a8da5ad 100644 --- a/src/nxt_port.h +++ b/src/nxt_port.h @@ -53,6 +53,9 @@ struct nxt_port_handlers_s { nxt_port_handler_t data; nxt_port_handler_t app_restart; + /* Status report. */ + nxt_port_handler_t status; + nxt_port_handler_t oosm; nxt_port_handler_t shm_ack; nxt_port_handler_t read_queue; @@ -104,6 +107,7 @@ typedef enum { _NXT_PORT_MSG_DATA = nxt_port_handler_idx(data), _NXT_PORT_MSG_APP_RESTART = nxt_port_handler_idx(app_restart), + _NXT_PORT_MSG_STATUS = nxt_port_handler_idx(status), _NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm), _NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack), @@ -145,6 +149,7 @@ typedef enum { NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA, NXT_PORT_MSG_DATA_LAST = nxt_msg_last(_NXT_PORT_MSG_DATA), NXT_PORT_MSG_APP_RESTART = nxt_msg_last(_NXT_PORT_MSG_APP_RESTART), + NXT_PORT_MSG_STATUS = nxt_msg_last(_NXT_PORT_MSG_STATUS), NXT_PORT_MSG_OOSM = nxt_msg_last(_NXT_PORT_MSG_OOSM), NXT_PORT_MSG_SHM_ACK = nxt_msg_last(_NXT_PORT_MSG_SHM_ACK), diff --git a/src/nxt_router.c b/src/nxt_router.c index e1f4f6da..e7723a2d 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -7,6 +7,7 @@ #include #include +#include #if (NXT_TLS) #include #endif @@ -90,6 +91,8 @@ static void nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); static void nxt_router_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); +static void nxt_router_status_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg); static void nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); @@ -269,6 +272,7 @@ static const nxt_port_handlers_t nxt_router_process_port_handlers = { .get_mmap = nxt_router_get_mmap_handler, .data = nxt_router_conf_data_handler, .app_restart = nxt_router_app_restart_handler, + .status = nxt_router_status_handler, .remove_pid = nxt_router_remove_pid_handler, .access_log = nxt_router_access_log_reopen_handler, .rpc_ready = nxt_port_rpc_handler, @@ -918,6 +922,83 @@ fail: } +static void +nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) +{ + u_char *p; + size_t alloc; + nxt_app_t *app; + nxt_buf_t *b; + nxt_uint_t type; + nxt_port_t *port; + nxt_status_app_t *app_stat; + nxt_event_engine_t *engine; + nxt_status_report_t *report; + + port = nxt_runtime_port_find(task->thread->runtime, + msg->port_msg.pid, + msg->port_msg.reply_port); + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "nxt_router_status_handler(): reply port not found"); + return; + } + + alloc = sizeof(nxt_status_report_t); + + nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { + + alloc += sizeof(nxt_status_app_t) + app->name.length; + + } nxt_queue_loop; + + b = nxt_buf_mem_alloc(port->mem_pool, alloc, 0); + if (nxt_slow_path(b == NULL)) { + type = NXT_PORT_MSG_RPC_ERROR; + goto fail; + } + + report = (nxt_status_report_t *) b->mem.free; + b->mem.free = b->mem.end; + + nxt_memzero(report, sizeof(nxt_status_report_t)); + + nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) { + + report->accepted_conns += engine->accepted_conns_cnt; + report->idle_conns += engine->idle_conns_cnt; + report->closed_conns += engine->closed_conns_cnt; + + } nxt_queue_loop; + + report->apps_count = 0; + app_stat = report->apps; + p = b->mem.end; + + nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { + p -= app->name.length; + + nxt_memcpy(p, app->name.start, app->name.length); + + app_stat->name.length = app->name.length; + app_stat->name.start = (u_char *) (p - b->mem.pos); + + app_stat->active_requests = app->active_requests; + app_stat->pending_processes = app->pending_processes; + app_stat->processes = app->processes; + app_stat->idle_processes = app->idle_processes; + + report->apps_count++; + app_stat++; + } nxt_queue_loop; + + type = NXT_PORT_MSG_RPC_READY_LAST; + +fail: + + nxt_port_socket_write(task, port, type, -1, msg->port_msg.stream, 0, b); +} + + static void nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port, void *data) diff --git a/src/nxt_status.c b/src/nxt_status.c new file mode 100644 index 00000000..529f6ebb --- /dev/null +++ b/src/nxt_status.c @@ -0,0 +1,102 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include + + +nxt_conf_value_t * +nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) +{ + size_t i; + nxt_str_t name; + nxt_int_t ret; + nxt_status_app_t *app; + nxt_conf_value_t *status, *obj, *apps, *app_obj; + + static nxt_str_t conns_str = nxt_string("connections"); + static nxt_str_t acc_str = nxt_string("accepted"); + static nxt_str_t active_str = nxt_string("active"); + static nxt_str_t idle_str = nxt_string("idle"); + static nxt_str_t closed_str = nxt_string("closed"); + static nxt_str_t reqs_str = nxt_string("requests"); + static nxt_str_t apps_str = nxt_string("applications"); + static nxt_str_t procs_str = nxt_string("processes"); + static nxt_str_t run_str = nxt_string("running"); + static nxt_str_t start_str = nxt_string("starting"); + + status = nxt_conf_create_object(mp, 3); + if (nxt_slow_path(status == NULL)) { + return NULL; + } + + obj = nxt_conf_create_object(mp, 4); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &conns_str, obj, 0); + + nxt_conf_set_member_integer(obj, &acc_str, report->accepted_conns, 0); + nxt_conf_set_member_integer(obj, &active_str, report->accepted_conns + - report->closed_conns + - report->idle_conns, 1); + nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2); + nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3); + + obj = nxt_conf_create_object(mp, 0); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &reqs_str, obj, 1); + + apps = nxt_conf_create_object(mp, report->apps_count); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &apps_str, apps, 2); + + for (i = 0; i < report->apps_count; i++) { + app = &report->apps[i]; + + app_obj = nxt_conf_create_object(mp, 2); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + name.length = app->name.length; + name.start = nxt_pointer_to(report, (uintptr_t) app->name.start); + + ret = nxt_conf_set_member_dup(apps, mp, &name, app_obj, i); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + obj = nxt_conf_create_object(mp, 3); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(app_obj, &procs_str, obj, 0); + + nxt_conf_set_member_integer(obj, &run_str, app->processes, 0); + nxt_conf_set_member_integer(obj, &start_str, app->pending_processes, 1); + nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2); + + obj = nxt_conf_create_object(mp, 1); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(app_obj, &reqs_str, obj, 1); + + nxt_conf_set_member_integer(obj, &active_str, app->active_requests, 0); + } + + return status; +} diff --git a/src/nxt_status.h b/src/nxt_status.h new file mode 100644 index 00000000..b12eabcb --- /dev/null +++ b/src/nxt_status.h @@ -0,0 +1,32 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_STATUS_H_INCLUDED_ +#define _NXT_STATUS_H_INCLUDED_ + + +typedef struct { + nxt_str_t name; + uint32_t active_requests; + uint32_t pending_processes; + uint32_t processes; + uint32_t idle_processes; +} nxt_status_app_t; + + +typedef struct { + uint64_t accepted_conns; + uint64_t idle_conns; + uint64_t closed_conns; + + size_t apps_count; + nxt_status_app_t apps[]; +} nxt_status_report_t; + + +nxt_conf_value_t *nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp); + + +#endif /* _NXT_STATUS_H_INCLUDED_ */ -- cgit From 3ea113fcb7261a0be3b9dc8d32c402da1bcfadaa Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 29 Aug 2022 14:32:20 +0800 Subject: Status: added requests count. --- src/nxt_event_engine.h | 1 + src/nxt_http_request.c | 2 ++ src/nxt_router.c | 1 + src/nxt_status.c | 5 ++++- src/nxt_status.h | 1 + 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 4153742d..291ea749 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -486,6 +486,7 @@ struct nxt_event_engine_s { nxt_atomic_uint_t accepted_conns_cnt; nxt_atomic_uint_t idle_conns_cnt; nxt_atomic_uint_t closed_conns_cnt; + nxt_atomic_uint_t requests_cnt; nxt_queue_link_t link; // STUB: router link diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index a16340de..943ad82d 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -278,6 +278,8 @@ nxt_http_request_create(nxt_task_t *task) r->resp.content_length_n = -1; r->state = &nxt_http_request_init_state; + task->thread->engine->requests_cnt++; + return r; fail: diff --git a/src/nxt_router.c b/src/nxt_router.c index e7723a2d..f02bf3f2 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -967,6 +967,7 @@ nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) report->accepted_conns += engine->accepted_conns_cnt; report->idle_conns += engine->idle_conns_cnt; report->closed_conns += engine->closed_conns_cnt; + report->requests += engine->requests_cnt; } nxt_queue_loop; diff --git a/src/nxt_status.c b/src/nxt_status.c index 529f6ebb..12280019 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -23,6 +23,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) static nxt_str_t idle_str = nxt_string("idle"); static nxt_str_t closed_str = nxt_string("closed"); static nxt_str_t reqs_str = nxt_string("requests"); + static nxt_str_t total_str = nxt_string("total"); static nxt_str_t apps_str = nxt_string("applications"); static nxt_str_t procs_str = nxt_string("processes"); static nxt_str_t run_str = nxt_string("running"); @@ -47,13 +48,15 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2); nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3); - obj = nxt_conf_create_object(mp, 0); + obj = nxt_conf_create_object(mp, 1); if (nxt_slow_path(obj == NULL)) { return NULL; } nxt_conf_set_member(status, &reqs_str, obj, 1); + nxt_conf_set_member_integer(obj, &total_str, report->requests, 0); + apps = nxt_conf_create_object(mp, report->apps_count); if (nxt_slow_path(obj == NULL)) { return NULL; diff --git a/src/nxt_status.h b/src/nxt_status.h index b12eabcb..a99ac7d0 100644 --- a/src/nxt_status.h +++ b/src/nxt_status.h @@ -20,6 +20,7 @@ typedef struct { uint64_t accepted_conns; uint64_t idle_conns; uint64_t closed_conns; + uint64_t requests; size_t apps_count; nxt_status_app_t apps[]; -- cgit From 6915ce1d1ca08ee72de1bafba1514a458b72116c Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 5 Sep 2022 23:06:16 +0100 Subject: Tests: added tests for basic statistics. --- test/conftest.py | 3 + test/test_status.py | 223 ++++++++++++++++++++++++++++++++++++++++++++++++ test/test_status_tls.py | 30 +++++++ test/unit/status.py | 45 ++++++++++ 4 files changed, 301 insertions(+) create mode 100644 test/test_status.py create mode 100644 test/test_status_tls.py create mode 100644 test/unit/status.py diff --git a/test/conftest.py b/test/conftest.py index ed19838c..18851baa 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -24,6 +24,7 @@ from unit.check.unix_abstract import check_unix_abstract from unit.http import TestHTTP from unit.log import Log from unit.option import option +from unit.status import Status from unit.utils import public_dir from unit.utils import waitforfiles @@ -429,6 +430,8 @@ def unit_run(state_dir=None): controller['pid'] = pid_by_name(controller['name']) controller['fds'] = _count_fds(controller['pid']) + Status._check_zeros() + return unit_instance diff --git a/test/test_status.py b/test/test_status.py new file mode 100644 index 00000000..214072d4 --- /dev/null +++ b/test/test_status.py @@ -0,0 +1,223 @@ +import time + +import pytest +from unit.applications.lang.python import TestApplicationPython +from unit.option import option +from unit.status import Status + + +class TestStatus(TestApplicationPython): + prerequisites = {'modules': {'python': 'any'}} + + def test_status(self): + assert 'error' in self.conf_delete('/status'), 'DELETE method' + + def test_status_requests(self, skip_alert): + skip_alert(r'Python failed to import module "blah"') + + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": {"pass": "applications/empty"}, + "*:7082": {"pass": "applications/blah"}, + }, + "routes": [{"action": {"return": 200}}], + "applications": { + "empty": { + "type": self.get_application_type(), + "processes": {"spare": 0}, + "path": option.test_dir + '/python/empty', + "working_directory": option.test_dir + '/python/empty', + "module": "wsgi", + }, + "blah": { + "type": self.get_application_type(), + "processes": {"spare": 0}, + "module": "blah", + }, + }, + }, + ) + + Status.init() + + assert self.get()['status'] == 200 + assert Status.get('/requests/total') == 1, '2xx' + + assert self.get(port=7081)['status'] == 200 + assert Status.get('/requests/total') == 2, '2xx app' + + assert ( + self.get(headers={'Host': '/', 'Connection': 'close'})['status'] + == 400 + ) + assert Status.get('/requests/total') == 3, '4xx' + + assert self.get(port=7082)['status'] == 503 + assert Status.get('/requests/total') == 4, '5xx' + + self.http( + b"""GET / HTTP/1.1 +Host: localhost + +GET / HTTP/1.1 +Host: localhost +Connection: close + +""", + raw=True, + ) + assert Status.get('/requests/total') == 6, 'pipeline' + + (_, sock) = self.get(port=7081, no_recv=True, start=True) + + time.sleep(1) + + assert Status.get('/requests/total') == 7, 'no receive' + + sock.close() + + def test_status_connections(self): + def check_connections(accepted, active, idle, closed): + Status.get('/connections') == { + 'accepted': accepted, + 'active': active, + 'idle': idle, + 'closed': closed, + } + + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": {"pass": "applications/delayed"}, + }, + "routes": [{"action": {"return": 200}}], + "applications": { + "delayed": { + "type": self.get_application_type(), + "processes": {"spare": 0}, + "path": option.test_dir + "/python/delayed", + "working_directory": option.test_dir + + "/python/delayed", + "module": "wsgi", + }, + }, + }, + ) + + Status.init() + + # accepted, closed + + assert self.get()['status'] == 200 + check_connections(1, 0, 0, 1) + + # idle + + _, sock = self.http(b'', start=True, raw=True, no_recv=True) + check_connections(2, 0, 1, 1) + + self.get(sock=sock) + check_connections(2, 0, 0, 2) + + # active + + (_, sock) = self.get( + headers={ + 'Host': 'localhost', + 'X-Delay': '2', + 'Connection': 'close', + }, + port=7081, + start=True, + read_timeout=1, + ) + check_connections(3, 1, 0, 2) + + self.get(sock=sock) + check_connections(3, 0, 0, 3) + + def test_status_applications(self): + def check_applications(expert): + apps = list(self.conf_get('/status/applications').keys()).sort() + assert apps == expert.sort() + + def check_application(name, running, starting, idle, active): + Status.get('/applications/' + name) == { + 'processes': { + 'running': running, + 'starting': starting, + 'idle': idle, + }, + 'requests': {'active': active}, + } + + self.load('delayed') + Status.init() + + check_applications(['delayed']) + check_application('delayed', 0, 0, 0, 0) + + # idle + + assert self.get()['status'] == 200 + check_application('delayed', 1, 0, 1, 0) + + assert 'success' in self.conf('4', 'applications/delayed/processes') + check_application('delayed', 4, 0, 4, 0) + + # active + + (_, sock) = self.get( + headers={ + 'Host': 'localhost', + 'X-Delay': '2', + 'Connection': 'close', + }, + start=True, + read_timeout=1, + ) + check_application('delayed', 4, 0, 3, 1) + sock.close() + + # starting + + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "applications/restart"}, + "*:7081": {"pass": "applications/delayed"}, + }, + "routes": [], + "applications": { + "restart": { + "type": self.get_application_type(), + "processes": {"spare": 0}, + "path": option.test_dir + "/python/restart", + "working_directory": option.test_dir + + "/python/restart", + "module": "longstart", + }, + "delayed": { + "type": self.get_application_type(), + "processes": {"spare": 0}, + "path": option.test_dir + "/python/delayed", + "working_directory": option.test_dir + + "/python/delayed", + "module": "wsgi", + }, + }, + }, + ) + Status.init() + + check_applications(['delayed', 'restart']) + check_application('restart', 0, 0, 0, 0) + check_application('delayed', 0, 0, 0, 0) + + self.get(read_timeout=1) + + check_application('restart', 0, 1, 0, 1) + check_application('delayed', 0, 0, 0, 0) diff --git a/test/test_status_tls.py b/test/test_status_tls.py new file mode 100644 index 00000000..dc3d68da --- /dev/null +++ b/test/test_status_tls.py @@ -0,0 +1,30 @@ +from unit.applications.tls import TestApplicationTLS +from unit.status import Status + + +class TestStatusTLS(TestApplicationTLS): + prerequisites = {'modules': {'openssl': 'any'}} + + def test_status_tls_requests(self): + self.certificate() + + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": { + "pass": "routes", + "tls": {"certificate": "default"}, + }, + }, + "routes": [{"action": {"return": 200}}], + "applications": {}, + } + ) + + Status.init() + + assert self.get()['status'] == 200 + assert self.get_ssl(port=7081)['status'] == 200 + + assert Status.get('/requests/total') == 2 diff --git a/test/unit/status.py b/test/unit/status.py new file mode 100644 index 00000000..17416f17 --- /dev/null +++ b/test/unit/status.py @@ -0,0 +1,45 @@ +from unit.control import TestControl + + +class Status: + _status = None + control = TestControl() + + def _check_zeros(): + assert Status.control.conf_get('/status') == { + 'connections': { + 'accepted': 0, + 'active': 0, + 'idle': 0, + 'closed': 0, + }, + 'requests': {'total': 0}, + 'applications': {}, + } + + def init(status=None): + Status._status = ( + status if status is not None else Status.control.conf_get('/status') + ) + + def diff(): + def find_diffs(d1, d2): + if isinstance(d1, dict) and isinstance(d2, dict): + return { + k: find_diffs(d1.get(k, 0), d2.get(k, 0)) + for k in d1 + if k in d2 + } + else: + return d1 - d2 + + return find_diffs(Status.control.conf_get('/status'), Status._status) + + def get(path='/'): + path = path.split('/')[1:] + diff = Status.diff() + + for p in path: + diff = diff[p] + + return diff -- cgit From b25ffe2bf30ea3d57e7e6e6cb9ec59e9a69fc8e9 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 5 Sep 2022 23:55:15 +0100 Subject: Fixed minor issues in "changes.xml". --- docs/changes.xml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index c3496715..989001dd 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -45,13 +45,13 @@ disallowed abstract Unix domain socket syntax in non-Linux systems. -supporting abstract UNIX sockets. +support for abstract Unix sockets. -supporting UNIX sockets in address matching. +support for Unix sockets in address matching. @@ -75,8 +75,7 @@ more http variables support. -added a new variable, $dollar, that translates to a literal "$" during -variable substitution. +the $dollar variable translates to a literal "$" during variable substitution. @@ -94,8 +93,7 @@ basic statistics API. -an index file that didn't contain a file extension was incorrectly -handled, and caused a use-after-free bug. +router process could crash if index file didn't contain an extension. @@ -107,13 +105,13 @@ force SCRIPT_NAME in Ruby to always be an empty string. -the ruby application process could crash if it's interrupted by SIGTERM signal. +the Ruby application process could crash on SIGTERM. -prevent the ruby application processes from crashing on SIGINT (^C). +the Ruby application process could crash on SIGINT. -- cgit From 9d3b9dba40924229b0c4909b0a4c60d08214501c Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Tue, 6 Sep 2022 09:40:54 +0800 Subject: Status: fixed incorrect pointer in test operation. Found by Coverity (CID 380755). --- src/nxt_status.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nxt_status.c b/src/nxt_status.c index 12280019..f8002e86 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -58,7 +58,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) nxt_conf_set_member_integer(obj, &total_str, report->requests, 0); apps = nxt_conf_create_object(mp, report->apps_count); - if (nxt_slow_path(obj == NULL)) { + if (nxt_slow_path(apps == NULL)) { return NULL; } @@ -81,7 +81,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) } obj = nxt_conf_create_object(mp, 3); - if (nxt_slow_path(app_obj == NULL)) { + if (nxt_slow_path(obj == NULL)) { return NULL; } @@ -92,7 +92,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2); obj = nxt_conf_create_object(mp, 1); - if (nxt_slow_path(app_obj == NULL)) { + if (nxt_slow_path(obj == NULL)) { return NULL; } -- cgit From c65e04682e85cc708b534863ae8f4e069ccccf64 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 7 Sep 2022 01:11:04 +0100 Subject: Tests: minor fixes. --- test/python/ctx_iter_atexit/wsgi.py | 1 - test/test_access_log.py | 22 ++---------------- test/test_asgi_application.py | 45 ++++--------------------------------- test/test_configuration.py | 12 +++------- test/test_go_application.py | 12 +--------- test/test_node_application.py | 11 +-------- test/test_php_application.py | 11 +-------- test/test_proxy.py | 4 ---- test/test_python_application.py | 44 ++++-------------------------------- test/test_ruby_application.py | 11 +-------- test/test_tls.py | 17 ++------------ 11 files changed, 19 insertions(+), 171 deletions(-) diff --git a/test/python/ctx_iter_atexit/wsgi.py b/test/python/ctx_iter_atexit/wsgi.py index b2f12c35..75d40895 100644 --- a/test/python/ctx_iter_atexit/wsgi.py +++ b/test/python/ctx_iter_atexit/wsgi.py @@ -15,7 +15,6 @@ class application: self.start( '200', [ - ('Content-Type', self.environ.get('CONTENT_TYPE')), ('Content-Length', str(len(body))), ], ) diff --git a/test/test_access_log.py b/test/test_access_log.py index f7343d21..b1d89343 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -36,7 +36,6 @@ class TestAccessLog(TestApplicationPython): headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body='01234', @@ -47,15 +46,7 @@ class TestAccessLog(TestApplicationPython): self.wait_for_record(r'"POST / HTTP/1.1" 200 5') is not None ), 'keepalive 1' - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=sock, - body='0123456789', - ) + resp = self.post(sock=sock, body='0123456789') assert ( self.wait_for_record(r'"POST / HTTP/1.1" 200 10') is not None @@ -315,16 +306,7 @@ Connection: close self.set_format('$uri $body_bytes_sent') body = '0123456789' * 50 - self.post( - url='/bbs', - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - body=body, - read_timeout=1, - ) + self.post(url='/bbs', body=body, read_timeout=1) assert ( self.wait_for_record(r'^\/bbs ' + str(len(body)) + r'$') is not None ), '$body_bytes_sent' diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index 534bd3c0..34dfe18e 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -160,15 +160,7 @@ custom-header: BLAH assert self.get()['status'] == 200, 'init' body = '0123456789AB' * 1024 * 1024 # 12 Mb - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - body=body, - read_buffer_size=1024 * 1024, - ) + resp = self.post(body=body, read_buffer_size=1024 * 1024) assert resp['body'] == body, 'keep-alive 1' @@ -182,7 +174,6 @@ custom-header: BLAH headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -192,15 +183,7 @@ custom-header: BLAH assert resp['body'] == body, 'keep-alive 1' body = '0123456789' - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=sock, - body=body, - ) + resp = self.post(sock=sock, body=body) assert resp['body'] == body, 'keep-alive 2' @@ -218,7 +201,6 @@ custom-header: BLAH headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -236,7 +218,6 @@ custom-header: BLAH headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, sock=socks[i], @@ -249,15 +230,7 @@ custom-header: BLAH self.load('mirror', processes=i + 1) for i in range(conns): - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=socks[i], - body=body, - ) + resp = self.post(sock=socks[i], body=body) assert resp['body'] == body, 'keep-alive close' @@ -274,7 +247,6 @@ custom-header: BLAH headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -287,16 +259,7 @@ custom-header: BLAH assert self.get()['status'] == 200, 'init' - (resp, sock) = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - start=True, - sock=sock, - body=body, - ) + (resp, sock) = self.post(start=True, sock=sock, body=body) assert resp['status'] == 200, 'reconfigure 2 keep-alive 2' assert resp['body'] == '', 'reconfigure 2 keep-alive 2 body' diff --git a/test/test_configuration.py b/test/test_configuration.py index 75fbb845..7c612db0 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -229,18 +229,12 @@ class TestConfiguration(TestControl): def test_listeners_unix_abstract(self): if option.system != 'Linux': - assert 'error' in self.conf( - {"unix:@sock": {"pass": "routes"}}, 'listeners' - ), 'unix abstract at' + assert 'error' in self.try_addr("unix:@sock"), 'abstract at' pytest.skip('not yet') - assert 'error' in self.conf( - {"unix:\0sock": {"pass": "routes"}}, 'listeners' - ), 'unix abstract zero' - assert 'error' in self.conf( - {"unix:\u0000sock": {"pass": "routes"}}, 'listeners' - ), 'unix abstract zero unicode' + assert 'error' in self.try_addr("unix:\0soc"), 'abstract \0' + assert 'error' in self.try_addr("unix:\u0000soc"), 'abstract \0 unicode' def test_listeners_addr(self): assert 'success' in self.try_addr("*:7080"), 'wildcard' diff --git a/test/test_go_application.py b/test/test_go_application.py index c8cf3e53..a746c6f4 100644 --- a/test/test_go_application.py +++ b/test/test_go_application.py @@ -95,7 +95,6 @@ class TestGoApplication(TestApplicationGo): headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -105,16 +104,7 @@ class TestGoApplication(TestApplicationGo): assert resp['body'] == body, 'keep-alive 1' body = '0123456789' - resp = self.post( - headers={ - 'Host': 'localhost', - 'Content-Type': 'text/html', - 'Connection': 'close', - }, - sock=sock, - body=body, - ) - + resp = self.post(sock=sock, body=body) assert resp['body'] == body, 'keep-alive 2' def test_go_application_cookies(self): diff --git a/test/test_node_application.py b/test/test_node_application.py index fc722582..c26c72d0 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -124,7 +124,6 @@ class TestNodeApplication(TestApplicationNode): headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -134,15 +133,7 @@ class TestNodeApplication(TestApplicationNode): assert resp['body'] == '0123456789' * 500, 'keep-alive 1' body = '0123456789' - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=sock, - body=body, - ) + resp = self.post(sock=sock, body=body) assert resp['body'] == body, 'keep-alive 2' diff --git a/test/test_php_application.py b/test/test_php_application.py index 606ac723..f1dcc995 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -226,7 +226,6 @@ opcache.preload_user = %(user)s headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -236,15 +235,7 @@ opcache.preload_user = %(user)s assert resp['body'] == body, 'keep-alive 1' body = '0123456789' - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=sock, - body=body, - ) + resp = self.post(sock=sock, body=body) assert resp['body'] == body, 'keep-alive 2' diff --git a/test/test_proxy.py b/test/test_proxy.py index 68ae2394..b0d471e4 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -370,7 +370,6 @@ Content-Length: 10 resp = self.post_http10( headers={ 'Host': 'localhost', - 'Content-Type': 'text/html', 'Content-Length': str(len(body)), 'X-Parts': '2', 'X-Delay': '1', @@ -384,7 +383,6 @@ Content-Length: 10 resp = self.post_http10( headers={ 'Host': 'localhost', - 'Content-Type': 'text/html', 'Content-Length': str(len(body)), 'X-Parts': '2', 'X-Delay': '1', @@ -403,7 +401,6 @@ Content-Length: 10 _, sock = self.post_http10( headers={ 'Host': 'localhost', - 'Content-Type': 'text/html', 'Content-Length': '10000', 'X-Parts': '3', 'X-Delay': '1', @@ -419,7 +416,6 @@ Content-Length: 10 _, sock = self.post_http10( headers={ 'Host': 'localhost', - 'Content-Type': 'text/html', 'Content-Length': '10000', 'X-Parts': '3', 'X-Delay': '1', diff --git a/test/test_python_application.py b/test/test_python_application.py index befbd4d8..2ea9a22e 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -138,14 +138,7 @@ custom-header: BLAH def test_python_application_ctx_iter_atexit(self): self.load('ctx_iter_atexit') - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - body='0123456789', - ) + resp = self.post(body='0123456789') assert resp['status'] == 200, 'ctx iter status' assert resp['body'] == '0123456789', 'ctx iter body' @@ -166,7 +159,6 @@ custom-header: BLAH headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -176,15 +168,7 @@ custom-header: BLAH assert resp['body'] == body, 'keep-alive 1' body = '0123456789' - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=sock, - body=body, - ) + resp = self.post(sock=sock, body=body) assert resp['body'] == body, 'keep-alive 2' @@ -202,7 +186,6 @@ custom-header: BLAH headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -220,7 +203,6 @@ custom-header: BLAH headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, sock=socks[i], @@ -233,15 +215,7 @@ custom-header: BLAH self.load('mirror', processes=i + 1) for i in range(conns): - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=socks[i], - body=body, - ) + resp = self.post(sock=socks[i], body=body) assert resp['body'] == body, 'keep-alive close' @@ -258,7 +232,6 @@ custom-header: BLAH headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -271,16 +244,7 @@ custom-header: BLAH assert self.get()['status'] == 200, 'init' - (resp, sock) = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - start=True, - sock=sock, - body=body, - ) + (resp, sock) = self.post(start=True, sock=sock, body=body) assert resp['status'] == 200, 'reconfigure 2 keep-alive 2' assert resp['body'] == '', 'reconfigure 2 keep-alive 2 body' diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index b3e02406..83af39be 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -347,7 +347,6 @@ class TestRubyApplication(TestApplicationRuby): headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body=body, @@ -357,15 +356,7 @@ class TestRubyApplication(TestApplicationRuby): assert resp['body'] == body, 'keep-alive 1' body = '0123456789' - resp = self.post( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=sock, - body=body, - ) + resp = self.post(sock=sock, body=body) assert resp['body'] == body, 'keep-alive 2' diff --git a/test/test_tls.py b/test/test_tls.py index 3fa5dabf..d4edcbd3 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -505,7 +505,6 @@ basicConstraints = critical,CA:TRUE""" headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body='0123456789', @@ -518,7 +517,6 @@ basicConstraints = critical,CA:TRUE""" headers={ 'Host': 'localhost', 'Connection': 'close', - 'Content-Type': 'text/html', }, sock=sock, body='0123456789', @@ -570,9 +568,7 @@ basicConstraints = critical,CA:TRUE""" assert 'success' in self.conf_delete('/certificates/default') try: - resp = self.get_ssl( - headers={'Host': 'localhost', 'Connection': 'close'}, sock=sock - ) + resp = self.get_ssl(sock=sock) except KeyboardInterrupt: raise @@ -605,7 +601,6 @@ basicConstraints = critical,CA:TRUE""" headers={ 'Host': 'localhost', 'Connection': 'keep-alive', - 'Content-Type': 'text/html', }, start=True, body='0123456789', @@ -622,15 +617,7 @@ basicConstraints = critical,CA:TRUE""" r' (?!' + app_id + r'#)(\d+)#\d+ "mirror" application started' ) - resp = self.post_ssl( - headers={ - 'Host': 'localhost', - 'Connection': 'close', - 'Content-Type': 'text/html', - }, - sock=sock, - body='0123456789', - ) + resp = self.post_ssl(sock=sock, body='0123456789') assert resp['status'] == 200, 'application respawn status' assert resp['body'] == '0123456789', 'application respawn body' -- cgit From 97124fc349a0deae49ef547f65636b8bb1333ecd Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Tue, 21 Jun 2022 15:04:19 +0400 Subject: Packaging: removed support for SLES and derivatives. The packages were never built for those OSes. --- pkg/rpm/Makefile | 33 -------------------------- pkg/rpm/Makefile.go | 11 --------- pkg/rpm/Makefile.perl | 4 ---- pkg/rpm/Makefile.php | 4 ---- pkg/rpm/Makefile.python27 | 4 +--- pkg/rpm/Makefile.python310 | 2 +- pkg/rpm/Makefile.python34 | 57 --------------------------------------------- pkg/rpm/Makefile.python36 | 2 +- pkg/rpm/Makefile.python37 | 2 +- pkg/rpm/Makefile.python39 | 2 +- pkg/rpm/Makefile.ruby | 6 ----- pkg/rpm/unit.module.spec.in | 11 --------- pkg/rpm/unit.spec.in | 11 --------- 13 files changed, 5 insertions(+), 144 deletions(-) delete mode 100644 pkg/rpm/Makefile.python34 diff --git a/pkg/rpm/Makefile b/pkg/rpm/Makefile index a6b2955b..bbe44fe5 100644 --- a/pkg/rpm/Makefile +++ b/pkg/rpm/Makefile @@ -18,12 +18,6 @@ else ifeq ($(shell rpm --eval "%{?rhel}"), 9) OSVER = centos9 else ifeq ($(shell rpm --eval "%{?amzn}"), 2) OSVER = amazonlinux2 -else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1315 -a 0%{?suse_version} -lt 1330 -a 0%{?is_opensuse} -eq 1'`; echo $$?), 0) -OSVER = opensuse-leap -else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1330 -a 0%{?is_opensuse} -eq 1'`; echo $$?), 0) -OSVER = opensuse-tumbleweed -else ifeq ($(shell test `rpm --eval '0%{?suse_version} -ge 1315 -a 0%{?is_opensuse} -eq 0'`; echo $$?), 0) -OSVER = sles else ifeq ($(shell test `rpm --eval '0%{?fedora} -ge 35'`; echo $$?),0) OSVER = fedora endif @@ -34,15 +28,11 @@ ifeq ($(OSVER), centos7) BUILD_DEPENDS_unit += which endif -ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed sles)) -BUILD_DEPENDS_unit += libxml2-tools libxslt1 libopenssl-devel -else ifneq (,$(findstring $(OSVER),amazonlinux2)) BUILD_DEPENDS_unit += libxml2 libxslt openssl11-devel else BUILD_DEPENDS_unit += libxml2 libxslt openssl-devel endif -endif BUILD_DEPENDS = $(BUILD_DEPENDS_unit) @@ -90,29 +80,6 @@ include Makefile.jsc-common include Makefile.jsc8 endif -ifeq ($(OSVER), opensuse-leap) -include Makefile.python27 -include Makefile.python34 -include Makefile.go -include Makefile.perl -include Makefile.ruby -endif - -ifeq ($(OSVER), opensuse-tumbleweed) -include Makefile.php -include Makefile.python27 -include Makefile.python36 -include Makefile.go -include Makefile.perl -include Makefile.ruby -endif - -ifeq ($(OSVER), sles) -include Makefile.python27 -include Makefile.python34 -include Makefile.perl -endif - ifeq ($(OSVER), fedora) include Makefile.php include Makefile.python310 diff --git a/pkg/rpm/Makefile.go b/pkg/rpm/Makefile.go index a1421bee..aacbe2b9 100644 --- a/pkg/rpm/Makefile.go +++ b/pkg/rpm/Makefile.go @@ -15,28 +15,17 @@ MODULE_SOURCES_go= unit.example-go-app \ ifeq ($(OSVER), centos6) BUILD_DEPENDS_go= epel-release golang -else ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed)) -BUILD_DEPENDS_go= go1.9 else BUILD_DEPENDS_go= golang endif BUILD_DEPENDS+= $(BUILD_DEPENDS_go) -ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed)) define MODULE_DEFINITIONS_go BuildArch: noarch Requires: unit-devel == $(VERSION)-$(RELEASE)%{?dist}.ngx BuildRequires: $(BUILD_DEPENDS_go) -%define gopath /usr/share/go/contrib endef -else -define MODULE_DEFINITIONS_go -BuildArch: noarch -Requires: unit-devel == $(VERSION)-$(RELEASE)%{?dist}.ngx -BuildRequires: $(BUILD_DEPENDS_go) -endef -endif export MODULE_DEFINITIONS_go define MODULE_PREINSTALL_go diff --git a/pkg/rpm/Makefile.perl b/pkg/rpm/Makefile.perl index f59b7353..92440cfa 100644 --- a/pkg/rpm/Makefile.perl +++ b/pkg/rpm/Makefile.perl @@ -13,11 +13,7 @@ MODULE_INSTARGS_perl= perl-install MODULE_SOURCES_perl= unit.example-perl-app \ unit.example-perl-config -ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed sles)) -BUILD_DEPENDS_perl= perl -else BUILD_DEPENDS_perl= perl-devel perl-libs perl-ExtUtils-Embed -endif BUILD_DEPENDS+= $(BUILD_DEPENDS_perl) diff --git a/pkg/rpm/Makefile.php b/pkg/rpm/Makefile.php index 8f39efc0..0f5a10e5 100644 --- a/pkg/rpm/Makefile.php +++ b/pkg/rpm/Makefile.php @@ -13,11 +13,7 @@ MODULE_INSTARGS_php= php-install MODULE_SOURCES_php= unit.example-php-app \ unit.example-php-config -ifeq ($(OSVER), opensuse-tumbleweed) -BUILD_DEPENDS_php= php7-devel php7-embed -else BUILD_DEPENDS_php= php-devel php-embedded -endif BUILD_DEPENDS+= $(BUILD_DEPENDS_php) diff --git a/pkg/rpm/Makefile.python27 b/pkg/rpm/Makefile.python27 index 079a8512..3de5f634 100644 --- a/pkg/rpm/Makefile.python27 +++ b/pkg/rpm/Makefile.python27 @@ -13,9 +13,7 @@ MODULE_INSTARGS_python27= python2.7-install MODULE_SOURCES_python27= unit.example-python-app \ unit.example-python27-config -ifneq (,$(findstring $(OSVER),opensuse-leap opensuse-tumbleweed sles)) -BUILD_DEPENDS_python27= python-devel -else ifneq (,$(findstring $(OSVER),fedora centos8)) +ifneq (,$(findstring $(OSVER),fedora centos8)) BUILD_DEPENDS_python27= python2-devel else ifneq (,$(findstring $(OSVER),centos7 amazonlinux2)) BUILD_DEPENDS_python27= python-devel diff --git a/pkg/rpm/Makefile.python310 b/pkg/rpm/Makefile.python310 index 82bc311a..50731475 100644 --- a/pkg/rpm/Makefile.python310 +++ b/pkg/rpm/Makefile.python310 @@ -13,7 +13,7 @@ MODULE_INSTARGS_python310= python3.10-install MODULE_SOURCES_python310= unit.example-python-app \ unit.example-python310-config -ifneq (,$(findstring $(OSVER),opensuse-tumbleweed sles fedora amazonlinux2)) +ifneq (,$(findstring $(OSVER),fedora amazonlinux2)) BUILD_DEPENDS_python310= python3-devel else BUILD_DEPENDS_python310= python310-devel diff --git a/pkg/rpm/Makefile.python34 b/pkg/rpm/Makefile.python34 deleted file mode 100644 index 83c0bdb6..00000000 --- a/pkg/rpm/Makefile.python34 +++ /dev/null @@ -1,57 +0,0 @@ -MODULES+= python34 -MODULE_SUFFIX_python34= python3.4 - -MODULE_SUMMARY_python34= Python 3.4 module for NGINX Unit - -MODULE_VERSION_python34= $(VERSION) -MODULE_RELEASE_python34= 1 - -MODULE_CONFARGS_python34= python --config=python3.4-config -MODULE_MAKEARGS_python34= python3.4 -MODULE_INSTARGS_python34= python3.4-install - -MODULE_SOURCES_python34= unit.example-python-app \ - unit.example-python34-config - -ifneq (,$(findstring $(OSVER),opensuse-leap sles)) -BUILD_DEPENDS_python34= python3-devel -else -BUILD_DEPENDS_python34= python34-devel -endif - -BUILD_DEPENDS+= $(BUILD_DEPENDS_python34) - -define MODULE_PREINSTALL_python34 -%{__mkdir} -p %{buildroot}%{_datadir}/doc/unit-python34/examples/python-app -%{__install} -m 644 -p %{SOURCE100} \ - %{buildroot}%{_datadir}/doc/unit-python34/examples/python-app/wsgi.py -%{__install} -m 644 -p %{SOURCE101} \ - %{buildroot}%{_datadir}/doc/unit-python34/examples/unit.config -endef -export MODULE_PREINSTALL_python34 - -define MODULE_FILES_python34 -%{_libdir}/unit/modules/* -%{_libdir}/unit/debug-modules/* -endef -export MODULE_FILES_python34 - -define MODULE_POST_python34 -cat <= 1315 -BuildRequires: libopenssl-devel -%endif - %define unit_version %%UNIT_VERSION%% %define unit_release %%UNIT_RELEASE%%%{?dist}.ngx @@ -54,10 +50,6 @@ directly in the cloud / container environments and fully control your app dynamically via an API. This package contains %%SUMMARY%%. -%if 0%{?suse_version} -%debug_package -%endif - %if (0%{?fedora}) || (0%{?rhel} >= 8) %define _debugsource_template %{nil} %endif @@ -106,9 +98,6 @@ DESTDIR=%{buildroot} make %%MODULE_INSTARGS%% cd %{bdir} grep -v 'usr/src' debugfiles.list > debugfiles.list.new && mv debugfiles.list.new debugfiles.list cat /dev/null > debugsources.list -%if 0%{?suse_version} >= 1500 -cat /dev/null > debugsourcefiles.list -%endif %clean %{__rm} -rf %{buildroot} diff --git a/pkg/rpm/unit.spec.in b/pkg/rpm/unit.spec.in index a9f47e9d..01c08bb8 100644 --- a/pkg/rpm/unit.spec.in +++ b/pkg/rpm/unit.spec.in @@ -17,10 +17,6 @@ BuildRequires: openssl-devel %endif %endif -%if 0%{?suse_version} >= 1315 -BuildRequires: libopenssl-devel -%endif - %define CC_OPT %{optflags} -fPIC %define LD_OPT -Wl,-z,relro -Wl,-z,now -pie @@ -59,10 +55,6 @@ in and out of the application. Take this application server and proxy directly in the cloud / container environments and fully control your app dynamically via an API. -%if 0%{?suse_version} -%debug_package -%endif - %if (0%{?fedora}) || (0%{?rhel} >= 8) %define _debugsource_template %{nil} %endif @@ -142,9 +134,6 @@ cd %{bdir} && make tests && ./build/tests cd %{bdir} grep -v 'usr/src' debugfiles.list > debugfiles.list.new && mv debugfiles.list.new debugfiles.list cat /dev/null > debugsources.list -%if 0%{?suse_version} >= 1500 -cat /dev/null > debugsourcefiles.list -%endif %clean %{__rm} -rf %{buildroot} -- cgit From 38350c17fcfa0392c995688fd87bbd34d1ba374f Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Fri, 9 Sep 2022 16:17:42 +0400 Subject: Docker: bumped language versions, moved jsc11 to eclipse-temurin. openjdk builds are no longer provided in the docker library due to deprecation. --- pkg/docker/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/docker/Makefile b/pkg/docker/Makefile index 5c48f925..03723d1d 100644 --- a/pkg/docker/Makefile +++ b/pkg/docker/Makefile @@ -18,7 +18,7 @@ INSTALL_minimal ?= version define COPY_minimal endef -VERSION_go ?= 1.18 +VERSION_go ?= 1.19 CONTAINER_go ?= golang:$(VERSION_go) CONFIGURE_go ?= go --go-path=$$GOPATH INSTALL_go ?= go-install-src libunit-install @@ -29,7 +29,7 @@ COPY --from=BUILDER /go/src/ /go/src/ endef VERSION_jsc ?= 11 -CONTAINER_jsc ?= openjdk:$(VERSION_jsc)-jdk +CONTAINER_jsc ?= eclipse-temurin:$(VERSION_jsc)-jdk CONFIGURE_jsc ?= java --jars=/usr/share/unit-jsc-common/ INSTALL_jsc ?= java-shared-install java-install COPY_jsc = COPY --from=BUILDER /usr/share/unit-jsc-common/ /usr/share/unit-jsc-common/ @@ -44,7 +44,7 @@ COPY --from=BUILDER /usr/include/nxt_* /usr/include/\n\$ COPY --from=BUILDER /usr/local/lib/node_modules/unit-http/ /usr/local/lib/node_modules/unit-http/ endef -VERSION_perl ?= 5.34 +VERSION_perl ?= 5.36 CONTAINER_perl ?= perl:$(VERSION_perl) CONFIGURE_perl ?= perl INSTALL_perl ?= perl-install -- cgit From 4924bd185db2c2717bf0ef6d0403c6594c1f7789 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Fri, 9 Sep 2022 17:45:58 +0400 Subject: Regenerated Dockerfiles. --- pkg/docker/Dockerfile.go1.18 | 79 ------------------------------------------ pkg/docker/Dockerfile.go1.19 | 79 ++++++++++++++++++++++++++++++++++++++++++ pkg/docker/Dockerfile.jsc11 | 4 +-- pkg/docker/Dockerfile.perl5.34 | 77 ---------------------------------------- pkg/docker/Dockerfile.perl5.36 | 77 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 158 deletions(-) delete mode 100644 pkg/docker/Dockerfile.go1.18 create mode 100644 pkg/docker/Dockerfile.go1.19 delete mode 100644 pkg/docker/Dockerfile.perl5.34 create mode 100644 pkg/docker/Dockerfile.perl5.36 diff --git a/pkg/docker/Dockerfile.go1.18 b/pkg/docker/Dockerfile.go1.18 deleted file mode 100644 index 9162d8cf..00000000 --- a/pkg/docker/Dockerfile.go1.18 +++ /dev/null @@ -1,79 +0,0 @@ -FROM golang:1.18 as BUILDER - -LABEL maintainer="NGINX Docker Maintainers " - -RUN set -ex \ - && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates mercurial build-essential libssl-dev libpcre2-dev \ - && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ - && hg clone https://hg.nginx.org/unit \ - && cd unit \ - && hg up 1.27.0 \ - && NCPU="$(getconf _NPROCESSORS_ONLN)" \ - && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ - && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ - && LD_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_LDFLAGS_MAINT_APPEND="-Wl,--as-needed -pie" dpkg-buildflags --get LDFLAGS)" \ - && CONFIGURE_ARGS="--prefix=/usr \ - --state=/var/lib/unit \ - --control=unix:/var/run/control.unit.sock \ - --pid=/var/run/unit.pid \ - --log=/var/log/unit.log \ - --tmp=/var/tmp \ - --user=unit \ - --group=unit \ - --openssl \ - --libdir=/usr/lib/$DEB_HOST_MULTIARCH" \ - && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/debug-modules --debug \ - && make -j $NCPU unitd \ - && install -pm755 build/unitd /usr/sbin/unitd-debug \ - && make clean \ - && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/modules \ - && make -j $NCPU unitd \ - && install -pm755 build/unitd /usr/sbin/unitd \ - && make clean \ - && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/debug-modules --debug \ - && ./configure go --go-path=$GOPATH \ - && make -j $NCPU go-install-src libunit-install \ - && make clean \ - && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/modules \ - && ./configure go --go-path=$GOPATH \ - && make -j $NCPU go-install-src libunit-install \ - && ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt - -FROM golang:1.18 -COPY docker-entrypoint.sh /usr/local/bin/ -COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd -COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug -COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ -COPY --from=BUILDER /requirements.apt /requirements.apt -COPY --from=BUILDER /usr/lib/*-linux-gnu/libunit.a /tmp/ -COPY --from=BUILDER /usr/include/nxt_* /usr/include/ -COPY --from=BUILDER /go/src/ /go/src/ -RUN set -x \ - && if [ -f "/tmp/libunit.a" ]; then \ - mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ - rm -f /tmp/libunit.a; \ - fi \ - && mkdir -p /var/lib/unit/ \ - && mkdir /docker-entrypoint.d/ \ - && addgroup --system unit \ - && adduser \ - --system \ - --disabled-login \ - --ingroup unit \ - --no-create-home \ - --home /nonexistent \ - --gecos "unit user" \ - --shell /bin/false \ - unit \ - && apt update \ - && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ - && apt-get clean && rm -rf /var/lib/apt/lists/* \ - && rm -f /requirements.apt \ - && ln -sf /dev/stdout /var/log/unit.log - -STOPSIGNAL SIGTERM - -ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] - -CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"] diff --git a/pkg/docker/Dockerfile.go1.19 b/pkg/docker/Dockerfile.go1.19 new file mode 100644 index 00000000..d911e76f --- /dev/null +++ b/pkg/docker/Dockerfile.go1.19 @@ -0,0 +1,79 @@ +FROM golang:1.19 as BUILDER + +LABEL maintainer="NGINX Docker Maintainers " + +RUN set -ex \ + && apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates mercurial build-essential libssl-dev libpcre2-dev \ + && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ + && hg clone https://hg.nginx.org/unit \ + && cd unit \ + && hg up 1.27.0 \ + && NCPU="$(getconf _NPROCESSORS_ONLN)" \ + && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ + && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ + && LD_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_LDFLAGS_MAINT_APPEND="-Wl,--as-needed -pie" dpkg-buildflags --get LDFLAGS)" \ + && CONFIGURE_ARGS="--prefix=/usr \ + --state=/var/lib/unit \ + --control=unix:/var/run/control.unit.sock \ + --pid=/var/run/unit.pid \ + --log=/var/log/unit.log \ + --tmp=/var/tmp \ + --user=unit \ + --group=unit \ + --openssl \ + --libdir=/usr/lib/$DEB_HOST_MULTIARCH" \ + && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/debug-modules --debug \ + && make -j $NCPU unitd \ + && install -pm755 build/unitd /usr/sbin/unitd-debug \ + && make clean \ + && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/modules \ + && make -j $NCPU unitd \ + && install -pm755 build/unitd /usr/sbin/unitd \ + && make clean \ + && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/debug-modules --debug \ + && ./configure go --go-path=$GOPATH \ + && make -j $NCPU go-install-src libunit-install \ + && make clean \ + && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/modules \ + && ./configure go --go-path=$GOPATH \ + && make -j $NCPU go-install-src libunit-install \ + && ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt + +FROM golang:1.19 +COPY docker-entrypoint.sh /usr/local/bin/ +COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd +COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug +COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ +COPY --from=BUILDER /requirements.apt /requirements.apt +COPY --from=BUILDER /usr/lib/*-linux-gnu/libunit.a /tmp/ +COPY --from=BUILDER /usr/include/nxt_* /usr/include/ +COPY --from=BUILDER /go/src/ /go/src/ +RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ + && mkdir -p /var/lib/unit/ \ + && mkdir /docker-entrypoint.d/ \ + && addgroup --system unit \ + && adduser \ + --system \ + --disabled-login \ + --ingroup unit \ + --no-create-home \ + --home /nonexistent \ + --gecos "unit user" \ + --shell /bin/false \ + unit \ + && apt update \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ + && apt-get clean && rm -rf /var/lib/apt/lists/* \ + && rm -f /requirements.apt \ + && ln -sf /dev/stdout /var/log/unit.log + +STOPSIGNAL SIGTERM + +ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] + +CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"] diff --git a/pkg/docker/Dockerfile.jsc11 b/pkg/docker/Dockerfile.jsc11 index 69fc72ad..30a718ba 100644 --- a/pkg/docker/Dockerfile.jsc11 +++ b/pkg/docker/Dockerfile.jsc11 @@ -1,4 +1,4 @@ -FROM openjdk:11-jdk as BUILDER +FROM eclipse-temurin:11-jdk as BUILDER LABEL maintainer="NGINX Docker Maintainers " @@ -40,7 +40,7 @@ RUN set -ex \ && make -j $NCPU java-shared-install java-install \ && ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt -FROM openjdk:11-jdk +FROM eclipse-temurin:11-jdk COPY docker-entrypoint.sh /usr/local/bin/ COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug diff --git a/pkg/docker/Dockerfile.perl5.34 b/pkg/docker/Dockerfile.perl5.34 deleted file mode 100644 index db87d209..00000000 --- a/pkg/docker/Dockerfile.perl5.34 +++ /dev/null @@ -1,77 +0,0 @@ -FROM perl:5.34 as BUILDER - -LABEL maintainer="NGINX Docker Maintainers " - -RUN set -ex \ - && apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates mercurial build-essential libssl-dev libpcre2-dev \ - && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ - && hg clone https://hg.nginx.org/unit \ - && cd unit \ - && hg up 1.27.0 \ - && NCPU="$(getconf _NPROCESSORS_ONLN)" \ - && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ - && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ - && LD_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_LDFLAGS_MAINT_APPEND="-Wl,--as-needed -pie" dpkg-buildflags --get LDFLAGS)" \ - && CONFIGURE_ARGS="--prefix=/usr \ - --state=/var/lib/unit \ - --control=unix:/var/run/control.unit.sock \ - --pid=/var/run/unit.pid \ - --log=/var/log/unit.log \ - --tmp=/var/tmp \ - --user=unit \ - --group=unit \ - --openssl \ - --libdir=/usr/lib/$DEB_HOST_MULTIARCH" \ - && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/debug-modules --debug \ - && make -j $NCPU unitd \ - && install -pm755 build/unitd /usr/sbin/unitd-debug \ - && make clean \ - && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/modules \ - && make -j $NCPU unitd \ - && install -pm755 build/unitd /usr/sbin/unitd \ - && make clean \ - && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/debug-modules --debug \ - && ./configure perl \ - && make -j $NCPU perl-install \ - && make clean \ - && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/modules \ - && ./configure perl \ - && make -j $NCPU perl-install \ - && ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt - -FROM perl:5.34 -COPY docker-entrypoint.sh /usr/local/bin/ -COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd -COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug -COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ -COPY --from=BUILDER /requirements.apt /requirements.apt - -RUN set -x \ - && if [ -f "/tmp/libunit.a" ]; then \ - mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ - rm -f /tmp/libunit.a; \ - fi \ - && mkdir -p /var/lib/unit/ \ - && mkdir /docker-entrypoint.d/ \ - && addgroup --system unit \ - && adduser \ - --system \ - --disabled-login \ - --ingroup unit \ - --no-create-home \ - --home /nonexistent \ - --gecos "unit user" \ - --shell /bin/false \ - unit \ - && apt update \ - && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ - && apt-get clean && rm -rf /var/lib/apt/lists/* \ - && rm -f /requirements.apt \ - && ln -sf /dev/stdout /var/log/unit.log - -STOPSIGNAL SIGTERM - -ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] - -CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"] diff --git a/pkg/docker/Dockerfile.perl5.36 b/pkg/docker/Dockerfile.perl5.36 new file mode 100644 index 00000000..56c73c51 --- /dev/null +++ b/pkg/docker/Dockerfile.perl5.36 @@ -0,0 +1,77 @@ +FROM perl:5.36 as BUILDER + +LABEL maintainer="NGINX Docker Maintainers " + +RUN set -ex \ + && apt-get update \ + && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates mercurial build-essential libssl-dev libpcre2-dev \ + && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ + && hg clone https://hg.nginx.org/unit \ + && cd unit \ + && hg up 1.27.0 \ + && NCPU="$(getconf _NPROCESSORS_ONLN)" \ + && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ + && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ + && LD_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_LDFLAGS_MAINT_APPEND="-Wl,--as-needed -pie" dpkg-buildflags --get LDFLAGS)" \ + && CONFIGURE_ARGS="--prefix=/usr \ + --state=/var/lib/unit \ + --control=unix:/var/run/control.unit.sock \ + --pid=/var/run/unit.pid \ + --log=/var/log/unit.log \ + --tmp=/var/tmp \ + --user=unit \ + --group=unit \ + --openssl \ + --libdir=/usr/lib/$DEB_HOST_MULTIARCH" \ + && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/debug-modules --debug \ + && make -j $NCPU unitd \ + && install -pm755 build/unitd /usr/sbin/unitd-debug \ + && make clean \ + && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modules=/usr/lib/unit/modules \ + && make -j $NCPU unitd \ + && install -pm755 build/unitd /usr/sbin/unitd \ + && make clean \ + && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/debug-modules --debug \ + && ./configure perl \ + && make -j $NCPU perl-install \ + && make clean \ + && ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --modules=/usr/lib/unit/modules \ + && ./configure perl \ + && make -j $NCPU perl-install \ + && ldd /usr/sbin/unitd | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq > /requirements.apt + +FROM perl:5.36 +COPY docker-entrypoint.sh /usr/local/bin/ +COPY --from=BUILDER /usr/sbin/unitd /usr/sbin/unitd +COPY --from=BUILDER /usr/sbin/unitd-debug /usr/sbin/unitd-debug +COPY --from=BUILDER /usr/lib/unit/ /usr/lib/unit/ +COPY --from=BUILDER /requirements.apt /requirements.apt + +RUN set -x \ + && if [ -f "/tmp/libunit.a" ]; then \ + mv /tmp/libunit.a /usr/lib/$(dpkg-architecture -q DEB_HOST_MULTIARCH)/libunit.a; \ + rm -f /tmp/libunit.a; \ + fi \ + && mkdir -p /var/lib/unit/ \ + && mkdir /docker-entrypoint.d/ \ + && addgroup --system unit \ + && adduser \ + --system \ + --disabled-login \ + --ingroup unit \ + --no-create-home \ + --home /nonexistent \ + --gecos "unit user" \ + --shell /bin/false \ + unit \ + && apt update \ + && apt --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \ + && apt-get clean && rm -rf /var/lib/apt/lists/* \ + && rm -f /requirements.apt \ + && ln -sf /dev/stdout /var/log/unit.log + +STOPSIGNAL SIGTERM + +ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] + +CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"] -- cgit From 558a5d3e892dab4690c9f980b3e175ac26e4e077 Mon Sep 17 00:00:00 2001 From: Alex Colomar Date: Fri, 9 Sep 2022 13:40:17 +0100 Subject: Fixed a mutex leak in the C API. In nxt_unit_create() we could leak a mutex created in nxt_unit_ctx_init(). This could happen if nxt_unit_ctx_init() succeeded but later on we bailed out of nxt_unit_create(), we would destroy the mutex created in nxt_unit_create() but not the one created in nxt_unit_ctx_init(). Reorder things so that we do the call to nxt_unit_create() after all the other checks so if it fails we don't leak the mutex it created. Co-developed-by: Andrew Clayton Signed-off-by: Andrew Clayton Signed-off-by: Alex Colomar --- docs/changes.xml | 6 ++++++ src/nxt_unit.c | 20 ++++++++------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 989001dd..0175fd33 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -122,6 +122,12 @@ the prototype crashed. + + +mutex leak in the C API. + + + diff --git a/src/nxt_unit.c b/src/nxt_unit.c index fd086b2c..e5cb0b58 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -585,9 +585,14 @@ fail: static nxt_unit_impl_t * nxt_unit_create(nxt_unit_init_t *init) { - int rc; - nxt_unit_impl_t *lib; - nxt_unit_callbacks_t *cb; + int rc; + nxt_unit_impl_t *lib; + + if (nxt_slow_path(init->callbacks.request_handler == NULL)) { + nxt_unit_alert(NULL, "request_handler is NULL"); + + return NULL; + } lib = nxt_unit_malloc(NULL, sizeof(nxt_unit_impl_t) + init->request_data_size); @@ -630,15 +635,6 @@ nxt_unit_create(nxt_unit_init_t *init) goto fail; } - cb = &lib->callbacks; - - if (cb->request_handler == NULL) { - nxt_unit_alert(NULL, "request_handler is NULL"); - - pthread_mutex_destroy(&lib->mutex); - goto fail; - } - nxt_unit_mmaps_init(&lib->incoming); nxt_unit_mmaps_init(&lib->outgoing); -- cgit From ac5c0f1f03ccde7d3354951e2f0c2c2ddd88a757 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 13 Sep 2022 00:31:32 +0100 Subject: Capitalize "HTTP" in "changes.xml" to match common style. --- docs/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changes.xml b/docs/changes.xml index 0175fd33..38b57ba5 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -69,7 +69,7 @@ ability to get dynamic variables. -more http variables support. +more HTTP variables support. -- cgit From ff9054af10fe439e3ad159e2570a789db9c0cb80 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 13 Sep 2022 09:16:55 +0100 Subject: Reordered changes for 1.28.0 by significance (subjective). --- docs/changes.xml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/changes.xml b/docs/changes.xml index 38b57ba5..3674c650 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -45,49 +45,49 @@ disallowed abstract Unix domain socket syntax in non-Linux systems. -support for abstract Unix sockets. +basic statistics API. -support for Unix sockets in address matching. +customizable access log format. -forwarded header to replace client address and protocol. +more HTTP variables support. -ability to get dynamic variables. +forwarded header to replace client address and protocol. -more HTTP variables support. +ability to get dynamic variables. -the $dollar variable translates to a literal "$" during variable substitution. +support for abstract Unix sockets. -customizable access log format. +support for Unix sockets in address matching. -basic statistics API. +the $dollar variable translates to a literal "$" during variable substitution. @@ -105,20 +105,20 @@ force SCRIPT_NAME in Ruby to always be an empty string. -the Ruby application process could crash on SIGTERM. +when isolated PID numbers reach the prototype process host PID, +the prototype crashed. -the Ruby application process could crash on SIGINT. +the Ruby application process could crash on SIGTERM. -when isolated PID numbers reach the prototype process host PID, -the prototype crashed. +the Ruby application process could crash on SIGINT. -- cgit From a03894df61d679847c6dae4617b8e21511f71785 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 13 Sep 2022 09:27:13 +0100 Subject: Added version 1.28.0 CHANGES. --- CHANGES | 39 +++++++++++++++++++++++++++++++++++++++ docs/changes.xml | 4 ++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 98208fa9..29cd3301 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,43 @@ +Changes with Unit 1.28.0 13 Sep 2022 + + *) Change: increased the applications' startup timeout. + + *) Change: disallowed abstract Unix domain socket syntax in non-Linux + systems. + + *) Feature: basic statistics API. + + *) Feature: customizable access log format. + + *) Feature: more HTTP variables support. + + *) Feature: forwarded header to replace client address and protocol. + + *) Feature: ability to get dynamic variables. + + *) Feature: support for abstract Unix sockets. + + *) Feature: support for Unix sockets in address matching. + + *) Feature: the $dollar variable translates to a literal "$" during + variable substitution. + + *) Bugfix: router process could crash if index file didn't contain an + extension. + + *) Bugfix: force SCRIPT_NAME in Ruby to always be an empty string. + + *) Bugfix: when isolated PID numbers reach the prototype process host + PID, the prototype crashed. + + *) Bugfix: the Ruby application process could crash on SIGTERM. + + *) Bugfix: the Ruby application process could crash on SIGINT. + + *) Bugfix: mutex leak in the C API. + + Changes with Unit 1.27.0 02 Jun 2022 *) Feature: ability to specify a custom index file name when serving diff --git a/docs/changes.xml b/docs/changes.xml index 3674c650..391ff2fb 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -15,7 +15,7 @@ unit-jsc-common unit-jsc8 unit-jsc10 unit-jsc11 unit-jsc13 unit-jsc14 unit-jsc15 unit-jsc16 unit-jsc17 unit-jsc18" ver="1.28.0" rev="1" - date="" time="" + date="2022-09-13" time="18:00:00 +0300" packager="Nginx Packaging <nginx-packaging@f5.com>"> @@ -28,7 +28,7 @@ NGINX Unit updated to 1.28.0. -- cgit From 38bd7e76a134084ab95a4ee3125af1ccd7b35864 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 13 Sep 2022 07:26:26 +0800 Subject: Generated Dockerfiles for Unit 1.28.0. --- pkg/docker/Dockerfile.go1.19 | 2 +- pkg/docker/Dockerfile.jsc11 | 2 +- pkg/docker/Dockerfile.minimal | 2 +- pkg/docker/Dockerfile.node16 | 2 +- pkg/docker/Dockerfile.perl5.36 | 2 +- pkg/docker/Dockerfile.php8.1 | 2 +- pkg/docker/Dockerfile.python3.10 | 2 +- pkg/docker/Dockerfile.ruby3.1 | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/docker/Dockerfile.go1.19 b/pkg/docker/Dockerfile.go1.19 index d911e76f..1625b64f 100644 --- a/pkg/docker/Dockerfile.go1.19 +++ b/pkg/docker/Dockerfile.go1.19 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.27.0 \ + && hg up 1.28.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ diff --git a/pkg/docker/Dockerfile.jsc11 b/pkg/docker/Dockerfile.jsc11 index 30a718ba..fe344d0e 100644 --- a/pkg/docker/Dockerfile.jsc11 +++ b/pkg/docker/Dockerfile.jsc11 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.27.0 \ + && hg up 1.28.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ diff --git a/pkg/docker/Dockerfile.minimal b/pkg/docker/Dockerfile.minimal index 730e1893..c57379f7 100644 --- a/pkg/docker/Dockerfile.minimal +++ b/pkg/docker/Dockerfile.minimal @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.27.0 \ + && hg up 1.28.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ diff --git a/pkg/docker/Dockerfile.node16 b/pkg/docker/Dockerfile.node16 index 246105d8..d341e43f 100644 --- a/pkg/docker/Dockerfile.node16 +++ b/pkg/docker/Dockerfile.node16 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.27.0 \ + && hg up 1.28.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ diff --git a/pkg/docker/Dockerfile.perl5.36 b/pkg/docker/Dockerfile.perl5.36 index 56c73c51..d0b8006f 100644 --- a/pkg/docker/Dockerfile.perl5.36 +++ b/pkg/docker/Dockerfile.perl5.36 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.27.0 \ + && hg up 1.28.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ diff --git a/pkg/docker/Dockerfile.php8.1 b/pkg/docker/Dockerfile.php8.1 index 5c18a9bc..c63e708e 100644 --- a/pkg/docker/Dockerfile.php8.1 +++ b/pkg/docker/Dockerfile.php8.1 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.27.0 \ + && hg up 1.28.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ diff --git a/pkg/docker/Dockerfile.python3.10 b/pkg/docker/Dockerfile.python3.10 index 09e7f42a..6502f8a8 100644 --- a/pkg/docker/Dockerfile.python3.10 +++ b/pkg/docker/Dockerfile.python3.10 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.27.0 \ + && hg up 1.28.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ diff --git a/pkg/docker/Dockerfile.ruby3.1 b/pkg/docker/Dockerfile.ruby3.1 index 0baedc32..f365bc96 100644 --- a/pkg/docker/Dockerfile.ruby3.1 +++ b/pkg/docker/Dockerfile.ruby3.1 @@ -8,7 +8,7 @@ RUN set -ex \ && mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \ && hg clone https://hg.nginx.org/unit \ && cd unit \ - && hg up 1.27.0 \ + && hg up 1.28.0 \ && NCPU="$(getconf _NPROCESSORS_ONLN)" \ && DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \ && CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \ -- cgit