From 76df62a6236eba2ae1ea7ffe7b9599418b044a01 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 19 Sep 2022 02:45:44 +0800 Subject: HTTP: fixed cookie parsing. The fixing supports the cookie value with the '=' character. This is related to #756 PR on Github. Thanks to changxiaocui. --- src/nxt_http_request.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 943ad82d..7a790f73 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -1035,14 +1035,11 @@ nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, const u_char *end) for (p = start; p < end; p++) { c = *p; - if (c == '=') { + if (c == '=' && name == NULL) { while (start[0] == ' ') { start++; } name_length = p - start; - - if (name_length != 0) { - name = start; - } + name = start; start = p + 1; -- cgit From 0711101af826cf7f5cb25050587ac6788ac0451c Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 22 Sep 2022 01:01:18 +0800 Subject: Status: fixed error in connection statistics. When proxy is used, the number of accepted connections is not counted, This also results in the wrong number of active connections. --- src/nxt_conn.h | 3 +-- src/nxt_conn_close.c | 8 ++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nxt_conn.h b/src/nxt_conn.h index 8a703e9a..5717d3c9 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -312,8 +312,7 @@ NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task, \ nxt_queue_remove(&c->link); \ \ - c->idle = 0; \ - e->idle_conns_cnt--; \ + e->idle_conns_cnt -= c->idle; \ } while (0) diff --git a/src/nxt_conn_close.c b/src/nxt_conn_close.c index 92bd8d1b..bdd66951 100644 --- a/src/nxt_conn_close.c +++ b/src/nxt_conn_close.c @@ -119,7 +119,9 @@ 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 (c->idle) { + engine->closed_conns_cnt++; + } if (timers_pending == 0) { nxt_work_queue_add(&engine->fast_work_queue, @@ -155,7 +157,9 @@ nxt_conn_close_timer_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 (c->idle) { + engine->closed_conns_cnt++; + } } nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, -- cgit From 57fc9201cb91e3d8901a64e3daaaf31684ee5bf5 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Sun, 7 Aug 2022 00:19:24 +0100 Subject: Socket: Created control socket & pid file directories. @alejandro-colomar reported an issue on GitHub whereby Unit would fail to start due to not being able to create the control socket (a Unix Domain Socket) 2022/08/05 20:12:22 [alert] 21613#21613 bind(6, unix:/opt/local/unit/var/run/unit/control.unit.sock.tmp) failed (2: No such file or directory) This could happen if the control socket was set to a directory that doesn't exist. A common place to put the control socket would be under /run/unit, and while /run will exist, /run/unit may well not (/run is/should be cleared on each boot). The pid file would also generally go under /run/unit, though this is created after the control socket, however it could go someplace else so we should also ensure its directory exists. This commit will try to create the pid file and control sockets parent directory. In some cases the user will need to ensure that the rest of the path already exists. This adds a new nxt_fs_mkdir_parent() function that given a full path to a file (or directory), strips the last component off before passing the remaining directory path to nxt_fs_mkdir(). Cc: Konstantin Pavlov Closes: Reported-by: Alejandro Colomar Reviewed-by: Alejandro Colomar Tested-by: Alejandro Colomar Signed-off-by: Andrew Clayton --- src/nxt_controller.c | 8 ++++++++ src/nxt_fs.c | 25 +++++++++++++++++++++++++ src/nxt_fs.h | 1 + src/nxt_runtime.c | 2 ++ 4 files changed, 36 insertions(+) (limited to 'src') diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 09168821..99c7ca10 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -666,6 +666,14 @@ nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) #endif ls->handler = nxt_controller_conn_init; +#if (NXT_HAVE_UNIX_DOMAIN) + if (ls->sockaddr->u.sockaddr.sa_family == AF_UNIX) { + const char *path = ls->sockaddr->u.sockaddr_un.sun_path; + + nxt_fs_mkdir_parent((const u_char *) path, 0755); + } +#endif + if (nxt_listen_socket_create(task, rt->mem_pool, ls) != NXT_OK) { return NXT_ERROR; } diff --git a/src/nxt_fs.c b/src/nxt_fs.c index 71498f99..35850798 100644 --- a/src/nxt_fs.c +++ b/src/nxt_fs.c @@ -273,6 +273,31 @@ nxt_fs_mkdir_all(const u_char *dir, mode_t mode) } +nxt_int_t +nxt_fs_mkdir_parent(const u_char *path, mode_t mode) +{ + char *ptr, *dir; + nxt_int_t ret; + + dir = nxt_strdup(path); + if (nxt_slow_path(dir == NULL)) { + return NXT_ERROR; + } + + ret = NXT_OK; + + ptr = strrchr(dir, '/'); + if (nxt_fast_path(ptr != NULL)) { + *ptr = '\0'; + ret = nxt_fs_mkdir((const u_char *) dir, mode); + } + + nxt_free(dir); + + return ret; +} + + static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode) { diff --git a/src/nxt_fs.h b/src/nxt_fs.h index ff589979..af9585b8 100644 --- a/src/nxt_fs.h +++ b/src/nxt_fs.h @@ -36,6 +36,7 @@ typedef struct { } nxt_fs_mount_t; +nxt_int_t nxt_fs_mkdir_parent(const u_char *path, mode_t mode); nxt_int_t nxt_fs_mkdir_all(const u_char *dir, mode_t mode); nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt); void nxt_fs_unmount(const u_char *path); diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c index d9c9f2ef..c7e4455e 100644 --- a/src/nxt_runtime.c +++ b/src/nxt_runtime.c @@ -1369,6 +1369,8 @@ nxt_runtime_pid_file_create(nxt_task_t *task, nxt_file_name_t *pid_file) file.name = pid_file; + nxt_fs_mkdir_parent(pid_file, 0755); + n = nxt_file_open(task, &file, O_WRONLY, O_CREAT | O_TRUNC, NXT_FILE_DEFAULT_ACCESS); -- cgit From b00983369be5f356280168b4c5d600bd7d614c60 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 29 Sep 2022 20:59:43 +0100 Subject: Renamed a couple of members of nxt_unit_request_t. This is a preparatory patch that renames the 'local' and 'local_length' members of the nxt_unit_request_t structure to 'local_addr' and 'local_addr_length' in preparation for the adding of 'local_port' and 'local_port_length' members. Suggested-by: Zhidao HONG Signed-off-by: Andrew Clayton --- src/java/nxt_jni_Request.c | 20 ++++++++++---------- src/nodejs/unit-http/unit.cpp | 3 ++- src/nxt_php_sapi.c | 2 +- src/nxt_router.c | 4 ++-- src/nxt_unit_request.h | 4 ++-- src/perl/nxt_perl_psgi.c | 2 +- src/python/nxt_python_asgi.c | 2 +- src/python/nxt_python_wsgi.c | 4 ++-- src/ruby/nxt_ruby.c | 4 ++-- src/test/nxt_unit_app_test.c | 2 +- 10 files changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/java/nxt_jni_Request.c b/src/java/nxt_jni_Request.c index 2e9dce67..980a26b6 100644 --- a/src/java/nxt_jni_Request.c +++ b/src/java/nxt_jni_Request.c @@ -461,8 +461,8 @@ nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls, jlong req_ptr) r = nxt_jlong2ptr(req_ptr); - return nxt_java_newString(env, nxt_unit_sptr_get(&r->local), - r->local_length); + return nxt_java_newString(env, nxt_unit_sptr_get(&r->local_addr), + r->local_addr_length); } @@ -474,11 +474,11 @@ nxt_java_Request_getLocalName(JNIEnv *env, jclass cls, jlong req_ptr) r = nxt_jlong2ptr(req_ptr); - local = nxt_unit_sptr_get(&r->local); - colon = memchr(local, ':', r->local_length); + local = nxt_unit_sptr_get(&r->local_addr); + colon = memchr(local, ':', r->local_addr_length); if (colon == NULL) { - colon = local + r->local_length; + colon = local + r->local_addr_length; } return nxt_java_newString(env, local, colon - local); @@ -494,20 +494,20 @@ nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls, jlong req_ptr) r = nxt_jlong2ptr(req_ptr); - local = nxt_unit_sptr_get(&r->local); - colon = memchr(local, ':', r->local_length); + local = nxt_unit_sptr_get(&r->local_addr); + colon = memchr(local, ':', r->local_addr_length); if (colon == NULL) { return 80; } - tmp = local[r->local_length]; + tmp = local[r->local_addr_length]; - local[r->local_length] = '\0'; + local[r->local_addr_length] = '\0'; res = strtol(colon + 1, NULL, 10); - local[r->local_length] = tmp; + local[r->local_addr_length] = tmp; return res; } diff --git a/src/nodejs/unit-http/unit.cpp b/src/nodejs/unit-http/unit.cpp index ee5dc46f..7912d0ac 100644 --- a/src/nodejs/unit-http/unit.cpp +++ b/src/nodejs/unit-http/unit.cpp @@ -657,7 +657,8 @@ Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req) req_data->sock_ref = wrap(res, req, sock_destroy); set_named_property(res, "remoteAddress", r->remote, r->remote_length); - set_named_property(res, "localAddress", r->local, r->local_length); + set_named_property(res, "localAddress", r->local_addr, + r->local_addr_length); return res; } diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index 68ef07eb..42fdbc68 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -1365,7 +1365,7 @@ nxt_php_register_variables(zval *track_vars_array TSRMLS_DC) nxt_php_set_sptr(req, "REMOTE_ADDR", &r->remote, r->remote_length, track_vars_array TSRMLS_CC); - nxt_php_set_sptr(req, "SERVER_ADDR", &r->local, r->local_length, + nxt_php_set_sptr(req, "SERVER_ADDR", &r->local_addr, r->local_addr_length, track_vars_array TSRMLS_CC); nxt_php_set_sptr(req, "SERVER_NAME", &r->server_name, r->server_name_length, diff --git a/src/nxt_router.c b/src/nxt_router.c index f02bf3f2..6430aea4 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -5249,8 +5249,8 @@ nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r, r->remote->address_length); *p++ = '\0'; - req->local_length = r->local->address_length; - nxt_unit_sptr_set(&req->local, p); + req->local_addr_length = r->local->address_length; + nxt_unit_sptr_set(&req->local_addr, p); p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length); *p++ = '\0'; diff --git a/src/nxt_unit_request.h b/src/nxt_unit_request.h index 5dbf648d..f6b96838 100644 --- a/src/nxt_unit_request.h +++ b/src/nxt_unit_request.h @@ -18,7 +18,7 @@ struct nxt_unit_request_s { uint8_t method_length; uint8_t version_length; uint8_t remote_length; - uint8_t local_length; + uint8_t local_addr_length; uint8_t tls; uint8_t websocket_handshake; uint8_t app_target; @@ -38,7 +38,7 @@ struct nxt_unit_request_s { nxt_unit_sptr_t method; nxt_unit_sptr_t version; nxt_unit_sptr_t remote; - nxt_unit_sptr_t local; + nxt_unit_sptr_t local_addr; nxt_unit_sptr_t server_name; nxt_unit_sptr_t target; nxt_unit_sptr_t path; diff --git a/src/perl/nxt_perl_psgi.c b/src/perl/nxt_perl_psgi.c index 08a6f29e..0c1c1222 100644 --- a/src/perl/nxt_perl_psgi.c +++ b/src/perl/nxt_perl_psgi.c @@ -671,7 +671,7 @@ nxt_perl_psgi_env_create(PerlInterpreter *my_perl, RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("REMOTE_ADDR"), &r->remote, r->remote_length)); RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_ADDR"), - &r->local, r->local_length)); + &r->local_addr, r->local_addr_length)); RC(nxt_perl_psgi_add_sptr(my_perl, hash_env, NL("SERVER_NAME"), &r->server_name, r->server_name_length)); diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 4ad0857d..40ea5e24 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -674,7 +674,7 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) SET_ITEM(scope, client, v) Py_DECREF(v); - v = nxt_py_asgi_create_address(&r->local, r->local_length, 80); + v = nxt_py_asgi_create_address(&r->local_addr, r->local_addr_length, 80); if (nxt_slow_path(v == NULL)) { nxt_unit_req_alert(req, "Python failed to create 'server' pair"); goto fail; diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index 87dcfaa2..3fb6ac3b 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -609,8 +609,8 @@ nxt_python_get_environ(nxt_python_ctx_t *pctx) RC(nxt_python_add_sptr(pctx, nxt_py_remote_addr_str, &r->remote, r->remote_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local, - r->local_length)); + RC(nxt_python_add_sptr(pctx, nxt_py_server_addr_str, &r->local_addr, + r->local_addr_length)); if (r->tls) { RC(nxt_python_add_obj(pctx, nxt_py_wsgi_uri_scheme_str, diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index f316d8a5..1b55e7ef 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -747,8 +747,8 @@ nxt_ruby_read_request(nxt_unit_request_info_t *req, VALUE hash_env) r->version_length); nxt_ruby_add_sptr(hash_env, nxt_rb_remote_addr_str, &r->remote, r->remote_length); - nxt_ruby_add_sptr(hash_env, nxt_rb_server_addr_str, &r->local, - r->local_length); + nxt_ruby_add_sptr(hash_env, nxt_rb_server_addr_str, &r->local_addr, + r->local_addr_length); nxt_ruby_add_sptr(hash_env, nxt_rb_server_name_str, &r->server_name, r->server_name_length); diff --git a/src/test/nxt_unit_app_test.c b/src/test/nxt_unit_app_test.c index 8fda9740..d83bd83a 100644 --- a/src/test/nxt_unit_app_test.c +++ b/src/test/nxt_unit_app_test.c @@ -225,7 +225,7 @@ greeting_app_request_handler(nxt_unit_request_info_t *req) *p++ = '\n'; p = copy(p, LOCAL_ADDR, nxt_length(LOCAL_ADDR)); - p = copy(p, nxt_unit_sptr_get(&r->local), r->local_length); + p = copy(p, nxt_unit_sptr_get(&r->local_addr), r->local_addr_length); *p++ = '\n'; p = copy(p, TARGET, nxt_length(TARGET)); -- cgit From dc9f592d6e7123d57924146dcbf1be80366bc98b Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Wed, 28 Sep 2022 15:51:55 +0100 Subject: Ruby: added support for rack V3. Ruby applications would fail to start if they were using rack v3 2022/09/28 15:48:46 [alert] 0#80912 [unit] Ruby: Failed to parse rack script 2022/09/28 15:48:46 [notice] 80911#80911 app process 80912 exited with code 1 This was due to a change in the rack API Rack V2 def self.load_file(path, opts = Server::Options.new) ... cfgfile.sub!(/^__END__\n.*\Z/m, '') app = new_from_string cfgfile, path return app, options end Rack V3 def self.load_file(path) ... return new_from_string(config, path) end This patch handles _both_ the above APIs by correctly handling the cases where we do and don't get an array returned from nxt_ruby_rack_parse_script(). Closes: Tested-by: Andrew Clayton Reviewed-by: Andrew Clayton [ Andrew: Patch by Zhidao, commit message by me with input from Zhidao ] Signed-off-by: Andrew Clayton --- src/ruby/nxt_ruby.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 1b55e7ef..cc287e0e 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -480,12 +480,17 @@ nxt_ruby_rack_init(nxt_ruby_rack_init_t *rack_init) rackup = rb_protect(nxt_ruby_rack_parse_script, (VALUE) (uintptr_t) rack_init, &state); - if (nxt_slow_path(TYPE(rackup) != T_ARRAY || state != 0)) { + + if (nxt_slow_path(state != 0)) { nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Failed to parse rack script"); return Qnil; } + if (TYPE(rackup) != T_ARRAY) { + return rackup; + } + if (nxt_slow_path(RARRAY_LEN(rackup) < 1)) { nxt_alert(rack_init->task, "Ruby: Invalid rack config file"); return Qnil; -- cgit From d806a90609e99cb4c8db71d620d5db3d26e83693 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Mon, 3 Oct 2022 13:01:33 +0100 Subject: Ruby: used nxt_ruby_exception_log() in nxt_ruby_rack_init(). For consistency use nxt_ruby_exception_log() rather than nxt_alert() in nxt_ruby_rack_init(). Signed-off-by: Andrew Clayton --- src/ruby/nxt_ruby.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index cc287e0e..bcb48f6b 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -492,7 +492,7 @@ nxt_ruby_rack_init(nxt_ruby_rack_init_t *rack_init) } if (nxt_slow_path(RARRAY_LEN(rackup) < 1)) { - nxt_alert(rack_init->task, "Ruby: Invalid rack config file"); + nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Invalid rack config file"); return Qnil; } -- cgit From 7aa6b0629897235684961dfb9aa16e226efa27e6 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Wed, 12 Oct 2022 08:21:02 +0800 Subject: HTTP: added a $request_time variable. --- src/nxt_http.h | 2 ++ src/nxt_http_request.c | 2 ++ src/nxt_http_variables.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) (limited to 'src') diff --git a/src/nxt_http.h b/src/nxt_http.h index c2e85840..d5bff712 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -140,6 +140,8 @@ struct nxt_http_request_s { nxt_buf_t *out; const nxt_http_request_state_t *state; + nxt_nsec_t start_time; + nxt_str_t host; nxt_str_t server_name; nxt_str_t target; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 7a790f73..5c1455bf 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; + r->start_time = nxt_thread_monotonic_time(task->thread); + task->thread->engine->requests_cnt++; return r; diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index 5a632b24..e01bcdb9 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -9,6 +9,8 @@ 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_request_time(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, @@ -45,6 +47,9 @@ static nxt_var_decl_t nxt_http_vars[] = { { .name = nxt_string("dollar"), .handler = nxt_http_var_dollar, + }, { + .name = nxt_string("request_time"), + .handler = nxt_http_var_request_time, }, { .name = nxt_string("method"), .handler = nxt_http_var_method, @@ -110,6 +115,34 @@ nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) } +static nxt_int_t +nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + u_char *p; + nxt_msec_t ms; + nxt_nsec_t now; + nxt_http_request_t *r; + + r = ctx; + + now = nxt_thread_monotonic_time(task->thread); + ms = (now - r->start_time) / 1000000; + + str->start = nxt_mp_nget(r->mem_pool, NXT_TIME_T_LEN + 4); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + p = nxt_sprintf(str->start, str->start + NXT_TIME_T_LEN, "%T.%03M", + (nxt_time_t) ms / 1000, ms % 1000); + + str->length = p - str->start; + + 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 f8b892e1fa3d6398a21ce5e183911baa11a14d6a Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 6 Oct 2022 13:13:30 +0100 Subject: Fixed the build on MacOS (and others). @alejandro-colomar reported that the build was broken on MacOS cc -o build/unitd -pipe -fPIC -fvisibility=hidden -O -W -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -fstrict-aliasing -Wstrict-overflow=5 -Wmissing-prototypes -Werror -g \ build/src/nxt_main.o build/libnxt.a \ \ \ -L/usr/local/Cellar/pcre2/10.40/lib -lpcre2-8 Undefined symbols for architecture x86_64: "_nxt_fs_mkdir_parent", referenced from: _nxt_runtime_pid_file_create in libnxt.a(nxt_runtime.o) _nxt_runtime_controller_socket in libnxt.a(nxt_controller.o) ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [build/unitd] Error 1 This was due to commit 57fc920 ("Socket: Created control socket & pid file directories."). This happened because this commit introduced the usage of nxt_fs_mkdir_parent() in core code which uses nxt_fs_mkdir(), both of these are defined in src/nxt_fs.c. It turns out however that this file doesn't get built on MacOS (or any system that isn't Linux or that lacks a FreeBSD compatible nmount(2) system call) due to the following In auto/sources we have if [ $NXT_HAVE_ROOTFS = YES ]; then NXT_LIB_SRCS="$NXT_LIB_SRCS src/nxt_fs.c" fi NXT_HAVE_ROOTFS is set in auto/isolation If [ $NXT_HAVE_MOUNT = YES -a $NXT_HAVE_UNMOUNT = YES ]; then NXT_HAVE_ROOTFS=YES cat << END >> $NXT_AUTO_CONFIG_H #ifndef NXT_HAVE_ISOLATION_ROOTFS #define NXT_HAVE_ISOLATION_ROOTFS 1 #endif END fi While we do have a check for a generic umount(2) which is found on MacOS, for mount(2) we currently only check for the Linux mount(2) and FreeBSD nmount(2) system calls. So NXT_HAVE_ROOTFS is set to NO on MacOS and we don't build src/nxt_fs.c This fixes the immediate build issue by taking the mount/umount OS support out of nxt_fs.c into a new nxt_fs_mount.c file which is guarded by the above while we now build nxt_fs.c unconditionally. This should fix the build on any _supported_ system. Reported-by: Alejandro Colomar Fixes: 57fc920 ("Socket: Created control socket & pid file directories.") Signed-off-by: Andrew Clayton --- src/nxt_fs.c | 225 --------------------------------------------------- src/nxt_fs.h | 32 -------- src/nxt_fs_mount.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nxt_fs_mount.h | 48 +++++++++++ src/nxt_main.h | 1 + 5 files changed, 279 insertions(+), 257 deletions(-) create mode 100644 src/nxt_fs_mount.c create mode 100644 src/nxt_fs_mount.h (limited to 'src') diff --git a/src/nxt_fs.c b/src/nxt_fs.c index 35850798..a467da98 100644 --- a/src/nxt_fs.c +++ b/src/nxt_fs.c @@ -4,235 +4,10 @@ #include -#if (NXT_HAVE_FREEBSD_NMOUNT) -#include -#include -#endif - static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode); -#if (NXT_HAVE_LINUX_MOUNT) - -nxt_int_t -nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) -{ - int rc; - const char *fsname; - unsigned long flags; - - flags = 0; - - switch (mnt->type) { - case NXT_FS_BIND: - if (nxt_slow_path(mnt->flags != 0)) { - nxt_log(task, NXT_LOG_WARN, - "bind mount ignores additional flags"); - } - - fsname = "bind"; - flags = MS_BIND | MS_REC; - break; - - case NXT_FS_PROC: - fsname = "proc"; - goto getflags; - - case NXT_FS_TMP: - fsname = "tmpfs"; - goto getflags; - - default: - fsname = (const char *) mnt->name; - - getflags: - - if (mnt->flags & NXT_FS_FLAGS_NODEV) { - flags |= MS_NODEV; - } - - if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { - flags |= MS_NOEXEC; - } - - if (mnt->flags & NXT_FS_FLAGS_NOSUID) { - flags |= MS_NOSUID; - } - - if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) { - flags |= MS_RELATIME; - } - } - - rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags, - mnt->data); - - if (nxt_slow_path(rc < 0)) { - nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E", - mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno); - - return NXT_ERROR; - } - - return NXT_OK; -} - -#elif (NXT_HAVE_FREEBSD_NMOUNT) - -nxt_int_t -nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) -{ - int flags; - u_char *data, *p, *end; - size_t iovlen; - nxt_int_t ret; - const char *fsname; - struct iovec iov[128]; - char errmsg[256]; - - if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) { - nxt_alert(task, "nmount(2) doesn't support \"nodev\" option"); - - return NXT_ERROR; - } - - flags = 0; - - switch (mnt->type) { - case NXT_FS_BIND: - fsname = "nullfs"; - break; - - case NXT_FS_PROC: - fsname = "procfs"; - goto getflags; - - case NXT_FS_TMP: - fsname = "tmpfs"; - goto getflags; - - default: - fsname = (const char *) mnt->name; - - getflags: - - if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { - flags |= MNT_NOEXEC; - } - - if (mnt->flags & NXT_FS_FLAGS_NOSUID) { - flags |= MNT_NOSUID; - } - - if (mnt->flags & NXT_FS_FLAGS_NOTIME) { - flags |= MNT_NOATIME; - } - - if (mnt->flags & NXT_FS_FLAGS_RDONLY) { - flags |= MNT_RDONLY; - } - } - - iov[0].iov_base = (void *) "fstype"; - iov[0].iov_len = 7; - iov[1].iov_base = (void *) fsname; - iov[1].iov_len = nxt_strlen(fsname) + 1; - iov[2].iov_base = (void *) "fspath"; - iov[2].iov_len = 7; - iov[3].iov_base = (void *) mnt->dst; - iov[3].iov_len = nxt_strlen(mnt->dst) + 1; - iov[4].iov_base = (void *) "target"; - iov[4].iov_len = 7; - iov[5].iov_base = (void *) mnt->src; - iov[5].iov_len = nxt_strlen(mnt->src) + 1; - iov[6].iov_base = (void *) "errmsg"; - iov[6].iov_len = 7; - iov[7].iov_base = (void *) errmsg; - iov[7].iov_len = sizeof(errmsg); - - iovlen = 8; - - data = NULL; - - if (mnt->data != NULL) { - data = (u_char *) nxt_strdup(mnt->data); - if (nxt_slow_path(data == NULL)) { - return NXT_ERROR; - } - - end = data - 1; - - do { - p = end + 1; - end = nxt_strchr(p, '='); - if (end == NULL) { - break; - } - - *end = '\0'; - - iov[iovlen].iov_base = (void *) p; - iov[iovlen].iov_len = (end - p) + 1; - - iovlen++; - - p = end + 1; - - end = nxt_strchr(p, ','); - if (end != NULL) { - *end = '\0'; - } - - iov[iovlen].iov_base = (void *) p; - iov[iovlen].iov_len = nxt_strlen(p) + 1; - - iovlen++; - - } while (end != NULL && nxt_nitems(iov) > (iovlen + 2)); - } - - ret = NXT_OK; - - if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) { - nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg); - ret = NXT_ERROR; - } - - if (data != NULL) { - free(data); - } - - return ret; -} - -#endif - - -#if (NXT_HAVE_LINUX_UMOUNT2) - -void -nxt_fs_unmount(const u_char *path) -{ - if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) { - nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E", - path, nxt_errno); - } -} - -#elif (NXT_HAVE_UNMOUNT) - -void -nxt_fs_unmount(const u_char *path) -{ - if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) { - nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno); - } -} - -#endif - - nxt_int_t nxt_fs_mkdir_all(const u_char *dir, mode_t mode) { diff --git a/src/nxt_fs.h b/src/nxt_fs.h index af9585b8..c8868d80 100644 --- a/src/nxt_fs.h +++ b/src/nxt_fs.h @@ -6,40 +6,8 @@ #define _NXT_FS_H_INCLUDED_ -typedef enum { - NXT_FS_UNKNOWN = 0, - NXT_FS_BIND, - NXT_FS_TMP, - NXT_FS_PROC, - NXT_FS_LAST, -} nxt_fs_type_t; - - -typedef enum { - NXT_FS_FLAGS_NOSUID = 1 << 0, - NXT_FS_FLAGS_NOEXEC = 1 << 1, - NXT_FS_FLAGS_NOTIME = 1 << 2, - NXT_FS_FLAGS_NODEV = 1 << 3, - NXT_FS_FLAGS_RDONLY = 1 << 4, -} nxt_fs_flags_t; - - -typedef struct { - u_char *src; - u_char *dst; - nxt_fs_type_t type; - u_char *name; - nxt_fs_flags_t flags; - u_char *data; - nxt_uint_t builtin; /* 1-bit */ - nxt_uint_t deps; /* 1-bit */ -} nxt_fs_mount_t; - - nxt_int_t nxt_fs_mkdir_parent(const u_char *path, mode_t mode); nxt_int_t nxt_fs_mkdir_all(const u_char *dir, mode_t mode); -nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt); -void nxt_fs_unmount(const u_char *path); #endif /* _NXT_FS_H_INCLUDED_ */ diff --git a/src/nxt_fs_mount.c b/src/nxt_fs_mount.c new file mode 100644 index 00000000..d9b384e4 --- /dev/null +++ b/src/nxt_fs_mount.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#include + +#if (NXT_HAVE_FREEBSD_NMOUNT) +#include +#include +#endif + + +#if (NXT_HAVE_LINUX_MOUNT) + +nxt_int_t +nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) +{ + int rc; + const char *fsname; + unsigned long flags; + + flags = 0; + + switch (mnt->type) { + case NXT_FS_BIND: + if (nxt_slow_path(mnt->flags != 0)) { + nxt_log(task, NXT_LOG_WARN, + "bind mount ignores additional flags"); + } + + fsname = "bind"; + flags = MS_BIND | MS_REC; + break; + + case NXT_FS_PROC: + fsname = "proc"; + goto getflags; + + case NXT_FS_TMP: + fsname = "tmpfs"; + goto getflags; + + default: + fsname = (const char *) mnt->name; + + getflags: + + if (mnt->flags & NXT_FS_FLAGS_NODEV) { + flags |= MS_NODEV; + } + + if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { + flags |= MS_NOEXEC; + } + + if (mnt->flags & NXT_FS_FLAGS_NOSUID) { + flags |= MS_NOSUID; + } + + if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) { + flags |= MS_RELATIME; + } + } + + rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags, + mnt->data); + + if (nxt_slow_path(rc < 0)) { + nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E", + mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno); + + return NXT_ERROR; + } + + return NXT_OK; +} + +#elif (NXT_HAVE_FREEBSD_NMOUNT) + +nxt_int_t +nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) +{ + int flags; + u_char *data, *p, *end; + size_t iovlen; + nxt_int_t ret; + const char *fsname; + struct iovec iov[128]; + char errmsg[256]; + + if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) { + nxt_alert(task, "nmount(2) doesn't support \"nodev\" option"); + + return NXT_ERROR; + } + + flags = 0; + + switch (mnt->type) { + case NXT_FS_BIND: + fsname = "nullfs"; + break; + + case NXT_FS_PROC: + fsname = "procfs"; + goto getflags; + + case NXT_FS_TMP: + fsname = "tmpfs"; + goto getflags; + + default: + fsname = (const char *) mnt->name; + + getflags: + + if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { + flags |= MNT_NOEXEC; + } + + if (mnt->flags & NXT_FS_FLAGS_NOSUID) { + flags |= MNT_NOSUID; + } + + if (mnt->flags & NXT_FS_FLAGS_NOTIME) { + flags |= MNT_NOATIME; + } + + if (mnt->flags & NXT_FS_FLAGS_RDONLY) { + flags |= MNT_RDONLY; + } + } + + iov[0].iov_base = (void *) "fstype"; + iov[0].iov_len = 7; + iov[1].iov_base = (void *) fsname; + iov[1].iov_len = nxt_strlen(fsname) + 1; + iov[2].iov_base = (void *) "fspath"; + iov[2].iov_len = 7; + iov[3].iov_base = (void *) mnt->dst; + iov[3].iov_len = nxt_strlen(mnt->dst) + 1; + iov[4].iov_base = (void *) "target"; + iov[4].iov_len = 7; + iov[5].iov_base = (void *) mnt->src; + iov[5].iov_len = nxt_strlen(mnt->src) + 1; + iov[6].iov_base = (void *) "errmsg"; + iov[6].iov_len = 7; + iov[7].iov_base = (void *) errmsg; + iov[7].iov_len = sizeof(errmsg); + + iovlen = 8; + + data = NULL; + + if (mnt->data != NULL) { + data = (u_char *) nxt_strdup(mnt->data); + if (nxt_slow_path(data == NULL)) { + return NXT_ERROR; + } + + end = data - 1; + + do { + p = end + 1; + end = nxt_strchr(p, '='); + if (end == NULL) { + break; + } + + *end = '\0'; + + iov[iovlen].iov_base = (void *) p; + iov[iovlen].iov_len = (end - p) + 1; + + iovlen++; + + p = end + 1; + + end = nxt_strchr(p, ','); + if (end != NULL) { + *end = '\0'; + } + + iov[iovlen].iov_base = (void *) p; + iov[iovlen].iov_len = nxt_strlen(p) + 1; + + iovlen++; + + } while (end != NULL && nxt_nitems(iov) > (iovlen + 2)); + } + + ret = NXT_OK; + + if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) { + nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg); + ret = NXT_ERROR; + } + + if (data != NULL) { + free(data); + } + + return ret; +} + +#endif + + +#if (NXT_HAVE_LINUX_UMOUNT2) + +void +nxt_fs_unmount(const u_char *path) +{ + if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) { + nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E", + path, nxt_errno); + } +} + +#elif (NXT_HAVE_UNMOUNT) + +void +nxt_fs_unmount(const u_char *path) +{ + if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) { + nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno); + } +} + +#endif diff --git a/src/nxt_fs_mount.h b/src/nxt_fs_mount.h new file mode 100644 index 00000000..e0fe6eb2 --- /dev/null +++ b/src/nxt_fs_mount.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_FS_MOUNT_H_INCLUDED_ +#define _NXT_FS_MOUNT_H_INCLUDED_ + + +typedef enum nxt_fs_type_s nxt_fs_type_t; +typedef enum nxt_fs_flags_s nxt_fs_flags_t; +typedef struct nxt_fs_mount_s nxt_fs_mount_t; + + +enum nxt_fs_type_s { + NXT_FS_UNKNOWN = 0, + NXT_FS_BIND, + NXT_FS_TMP, + NXT_FS_PROC, + NXT_FS_LAST, +}; + + +enum nxt_fs_flags_s { + NXT_FS_FLAGS_NOSUID = 1 << 0, + NXT_FS_FLAGS_NOEXEC = 1 << 1, + NXT_FS_FLAGS_NOTIME = 1 << 2, + NXT_FS_FLAGS_NODEV = 1 << 3, + NXT_FS_FLAGS_RDONLY = 1 << 4, +}; + + +struct nxt_fs_mount_s { + u_char *src; + u_char *dst; + nxt_fs_type_t type; + u_char *name; + nxt_fs_flags_t flags; + u_char *data; + nxt_uint_t builtin; /* 1-bit */ + nxt_uint_t deps; /* 1-bit */ +}; + + +nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt); +void nxt_fs_unmount(const u_char *path); + + +#endif /* _NXT_FS_MOUNT_H_INCLUDED_ */ diff --git a/src/nxt_main.h b/src/nxt_main.h index dca4b6dc..a51a1ce7 100644 --- a/src/nxt_main.h +++ b/src/nxt_main.h @@ -59,6 +59,7 @@ typedef uint16_t nxt_port_id_t; #include #include #include +#include #include #include #include -- cgit From f2213dbd1b51838ec6b59073d9d071a75def7858 Mon Sep 17 00:00:00 2001 From: Alex Colomar Date: Sat, 10 Sep 2022 18:00:27 +0200 Subject: Added missing error checking in the C API. pthread_mutex_init(3) may fail for several reasons, and failing to check will cause Undefined Behavior when those errors happen. Add missing checks, and correctly deinitialize previously created stuff before exiting from the API. Signed-off-by: Alejandro Colomar Reviewed-by: Andrew Clayton Reviewed-by: Zhidao HONG --- src/nxt_unit.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nxt_unit.c b/src/nxt_unit.c index e5cb0b58..3932b2ab 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -116,7 +116,7 @@ static int nxt_unit_incoming_mmap(nxt_unit_ctx_t *ctx, pid_t pid, int fd); static void nxt_unit_awake_ctx(nxt_unit_ctx_t *ctx, nxt_unit_ctx_impl_t *ctx_impl); -static void nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps); +static int nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps); nxt_inline void nxt_unit_process_use(nxt_unit_process_t *process); nxt_inline void nxt_unit_process_release(nxt_unit_process_t *process); static void nxt_unit_mmaps_destroy(nxt_unit_mmaps_t *mmaps); @@ -606,7 +606,7 @@ nxt_unit_create(nxt_unit_init_t *init) if (nxt_slow_path(rc != 0)) { nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); - goto fail; + goto out_unit_free; } lib->unit.data = init->data; @@ -631,17 +631,35 @@ nxt_unit_create(nxt_unit_init_t *init) rc = nxt_unit_ctx_init(lib, &lib->main_ctx, init->ctx_data); if (nxt_slow_path(rc != NXT_UNIT_OK)) { - pthread_mutex_destroy(&lib->mutex); - goto fail; + goto out_mutex_destroy; + } + + rc = nxt_unit_mmaps_init(&lib->incoming); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); + + goto out_ctx_free; } - nxt_unit_mmaps_init(&lib->incoming); - nxt_unit_mmaps_init(&lib->outgoing); + rc = nxt_unit_mmaps_init(&lib->outgoing); + if (nxt_slow_path(rc != 0)) { + nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc); + + goto out_mmaps_destroy; + } return lib; -fail: +out_mmaps_destroy: + nxt_unit_mmaps_destroy(&lib->incoming); + +out_ctx_free: + nxt_unit_ctx_free(&lib->main_ctx); + +out_mutex_destroy: + pthread_mutex_destroy(&lib->mutex); +out_unit_free: nxt_unit_free(NULL, lib); return NULL; @@ -4093,15 +4111,15 @@ nxt_unit_awake_ctx(nxt_unit_ctx_t *ctx, nxt_unit_ctx_impl_t *ctx_impl) } -static void +static int nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps) { - pthread_mutex_init(&mmaps->mutex, NULL); - mmaps->size = 0; mmaps->cap = 0; mmaps->elts = NULL; mmaps->allocated_chunks = 0; + + return pthread_mutex_init(&mmaps->mutex, NULL); } -- cgit From 48b6a7b311272896be9212e170fcee8d1da25e79 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 2 Jun 2022 16:16:35 +0200 Subject: PHP: Fixed php_module_startup() call for PHP 8.2. PHP 8.2 changed the prototype of the function, removing the last parameter. Signed-off-by: Remi Collet Cc: Timo Stark Cc: George Peter Banyard Tested-by: Andy Postnikov Acked-by: Andy Postnikov Reviewed-by: Andrew Clayton Signed-off-by: Alejandro Colomar --- src/nxt_php_sapi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index 42fdbc68..b7eb29d1 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -1150,7 +1150,11 @@ nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir) static int nxt_php_startup(sapi_module_struct *sapi_module) { +#if (PHP_VERSION_ID < 80200) return php_module_startup(sapi_module, &nxt_php_unit_module, 1); +#else + return php_module_startup(sapi_module, &nxt_php_unit_module); +#endif } -- cgit From db86dc0586ac6c7184eeacc3e8769816f90dfddd Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Fri, 14 Oct 2022 12:16:43 +0200 Subject: Added parentheses for consistency. Reported-by: Andrew Clayton Signed-off-by: Remi Collet Reviewed-by: Andrew Clayton Signed-off-by: Alejandro Colomar --- src/nxt_php_sapi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index b7eb29d1..ca49b289 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -16,20 +16,20 @@ #include -#if PHP_VERSION_ID >= 50400 +#if (PHP_VERSION_ID >= 50400) #define NXT_HAVE_PHP_IGNORE_CWD 1 #endif -#if PHP_VERSION_ID >= 70100 +#if (PHP_VERSION_ID >= 70100) #define NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 1 #else #define NXT_HAVE_PHP_INTERRUPTS 1 #endif -#if PHP_VERSION_ID >= 70000 +#if (PHP_VERSION_ID >= 70000) #define NXT_PHP7 1 #endif -#if PHP_VERSION_ID >= 80000 +#if (PHP_VERSION_ID >= 80000) #define NXT_PHP8 1 #endif @@ -73,7 +73,7 @@ typedef int (*nxt_php_disable_t)(char *p, size_t size); typedef int (*nxt_php_disable_t)(char *p, uint TSRMLS_DC); #endif -#if PHP_VERSION_ID < 70200 +#if (PHP_VERSION_ID < 70200) typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); #endif @@ -139,7 +139,7 @@ static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC); #ifdef NXT_PHP7 -#if PHP_VERSION_ID < 70200 +#if (PHP_VERSION_ID < 70200) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fastcgi_finish_request, 0, 0, _IS_BOOL, NULL, 0) #else @@ -355,7 +355,7 @@ static nxt_php_target_t *nxt_php_targets; static nxt_int_t nxt_php_last_target = -1; static nxt_unit_ctx_t *nxt_php_unit_ctx; -#if defined(ZTS) && PHP_VERSION_ID < 70400 +#if defined(ZTS) && (PHP_VERSION_ID < 70400) static void ***tsrm_ls; #endif @@ -377,7 +377,7 @@ nxt_php_setup(nxt_task_t *task, nxt_process_t *process, #ifdef ZTS -#if PHP_VERSION_ID >= 70400 +#if (PHP_VERSION_ID >= 70400) php_tsrm_startup(); #else tsrm_startup(1, 1, 0, NULL); -- cgit From c03ebf7ffec285c040450a1882687d762c7b1b4f Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Fri, 14 Oct 2022 14:00:02 +0800 Subject: Configuration: stopped automatic migration to the "share" behavior. This commit removed the $uri auto-append for the "share" option introduced in rev be6409cdb028. The main reason is that it causes problems when preparing Unit configurations to be loaded at startup from the state directory. E.g. Docker. A valid conf.json file with $uri references will end up with $uri$uri due to the auto-append. --- src/nxt_conf_validation.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index fe6c22e5..f8242f6e 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -1690,11 +1690,6 @@ static nxt_int_t nxt_conf_vldt_share(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) { - u_char *p; - nxt_str_t name, temp; - - static nxt_str_t uri = nxt_string("$uri"); - if (nxt_conf_type(value) == NXT_CONF_ARRAY) { if (nxt_conf_array_elements_count(value) == 0) { return nxt_conf_vldt_error(vldt, "The \"share\" array " @@ -1707,22 +1702,6 @@ nxt_conf_vldt_share(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, /* NXT_CONF_STRING */ - if (vldt->ver < 12600) { - nxt_conf_get_string(value, &name); - - temp.length = name.length + uri.length; - - temp.start = nxt_mp_get(vldt->conf_pool, temp.length); - if (nxt_slow_path(temp.start == NULL)) { - return NXT_ERROR; - } - - p = nxt_cpymem(temp.start, name.start, name.length); - nxt_memcpy(p, uri.start, uri.length); - - nxt_conf_set_string(value, &temp); - } - return nxt_conf_vldt_share_element(vldt, value); } -- cgit From 93d24bb1144bebedb79bec8745c42aa0dc778aef Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 16 Jan 2019 08:38:53 +0100 Subject: Preferring system crypto policy. If we don't call SSL_CTX_set_cipher_list(), then it uses the system's default. Link: Link: Link: Signed-off-by: Remi Collet Acked-by: Andrei Belov [ alx: add changelog and tweak commit message ] Signed-off-by: Alejandro Colomar --- src/nxt_openssl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index e19b1381..32904660 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -295,7 +295,7 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp, nxt_tls_init_t *tls_init, nxt_bool_t last) { SSL_CTX *ctx; - const char *ciphers, *ca_certificate; + const char *ca_certificate; nxt_tls_conf_t *conf; STACK_OF(X509_NAME) *list; nxt_tls_bundle_conf_t *bundle; @@ -361,13 +361,13 @@ nxt_openssl_server_init(nxt_task_t *task, nxt_mp_t *mp, } */ - ciphers = (conf->ciphers != NULL) ? conf->ciphers : "HIGH:!aNULL:!MD5"; - - if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) { - nxt_openssl_log_error(task, NXT_LOG_ALERT, + if (conf->ciphers) { /* else use system crypto policy */ + if (SSL_CTX_set_cipher_list(ctx, conf->ciphers) == 0) { + nxt_openssl_log_error(task, NXT_LOG_ALERT, "SSL_CTX_set_cipher_list(\"%s\") failed", - ciphers); - goto fail; + conf->ciphers); + goto fail; + } } #if (NXT_HAVE_OPENSSL_CONF_CMD) -- cgit From e096f19d47e45803d12a9c60ee51f79d2613281c Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 18 Nov 2021 17:47:39 +0100 Subject: TLS: Using ERR_get_error_all() with OpenSSL 3. Link: Cc: Andy Postnikov Cc: Andrew Clayton Signed-off-by: Remi Collet Signed-off-by: Alejandro Colomar --- src/nxt_openssl.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index 32904660..55611511 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -1777,7 +1777,11 @@ nxt_openssl_copy_error(u_char *p, u_char *end) clear = 0; for ( ;; ) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + err = ERR_get_error_all(NULL, NULL, NULL, &data, &flags); +#else err = ERR_get_error_line_data(NULL, NULL, &data, &flags); +#endif if (err == 0) { break; } -- cgit From 58248a6220540db89e69c928a5d8ad6be2a326fb Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Fri, 28 Oct 2022 00:54:01 +0100 Subject: Fixed some function definitions. Future releases of GCC will render function definitions like func() invalid by default. See the previous commit 09f88c9 ("Fixed main() prototypes in auto tests.") for details. Such functions should be defined like func(void) This is a good thing to do regardless of the upcoming GCC changes. Reviewed-by: Alejandro Colomar Signed-off-by: Andrew Clayton --- src/nxt_capability.c | 2 +- src/nxt_port.c | 4 ++-- src/test/nxt_unit_websocket_chat.c | 2 +- src/test/nxt_unit_websocket_echo.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nxt_capability.c b/src/nxt_capability.c index 24fd55d0..9f36ab99 100644 --- a/src/nxt_capability.c +++ b/src/nxt_capability.c @@ -50,7 +50,7 @@ nxt_capability_set(nxt_task_t *task, nxt_capabilities_t *cap) #if (NXT_HAVE_LINUX_CAPABILITY) static uint32_t -nxt_capability_linux_get_version() +nxt_capability_linux_get_version(void) { struct __user_cap_header_struct hdr; diff --git a/src/nxt_port.c b/src/nxt_port.c index ed7050f3..b9964df4 100644 --- a/src/nxt_port.c +++ b/src/nxt_port.c @@ -144,14 +144,14 @@ nxt_port_release(nxt_task_t *task, nxt_port_t *port) nxt_port_id_t -nxt_port_get_next_id() +nxt_port_get_next_id(void) { return nxt_atomic_fetch_add(&nxt_port_last_id, 1); } void -nxt_port_reset_next_id() +nxt_port_reset_next_id(void) { nxt_port_last_id = 1; } diff --git a/src/test/nxt_unit_websocket_chat.c b/src/test/nxt_unit_websocket_chat.c index 39f8a440..ec7c2cc3 100644 --- a/src/test/nxt_unit_websocket_chat.c +++ b/src/test/nxt_unit_websocket_chat.c @@ -201,7 +201,7 @@ ws_chat_close_handler(nxt_unit_request_info_t *req) int -main() +main(void) { nxt_unit_ctx_t *ctx; nxt_unit_init_t init; diff --git a/src/test/nxt_unit_websocket_echo.c b/src/test/nxt_unit_websocket_echo.c index 2a89cdc0..eab2e45f 100644 --- a/src/test/nxt_unit_websocket_echo.c +++ b/src/test/nxt_unit_websocket_echo.c @@ -83,7 +83,7 @@ ws_echo_websocket_handler(nxt_unit_websocket_frame_t *ws) int -main() +main(void) { nxt_unit_ctx_t *ctx; nxt_unit_init_t init; -- cgit From a03274456b54cbc39e220b9dd73c3fc3fb935e46 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Fri, 16 Sep 2022 14:38:53 +0100 Subject: PHP: allowed to specify URLs without a trailing '/'. Both @lucatacconi & @mwoodpatrick reported what appears to be the same issue on GitHub. Namely that when using the PHP language module and trying to access a URL that is a directory but without specifying the trailing '/', they were getting a '503 Service Unavailable' error. Note: This is when _not_ using the 'script' option. E.g with the following config { "listeners": { "[::1]:8080": { "pass": "applications/php" } }, "applications": { "php": { "type": "php", "root": "/var/tmp/unit-php" } } } and with a directory path of /var/tmp/unit-php/foo containing an index.php, you would see the following $ curl http://localhost/foo Error 503 Error 503 However $ curl http://localhost/foo/ would work and serve up the index.php This commit fixes the above so you get the desired behaviour without specifying the trailing '/' by doing the following 1] If the URL doesn't end in .php and doesn't have a trailing '/' then check if the requested path is a directory. 2) If it is a directory then create a 301 re-direct pointing to it. This matches the behaviour of the likes of nginx, Apache and lighttpd. This also matches the behaviour of the "share" action in Unit. This doesn't effect the behaviour of the 'script' option which bypasses the nxt_php_dynamic_request() function. This also adds a couple of tests to test/test_php_application.py to ensure this continues to work. Closes: Closes: Signed-off-by: Andrew Clayton --- src/nxt_php_sapi.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++---- src/nxt_router.c | 6 ++++ src/nxt_unit_request.h | 2 ++ 3 files changed, 92 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index ca49b289..924dd4e6 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -14,6 +14,7 @@ #include #include #include +#include #if (PHP_VERSION_ID >= 50400) @@ -100,6 +101,8 @@ static void nxt_php_str_trim_trail(nxt_str_t *str, u_char t); static void nxt_php_str_trim_lead(nxt_str_t *str, u_char t); nxt_inline u_char *nxt_realpath(const void *c); +static nxt_int_t nxt_php_do_301(nxt_unit_request_info_t *req); + static void nxt_php_request_handler(nxt_unit_request_info_t *req); static void nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r); @@ -920,6 +923,63 @@ nxt_realpath(const void *c) } +static nxt_int_t +nxt_php_do_301(nxt_unit_request_info_t *req) +{ + char *p, *url, *port; + uint32_t size; + const char *proto; + nxt_unit_request_t *r; + + r = req->request; + + url = nxt_malloc(sizeof("https://") - 1 + + r->server_name_length + + r->local_port_length + 1 + + r->path_length + 1 + + r->query_length + 1 + + 1); + if (nxt_slow_path(url == NULL)) { + return NXT_UNIT_ERROR; + } + + proto = r->tls ? "https://" : "http://"; + p = nxt_cpymem(url, proto, strlen(proto)); + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->server_name), + r->server_name_length); + + port = nxt_unit_sptr_get(&r->local_port); + if (r->local_port_length > 0 + && !(r->tls && strcmp(port, "443") == 0) + && !(!r->tls && strcmp(port, "80") == 0)) + { + *p++ = ':'; + p = nxt_cpymem(p, port, r->local_port_length); + } + + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->path), r->path_length); + *p++ = '/'; + + if (r->query_length > 0) { + *p++ = '?'; + p = nxt_cpymem(p, nxt_unit_sptr_get(&r->query), r->query_length); + } + + *p = '\0'; + + size = p - url; + + nxt_unit_response_init(req, NXT_HTTP_MOVED_PERMANENTLY, 1, + nxt_length("Location") + size); + nxt_unit_response_add_field(req, "Location", nxt_length("Location"), + url, size); + + nxt_free(url); + + return NXT_UNIT_OK; +} + + static void nxt_php_request_handler(nxt_unit_request_info_t *req) { @@ -975,15 +1035,33 @@ nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) } else if (path.start[path.length - 1] == '/') { script_name = *ctx->index; - } else { - if (nxt_slow_path(path.length < 4 - || nxt_memcmp(path.start + (path.length - 4), - ".php", 4))) - { - nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); + } else if (path.length < 4 + || nxt_memcmp(path.start + (path.length - 4), ".php", 4) != 0) + { + char tpath[PATH_MAX]; + nxt_int_t ec; + struct stat sb; + + ec = NXT_UNIT_ERROR; + + if (ctx->root->length + path.length + 1 > PATH_MAX) { + nxt_unit_request_done(ctx->req, ec); return; } + + p = nxt_cpymem(tpath, ctx->root->start, ctx->root->length); + p = nxt_cpymem(p, path.start, path.length); + *p = '\0'; + + ret = stat(tpath, &sb); + if (ret == 0 && S_ISDIR(sb.st_mode)) { + ec = nxt_php_do_301(ctx->req); + } + + nxt_unit_request_done(ctx->req, ec); + + return; } ctx->script_filename.length = ctx->root->length diff --git a/src/nxt_router.c b/src/nxt_router.c index 6430aea4..cfd79bf5 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -5254,6 +5254,12 @@ 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->local_port_length = nxt_sockaddr_port_length(r->local); + nxt_unit_sptr_set(&req->local_port, p); + p = nxt_cpymem(p, nxt_sockaddr_port(r->local), + nxt_sockaddr_port_length(r->local)); + *p++ = '\0'; + req->tls = r->tls; req->websocket_handshake = r->websocket_handshake; diff --git a/src/nxt_unit_request.h b/src/nxt_unit_request.h index f6b96838..a6ebf0b6 100644 --- a/src/nxt_unit_request.h +++ b/src/nxt_unit_request.h @@ -19,6 +19,7 @@ struct nxt_unit_request_s { uint8_t version_length; uint8_t remote_length; uint8_t local_addr_length; + uint8_t local_port_length; uint8_t tls; uint8_t websocket_handshake; uint8_t app_target; @@ -39,6 +40,7 @@ struct nxt_unit_request_s { nxt_unit_sptr_t version; nxt_unit_sptr_t remote; nxt_unit_sptr_t local_addr; + nxt_unit_sptr_t local_port; nxt_unit_sptr_t server_name; nxt_unit_sptr_t target; nxt_unit_sptr_t path; -- cgit From 1b05161107112f09c15b128090284bb6de5b4f70 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Wed, 2 Nov 2022 21:45:40 +0100 Subject: Removed the unsafe nxt_memcmp() wrapper for memcmp(3). The casts are unnecessary, since memcmp(3)'s arguments are 'void *'. It might have been necessary in the times of K&R, where 'void *' didn't exist. Nowadays, it's unnecessary, and _very_ unsafe, since casts can hide all classes of bugs by silencing most compiler warnings. The changes from nxt_memcmp() to memcmp(3) were scripted: $ find src/ -type f \ | grep '\.[ch]$' \ | xargs sed -i 's/nxt_memcmp/memcmp/' Reviewed-by: Andrew Clayton Signed-off-by: Alejandro Colomar --- src/nxt_application.c | 2 +- src/nxt_conf.c | 6 +++--- src/nxt_controller.c | 4 ++-- src/nxt_errno.c | 6 +++--- src/nxt_h1proto.c | 6 +++--- src/nxt_http_parse.c | 6 +++--- src/nxt_http_route.c | 18 +++++++++--------- src/nxt_http_route_addr.c | 4 ++-- src/nxt_http_variables.c | 4 ++-- src/nxt_openssl.c | 2 +- src/nxt_php_sapi.c | 2 +- src/nxt_sockaddr.c | 6 +++--- src/nxt_string.c | 4 ++-- src/nxt_string.h | 10 +++------- src/test/nxt_http_parse_test.c | 2 +- src/test/nxt_tests.c | 2 +- src/test/nxt_utf8_file_name_test.c | 2 +- src/test/nxt_utf8_test.c | 2 +- 18 files changed, 42 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/nxt_application.c b/src/nxt_application.c index 556f1ffb..786c768b 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -366,7 +366,7 @@ nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, &app->type, app->version, name); if (app->compat_length != sizeof(compat) - || nxt_memcmp(app->compat, compat, sizeof(compat)) != 0) + || memcmp(app->compat, compat, sizeof(compat)) != 0) { nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); diff --git a/src/nxt_conf.c b/src/nxt_conf.c index c6312f3d..d04aa45c 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -1389,7 +1389,7 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, case 't': if (nxt_fast_path(end - start >= 4 - && nxt_memcmp(start, "true", 4) == 0)) + && memcmp(start, "true", 4) == 0)) { value->u.boolean = 1; value->type = NXT_CONF_VALUE_BOOLEAN; @@ -1401,7 +1401,7 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, case 'f': if (nxt_fast_path(end - start >= 5 - && nxt_memcmp(start, "false", 5) == 0)) + && memcmp(start, "false", 5) == 0)) { value->u.boolean = 0; value->type = NXT_CONF_VALUE_BOOLEAN; @@ -1413,7 +1413,7 @@ nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, case 'n': if (nxt_fast_path(end - start >= 4 - && nxt_memcmp(start, "null", 4) == 0)) + && memcmp(start, "null", 4) == 0)) { value->type = NXT_CONF_VALUE_NULL; return start + 4; diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 99c7ca10..5f3e55ef 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -1263,7 +1263,7 @@ nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req, /* Skip UTF-8 BOM. */ if (nxt_buf_mem_used_size(mbuf) >= 3 - && nxt_memcmp(mbuf->pos, "\xEF\xBB\xBF", 3) == 0) + && memcmp(mbuf->pos, "\xEF\xBB\xBF", 3) == 0) { mbuf->pos += 3; } @@ -1940,7 +1940,7 @@ nxt_controller_process_control(nxt_task_t *task, } if (!nxt_str_start(path, "applications/", 13) - || nxt_memcmp(path->start + path->length - 8, "/restart", 8) != 0) + || memcmp(path->start + path->length - 8, "/restart", 8) != 0) { goto not_found; } diff --git a/src/nxt_errno.c b/src/nxt_errno.c index 869a970f..47479a82 100644 --- a/src/nxt_errno.c +++ b/src/nxt_errno.c @@ -78,7 +78,7 @@ nxt_strerror_start(void) if (length == 0 /* HP-UX empty strings. */ || nxt_errno == NXT_EINVAL - || nxt_memcmp(msg, "Unknown error", 13) == 0) + || memcmp(msg, "Unknown error", 13) == 0) { invalid++; continue; @@ -86,8 +86,8 @@ nxt_strerror_start(void) #if (NXT_AIX) - if (nxt_memcmp(msg, "Error ", 6) == 0 - && nxt_memcmp(msg + length - 10, " occurred.", 9) == 0) + if (memcmp(msg, "Error ", 6) == 0 + && memcmp(msg + length - 10, " occurred.", 9) == 0) { invalid++; continue; diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 852b4866..3acba088 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -823,7 +823,7 @@ nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data) field->hopbyhop = 1; if (field->value_length == 7 - && nxt_memcmp(field->value, "chunked", 7) == 0) + && memcmp(field->value, "chunked", 7) == 0) { te = NXT_HTTP_TE_CHUNKED; @@ -2594,7 +2594,7 @@ nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, nxt_buf_mem_t *bm) p = bm->pos; - if (nxt_slow_path(nxt_memcmp(p, "HTTP/1.", 7) != 0 + if (nxt_slow_path(memcmp(p, "HTTP/1.", 7) != 0 || (p[7] != '0' && p[7] != '1'))) { return NXT_ERROR; @@ -2868,7 +2868,7 @@ nxt_h1p_peer_transfer_encoding(void *ctx, nxt_http_field_t *field, field->skip = 1; if (field->value_length == 7 - && nxt_memcmp(field->value, "chunked", 7) == 0) + && memcmp(field->value, "chunked", 7) == 0) { r->peer->proto.h1->chunked = 1; } diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 1bb4291f..f39d8f67 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -357,7 +357,7 @@ space_after_target: } while (*p == ' '); - if (nxt_memcmp(p, "HTTP/", nxt_min(end - p, 5)) == 0) { + if (memcmp(p, "HTTP/", nxt_min(end - p, 5)) == 0) { switch (end - p) { case 8: @@ -412,7 +412,7 @@ space_after_target: if (nxt_fast_path(ver.ui64 == http11.ui64 || ver.ui64 == http10.ui64 - || (nxt_memcmp(ver.str, "HTTP/1.", 7) == 0 + || (memcmp(ver.str, "HTTP/1.", 7) == 0 && ver.s.minor >= '0' && ver.s.minor <= '9'))) { rp->version.ui64 = ver.ui64; @@ -464,7 +464,7 @@ space_after_target: return nxt_http_parse_field_name(rp, pos, end); } - if (nxt_memcmp(ver.s.prefix, "HTTP/", 5) == 0 + if (memcmp(ver.s.prefix, "HTTP/", 5) == 0 && ver.s.major >= '0' && ver.s.major <= '9' && ver.s.point == '.' && ver.s.minor >= '0' && ver.s.minor <= '9') diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index cdc9077f..9aa23899 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -1740,15 +1740,15 @@ nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, break; case NXT_HTTP_ROUTE_ADDR_EXACT: - match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, + match = (memcmp(&sin->sin_addr, &p->addr.v4.start, sizeof(struct in_addr)) == 0); break; case NXT_HTTP_ROUTE_ADDR_RANGE: - match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, + match = (memcmp(&sin->sin_addr, &p->addr.v4.start, sizeof(struct in_addr)) >= 0 - && nxt_memcmp(&sin->sin_addr, &p->addr.v4.end, + && memcmp(&sin->sin_addr, &p->addr.v4.end, sizeof(struct in_addr)) <= 0); break; @@ -1786,15 +1786,15 @@ nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, break; case NXT_HTTP_ROUTE_ADDR_EXACT: - match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, + match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start, sizeof(struct in6_addr)) == 0); break; case NXT_HTTP_ROUTE_ADDR_RANGE: - match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, + match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start, sizeof(struct in6_addr)) >= 0 - && nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.end, + && memcmp(&sin6->sin6_addr, &p->addr.v6.end, sizeof(struct in6_addr)) <= 0); break; @@ -1937,7 +1937,7 @@ nxt_http_route_test_argument(nxt_http_request_t *r, if (rule->u.name.hash == nv->hash && rule->u.name.length == nv->name_length - && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) + && memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) { ret = nxt_http_route_test_rule(r, rule, nv->value, nv->value_length); @@ -2015,7 +2015,7 @@ nxt_http_route_test_cookie(nxt_http_request_t *r, if (rule->u.name.hash == nv->hash && rule->u.name.length == nv->name_length - && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) + && memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) { ret = nxt_http_route_test_rule(r, rule, nv->value, nv->value_length); @@ -2158,7 +2158,7 @@ nxt_http_route_memcmp(u_char *start, u_char *test, size_t test_length, nxt_int_t n; if (case_sensitive) { - n = nxt_memcmp(start, test, test_length); + n = memcmp(start, test, test_length); } else { n = nxt_memcasecmp(start, test, test_length); diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c index 34455af4..06b30d29 100644 --- a/src/nxt_http_route_addr.c +++ b/src/nxt_http_route_addr.c @@ -115,7 +115,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, return NXT_ADDR_PATTERN_FORMAT_ERROR; } - if (nxt_slow_path(nxt_memcmp(&inet6->start, &inet6->end, + if (nxt_slow_path(memcmp(&inet6->start, &inet6->end, sizeof(struct in6_addr)) > 0)) { return NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR; @@ -223,7 +223,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, return NXT_ADDR_PATTERN_FORMAT_ERROR; } - if (nxt_slow_path(nxt_memcmp(&inet->start, &inet->end, + if (nxt_slow_path(memcmp(&inet->start, &inet->end, sizeof(struct in_addr)) > 0)) { return NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR; diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index e01bcdb9..eb341716 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -421,7 +421,7 @@ nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) if (vf->hash == nv->hash && vf->name.length == nv->name_length - && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + && memcmp(vf->name.start, nv->name, nv->name_length) == 0) { str->start = nv->value; str->length = nv->value_length; @@ -499,7 +499,7 @@ nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) if (vf->hash == nv->hash && vf->name.length == nv->name_length - && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + && memcmp(vf->name.start, nv->name, nv->name_length) == 0) { str->start = nv->value; str->length = nv->value_length; diff --git a/src/nxt_openssl.c b/src/nxt_openssl.c index 55611511..f56135f3 100644 --- a/src/nxt_openssl.c +++ b/src/nxt_openssl.c @@ -780,7 +780,7 @@ nxt_tls_ticket_key_callback(SSL *s, unsigned char *name, unsigned char *iv, /* decrypt session ticket */ do { - if (nxt_memcmp(name, ticket[i].name, 16) == 0) { + if (memcmp(name, ticket[i].name, 16) == 0) { goto found; } diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index 924dd4e6..126a4684 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -1036,7 +1036,7 @@ nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) script_name = *ctx->index; } else if (path.length < 4 - || nxt_memcmp(path.start + (path.length - 4), ".php", 4) != 0) + || memcmp(path.start + (path.length - 4), ".php", 4) != 0) { char tpath[PATH_MAX]; nxt_int_t ec; diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 86c3335e..a076f286 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -382,7 +382,7 @@ nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) return 0; } - if (nxt_memcmp(&sa1->u.sockaddr_in6.sin6_addr, + if (memcmp(&sa1->u.sockaddr_in6.sin6_addr, &sa2->u.sockaddr_in6.sin6_addr, 16) != 0) { @@ -401,7 +401,7 @@ nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) length = sa1->socklen - offsetof(struct sockaddr_un, sun_path); - if (nxt_memcmp(&sa1->u.sockaddr_un.sun_path, + if (memcmp(&sa1->u.sockaddr_un.sun_path, &sa2->u.sockaddr_un.sun_path, length) != 0) { @@ -550,7 +550,7 @@ nxt_sockaddr_parse_optport(nxt_mp_t *mp, nxt_str_t *addr) return NULL; } - if (addr->length > 6 && nxt_memcmp(addr->start, "unix:", 5) == 0) { + if (addr->length > 6 && memcmp(addr->start, "unix:", 5) == 0) { sa = nxt_sockaddr_unix_parse(mp, addr); } else if (addr->start[0] == '[' || nxt_inet6_probe(addr)) { diff --git a/src/nxt_string.c b/src/nxt_string.c index 4d89c23c..1ca595a1 100644 --- a/src/nxt_string.c +++ b/src/nxt_string.c @@ -257,7 +257,7 @@ nxt_memstrn(const u_char *s, const u_char *end, const char *ss, size_t length) return NULL; } - if (nxt_memcmp(s, s2, length) == 0) { + if (memcmp(s, s2, length) == 0) { return (u_char *) s - 1; } } @@ -325,7 +325,7 @@ nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length) c1 = *s1; if (c1 == c2) { - if (nxt_memcmp(s1 + 1, s2, length) == 0) { + if (memcmp(s1 + 1, s2, length) == 0) { return (u_char *) s1; } } diff --git a/src/nxt_string.h b/src/nxt_string.h index a8673c61..d021df69 100644 --- a/src/nxt_string.h +++ b/src/nxt_string.h @@ -66,10 +66,6 @@ nxt_cpymem(void *dst, const void *src, size_t length) (void) memmove(dst, src, length) -#define nxt_memcmp(s1, s2, length) \ - memcmp((char *) s1, (char *) s2, length) - - #define nxt_memchr(s, c, length) \ memchr((char *) s, c, length) @@ -132,7 +128,7 @@ NXT_EXPORT char *nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src); #define nxt_strstr_eq(s1, s2) \ (((s1)->length == (s2)->length) \ - && (nxt_memcmp((s1)->start, (s2)->start, (s1)->length) == 0)) + && (memcmp((s1)->start, (s2)->start, (s1)->length) == 0)) #define nxt_strcasestr_eq(s1, s2) \ @@ -141,11 +137,11 @@ NXT_EXPORT char *nxt_str_cstrz(nxt_mp_t *mp, const nxt_str_t *src); #define nxt_str_eq(s, p, _length) \ - (((s)->length == _length) && (nxt_memcmp((s)->start, p, _length) == 0)) + (((s)->length == _length) && (memcmp((s)->start, p, _length) == 0)) #define nxt_str_start(s, p, _length) \ - (((s)->length >= _length) && (nxt_memcmp((s)->start, p, _length) == 0)) + (((s)->length >= _length) && (memcmp((s)->start, p, _length) == 0)) #define nxt_strchr_eq(s, c) \ diff --git a/src/test/nxt_http_parse_test.c b/src/test/nxt_http_parse_test.c index 540309c1..5f1a518c 100644 --- a/src/test/nxt_http_parse_test.c +++ b/src/test/nxt_http_parse_test.c @@ -753,7 +753,7 @@ nxt_http_parse_test_request_line(nxt_http_request_parse_t *rp, return NXT_ERROR; } - if (nxt_memcmp(rp->version.str, test->version, 8) != 0) { + if (memcmp(rp->version.str, test->version, 8) != 0) { nxt_log_alert(log, "http parse test case failed:\n" " - request:\n\"%V\"\n" " - version: \"%*s\" (expected: \"%*s\")", request, diff --git a/src/test/nxt_tests.c b/src/test/nxt_tests.c index f5a1cbd4..03a2a1df 100644 --- a/src/test/nxt_tests.c +++ b/src/test/nxt_tests.c @@ -41,7 +41,7 @@ main(int argc, char **argv) #if (NXT_TEST_RTDTSC) if (nxt_process_argv[1] != NULL - && nxt_memcmp(nxt_process_argv[1], "rbm", 3) == 0) + && memcmp(nxt_process_argv[1], "rbm", 3) == 0) { if (nxt_rbtree1_mb_start(thr) != NXT_OK) { return 1; diff --git a/src/test/nxt_utf8_file_name_test.c b/src/test/nxt_utf8_file_name_test.c index 30546ffb..5723e19b 100644 --- a/src/test/nxt_utf8_file_name_test.c +++ b/src/test/nxt_utf8_file_name_test.c @@ -129,7 +129,7 @@ nxt_utf8_file_name_test(nxt_thread_t *thr) nxt_file_close(&task, &lc_file); - if (n != 4 || nxt_memcmp(utf8, test, 4) != 0) { + if (n != 4 || memcmp(utf8, test, 4) != 0) { nxt_log_alert(thr->log, "nxt_file_read() mismatch"); nxt_file_delete(lc_file.name); diff --git a/src/test/nxt_utf8_test.c b/src/test/nxt_utf8_test.c index bca9a737..31e5bff9 100644 --- a/src/test/nxt_utf8_test.c +++ b/src/test/nxt_utf8_test.c @@ -59,7 +59,7 @@ nxt_utf8_overlong(nxt_thread_t *thr, u_char *overlong, size_t len) size = (p != NULL) ? p - utf8 : 0; - if (len != size || nxt_memcmp(overlong, utf8, size) != 0) { + if (len != size || memcmp(overlong, utf8, size) != 0) { u = 0; for (i = 0; i < len; i++) { -- cgit From ebf02266a2cd663ad4744d3b8c07e211b8f38da1 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Wed, 2 Nov 2022 21:45:40 +0100 Subject: Removed the unsafe nxt_memchr() wrapper for memchr(3). The casts are unnecessary, since memchr(3)'s argument is 'const void *'. It might have been necessary in the times of K&R, where 'void *' didn't exist. Nowadays, it's unnecessary, and _very_ unsafe, since casts can hide all classes of bugs by silencing most compiler warnings. The changes from nxt_memchr() to memchr(3) were scripted: $ find src/ -type f \ | grep '\.[ch]$' \ | xargs sed -i 's/nxt_memchr/memchr/' Reviewed-by: Andrew Clayton Signed-off-by: Alejandro Colomar --- src/nxt_conf_validation.c | 12 ++++++------ src/nxt_controller.c | 2 +- src/nxt_h1proto.c | 2 +- src/nxt_http_route.c | 4 ++-- src/nxt_http_route_addr.c | 12 ++++++------ src/nxt_sockaddr.c | 8 ++++---- src/nxt_string.h | 4 ---- src/nxt_var.c | 2 +- src/nxt_var.h | 2 +- src/perl/nxt_perl_psgi.c | 2 +- 10 files changed, 23 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index f8242f6e..7fbe7e29 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -2710,12 +2710,12 @@ nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, "The environment name must not be empty."); } - if (nxt_memchr(name->start, '\0', name->length) != NULL) { + if (memchr(name->start, '\0', name->length) != NULL) { return nxt_conf_vldt_error(vldt, "The environment name must not " "contain null character."); } - if (nxt_memchr(name->start, '=', name->length) != NULL) { + if (memchr(name->start, '=', name->length) != NULL) { return nxt_conf_vldt_error(vldt, "The environment name must not " "contain '=' character."); } @@ -2727,7 +2727,7 @@ nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_get_string(value, &str); - if (nxt_memchr(str.start, '\0', str.length) != NULL) { + if (memchr(str.start, '\0', str.length) != NULL) { return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must " "not contain null character.", name); } @@ -2926,7 +2926,7 @@ nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) nxt_conf_get_string(value, &str); - if (nxt_memchr(str.start, '\0', str.length) != NULL) { + if (memchr(str.start, '\0', str.length) != NULL) { return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not " "contain strings with null character."); } @@ -2985,7 +2985,7 @@ nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, nxt_conf_get_string(value, &str); - if (nxt_memchr(str.start, '\0', str.length) != NULL) { + if (memchr(str.start, '\0', str.length) != NULL) { return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not " "contain strings with null character."); } @@ -3006,7 +3006,7 @@ nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) nxt_conf_get_string(value, &str); - if (nxt_memchr(str.start, '\0', str.length) != NULL) { + if (memchr(str.start, '\0', str.length) != NULL) { return nxt_conf_vldt_error(vldt, "The \"options\" array must not " "contain strings with null character."); } diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 5f3e55ef..b5e0d831 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -1637,7 +1637,7 @@ nxt_controller_process_cert(nxt_task_t *task, name.length = path->length - 1; name.start = path->start + 1; - p = nxt_memchr(name.start, '/', name.length); + p = memchr(name.start, '/', name.length); if (p != NULL) { name.length = p - name.start; diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 3acba088..1e37273f 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -2609,7 +2609,7 @@ nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, nxt_buf_mem_t *bm) p += 12; length -= 12; - p = nxt_memchr(p, '\n', length); + p = memchr(p, '\n', length); if (nxt_slow_path(p == NULL)) { return NXT_AGAIN; diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 9aa23899..1f2fe883 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -1016,7 +1016,7 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, if (type == NXT_HTTP_ROUTE_PATTERN_EXACT) { tmp.start = test.start; - p = nxt_memchr(test.start, '*', test.length); + p = memchr(test.start, '*', test.length); if (p == NULL) { /* No '*' found - EXACT pattern. */ @@ -1414,7 +1414,7 @@ nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, nxt_str_t *segments, nxt_memzero(segments, n * sizeof(nxt_str_t)); do { - p = nxt_memchr(rest.start, '/', rest.length); + p = memchr(rest.start, '/', rest.length); if (p != NULL) { n--; diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c index 06b30d29..5a0d7679 100644 --- a/src/nxt_http_route_addr.c +++ b/src/nxt_http_route_addr.c @@ -93,7 +93,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, inet6 = &pattern->addr.v6; - delim = nxt_memchr(addr.start, '-', addr.length); + delim = memchr(addr.start, '-', addr.length); if (delim != NULL) { len = delim - addr.start; if (nxt_slow_path(!nxt_valid_ipv6_blocks(addr.start, len))) { @@ -126,7 +126,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, goto parse_port; } - delim = nxt_memchr(addr.start, '/', addr.length); + delim = memchr(addr.start, '/', addr.length); if (delim != NULL) { cidr_prefix = nxt_int_parse(delim + 1, addr.start + addr.length - (delim + 1)); @@ -201,7 +201,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, base->addr_family = AF_INET; - delim = nxt_memchr(addr.start, ':', addr.length); + delim = memchr(addr.start, ':', addr.length); if (delim != NULL) { port.start = delim + 1; port.length = addr.start + addr.length - port.start; @@ -210,7 +210,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, inet = &pattern->addr.v4; - delim = nxt_memchr(addr.start, '-', addr.length); + delim = memchr(addr.start, '-', addr.length); if (delim != NULL) { inet->start = nxt_inet_addr(addr.start, delim - addr.start); if (nxt_slow_path(inet->start == INADDR_NONE)) { @@ -234,7 +234,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, goto parse_port; } - delim = nxt_memchr(addr.start, '/', addr.length); + delim = memchr(addr.start, '/', addr.length); if (delim != NULL) { cidr_prefix = nxt_int_parse(delim + 1, addr.start + addr.length - (delim + 1)); @@ -283,7 +283,7 @@ parse_port: return NXT_OK; } - delim = nxt_memchr(port.start, '-', port.length - 1); + delim = memchr(port.start, '-', port.length - 1); if (delim != NULL) { ret = nxt_int_parse(port.start, delim - port.start); if (nxt_slow_path(ret < 0 || ret > 65535)) { diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index a076f286..32941893 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -653,7 +653,7 @@ nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr) length = addr->length - 1; start = addr->start + 1; - end = nxt_memchr(start, ']', length); + end = memchr(start, ']', length); if (nxt_slow_path(end == NULL)) { return NULL; } @@ -723,7 +723,7 @@ nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr) in_addr_t inaddr; nxt_sockaddr_t *sa; - p = nxt_memchr(addr->start, ':', addr->length); + p = memchr(addr->start, ':', addr->length); if (p == NULL) { length = addr->length; @@ -964,11 +964,11 @@ nxt_inet6_probe(nxt_str_t *str) { u_char *colon, *end; - colon = nxt_memchr(str->start, ':', str->length); + colon = memchr(str->start, ':', str->length); if (colon != NULL) { end = str->start + str->length; - colon = nxt_memchr(colon + 1, ':', end - (colon + 1)); + colon = memchr(colon + 1, ':', end - (colon + 1)); } return (colon != NULL); diff --git a/src/nxt_string.h b/src/nxt_string.h index d021df69..18ea5490 100644 --- a/src/nxt_string.h +++ b/src/nxt_string.h @@ -66,10 +66,6 @@ nxt_cpymem(void *dst, const void *src, size_t length) (void) memmove(dst, src, length) -#define nxt_memchr(s, c, length) \ - memchr((char *) s, c, length) - - #define nxt_strcmp(s1, s2) \ strcmp((char *) s1, (char *) s2) diff --git a/src/nxt_var.c b/src/nxt_var.c index f55a2d30..15759eb4 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -456,7 +456,7 @@ nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, end = start + length; - p = nxt_memchr(start, '$', length); + p = memchr(start, '$', length); if (p == start) { *is_var = 1; diff --git a/src/nxt_var.h b/src/nxt_var.h index cc7ff502..34c8857a 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -41,7 +41,7 @@ typedef enum { nxt_inline nxt_bool_t nxt_is_var(nxt_str_t *str) { - return (nxt_memchr(str->start, '$', str->length) != NULL); + return (memchr(str->start, '$', str->length) != NULL); } diff --git a/src/perl/nxt_perl_psgi.c b/src/perl/nxt_perl_psgi.c index 0c1c1222..5e8d1aee 100644 --- a/src/perl/nxt_perl_psgi.c +++ b/src/perl/nxt_perl_psgi.c @@ -765,7 +765,7 @@ nxt_perl_psgi_result_status(PerlInterpreter *my_perl, SV *result) status.start = (u_char *) SvPV(*sv_status, status.length); - space = nxt_memchr(status.start, ' ', status.length); + space = memchr(status.start, ' ', status.length); if (space != NULL) { status.length = space - status.start; } -- cgit From 40d75c94a039f35505975736bb4f907ec456c9bd Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 15 Nov 2022 00:17:32 +0000 Subject: Optimization for the "--no-unix-sockets" case. --- src/python/nxt_python_asgi.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 40ea5e24..256bcdcc 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -738,42 +738,40 @@ fail: static PyObject * nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) { +#if (NXT_HAVE_UNIX_DOMAIN) size_t prefix_len; - nxt_str_t addr; PyObject *pair, *v; + nxt_str_t addr; 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_str_start(&addr, "unix:", prefix_len)) { -#if NXT_HAVE_UNIX_DOMAIN - pair = PyTuple_New(2); - if (nxt_slow_path(pair == NULL)) { - return NULL; - } + pair = PyTuple_New(2); + if (nxt_slow_path(pair == NULL)) { + return NULL; + } - addr.start += prefix_len; - addr.length -= prefix_len; + 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); + v = PyString_FromStringAndSize((const char *) addr.start, addr.length); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(pair); - return NULL; - } + return NULL; + } - PyTuple_SET_ITEM(pair, 0, v); - PyTuple_SET_ITEM(pair, 1, Py_None); + PyTuple_SET_ITEM(pair, 0, v); + PyTuple_SET_ITEM(pair, 1, Py_None); - return pair; + return pair; + } -#else - return NULL; #endif + return nxt_py_asgi_create_ip_address(sptr, len, port); } -- cgit From 3b970ed9345ee2fe27f15b43ff827630d38cc124 Mon Sep 17 00:00:00 2001 From: OutOfFocus4 Date: Tue, 13 Sep 2022 10:36:46 -0400 Subject: Removed dead code. Signed-off-by: Alejandro Colomar --- src/nxt_application.h | 1 - src/nxt_main_process.c | 12 ------------ src/python/nxt_python.c | 4 +--- 3 files changed, 1 insertion(+), 16 deletions(-) (limited to 'src') diff --git a/src/nxt_application.h b/src/nxt_application.h index 30a1a12f..239f357b 100644 --- a/src/nxt_application.h +++ b/src/nxt_application.h @@ -49,7 +49,6 @@ typedef struct { typedef struct { char *home; nxt_conf_value_t *path; - nxt_str_t module; char *callable; nxt_str_t protocol; uint32_t threads; diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 39a8e112..f21482d5 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -190,18 +190,6 @@ static nxt_conf_map_t nxt_python_app_conf[] = { offsetof(nxt_common_app_conf_t, u.python.path), }, - { - nxt_string("module"), - NXT_CONF_MAP_STR, - offsetof(nxt_common_app_conf_t, u.python.module), - }, - - { - nxt_string("callable"), - NXT_CONF_MAP_CSTRZ, - offsetof(nxt_common_app_conf_t, u.python.callable), - }, - { nxt_string("protocol"), NXT_CONF_MAP_STR, diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 188c4920..37204051 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -70,7 +70,7 @@ nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) int rc; size_t len, size; uint32_t next; - PyObject *obj, *module; + PyObject *obj; nxt_str_t proto, probe_proto, name; nxt_int_t ret, n, i; nxt_unit_ctx_t *unit_ctx; @@ -154,7 +154,6 @@ nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) } #endif - module = NULL; obj = NULL; python_init.ctx_data = NULL; @@ -307,7 +306,6 @@ fail: } Py_XDECREF(obj); - Py_XDECREF(module); nxt_python_atexit(); -- cgit From 6902cd14ad4e322be1c29564bc2e238d0a225e92 Mon Sep 17 00:00:00 2001 From: OutOfFocus4 Date: Sun, 6 Nov 2022 09:08:55 -0500 Subject: Refactored functions that set WSGI variables. Splitting `nxt_python_add_sptr` into several functions will make future additions easier. Signed-off-by: Alejandro Colomar --- src/python/nxt_python_wsgi.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index 3fb6ac3b..34afd9a9 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -63,6 +63,10 @@ static PyObject *nxt_python_copy_environ(nxt_unit_request_info_t *req); static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx); static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, nxt_unit_sptr_t *sptr, uint32_t size); +static int nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, + char *src, uint32_t size); +static int nxt_python_add_py_string(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value); static int nxt_python_add_field(nxt_python_ctx_t *pctx, nxt_unit_field_t *field, int n, uint32_t vl); static PyObject *nxt_python_field_name(const char *name, uint8_t len); @@ -692,10 +696,16 @@ static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, nxt_unit_sptr_t *sptr, uint32_t size) { - char *src; - PyObject *value; + return nxt_python_add_char(pctx, name, nxt_unit_sptr_get(sptr), size); +} - src = nxt_unit_sptr_get(sptr); + +static int +nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, + char *src, uint32_t size) +{ + int res; + PyObject *value; value = PyString_FromStringAndSize(src, size); if (nxt_slow_path(value == NULL)) { @@ -707,17 +717,25 @@ nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, return NXT_UNIT_ERROR; } + res = nxt_python_add_py_string(pctx, name, value); + + Py_DECREF(value); + + return res; +} + + +static int nxt_python_add_py_string(nxt_python_ctx_t *pctx, PyObject *name, + PyObject *value) +{ if (nxt_slow_path(PyDict_SetItem(pctx->environ, name, value) != 0)) { nxt_unit_req_error(pctx->req, "Python failed to set the \"%s\" environ value", PyUnicode_AsUTF8(name)); - Py_DECREF(value); return NXT_UNIT_ERROR; } - Py_DECREF(value); - return NXT_UNIT_OK; } -- cgit From 3711632c00f8538fd87ff1a14a028756f57239a2 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Sun, 20 Nov 2022 23:11:41 +0800 Subject: Var: improved variable parsing with empty names. Unit parsed the case of "$uri$$host" into unknown variables. This commit makes it invalid variable instead. --- src/nxt_var.c | 75 +++++++++++++++++++++++++---------------------------------- 1 file changed, 32 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/nxt_var.c b/src/nxt_var.c index 15759eb4..c4133544 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -61,8 +61,7 @@ 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); -static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, - nxt_bool_t *is_var); +static u_char *nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part); static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { @@ -340,7 +339,6 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, nxt_var_t *var; nxt_str_t part; nxt_uint_t n; - nxt_bool_t is_var; nxt_var_sub_t *subs; nxt_var_decl_t *decl; @@ -352,12 +350,12 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, end = p + str->length; while (p < end) { - p = nxt_var_next_part(p, end - p, &part, &is_var); + p = nxt_var_next_part(p, end, &part); if (nxt_slow_path(p == NULL)) { return NULL; } - if (is_var) { + if (part.start != NULL) { n++; } } @@ -386,9 +384,9 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, p = str->start; while (p < end) { - next = nxt_var_next_part(p, end - p, &part, &is_var); + next = nxt_var_next_part(p, end, &part); - if (is_var) { + if (part.start != NULL) { decl = nxt_var_decl_get(&part, fields, &index); if (nxt_slow_path(decl == NULL)) { return NULL; @@ -413,14 +411,13 @@ nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) { u_char *p, *end, *next; nxt_str_t part; - nxt_bool_t is_var; nxt_var_decl_t *decl; p = str->start; end = p + str->length; while (p < end) { - next = nxt_var_next_part(p, end - p, &part, &is_var); + next = nxt_var_next_part(p, end, &part); if (next == NULL) { nxt_sprintf(error, error + NXT_MAX_ERROR_STR, @@ -429,7 +426,7 @@ nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) return NXT_ERROR; } - if (is_var) { + if (part.start != NULL) { decl = nxt_var_decl_get(&part, fields, NULL); if (decl == NULL) { @@ -448,19 +445,15 @@ nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) static u_char * -nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, - nxt_bool_t *is_var) +nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part) { - u_char *p, *end, ch, c; + size_t length; + u_char *p, ch, c; nxt_bool_t bracket; - end = start + length; - - p = memchr(start, '$', length); + p = memchr(start, '$', end - start); if (p == start) { - *is_var = 1; - p++; if (p == end) { @@ -480,48 +473,44 @@ nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, bracket = 0; } + length = 0; start = p; - for ( ;; ) { + while (p < end) { ch = *p; c = (u_char) (ch | 0x20); - if ((c < 'a' || c > 'z') && ch != '_') { - - if (bracket && ch != '}') { - return NULL; - } - break; + if ((c >= 'a' && c <= 'z') || ch == '_') { + p++; + length++; + continue; } - p++; + if (bracket && ch == '}') { + p++; + bracket = 0; + } - if (p == end) { - if (bracket) { - return NULL; - } + break; + } - break; - } + if (bracket || length == 0) { + return NULL; } - length = p - start; - end = p + bracket; + part->length = length; + part->start = start; } else { - *is_var = 0; - - if (p != NULL) { - length = p - start; - end = p; + if (p == NULL) { + p = end; } - } - part->length = length; - part->start = start; + nxt_str_null(part); + } - return end; + return p; } -- cgit From 4735931ace321752c387dae04c8b217ef22897ee Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Sun, 20 Nov 2022 23:15:01 +0800 Subject: Var: separating nxt_tstr_t from nxt_var_t. It's for the introduction of njs support. For each option that supports native variable and JS template literals introduced next, it's unified as template string. No functional changes. --- src/nxt_conf.h | 2 +- src/nxt_conf_validation.c | 6 +- src/nxt_http.h | 5 +- src/nxt_http_request.c | 4 +- src/nxt_http_return.c | 30 +++--- src/nxt_http_route.c | 44 +++++---- src/nxt_http_static.c | 52 ++++++----- src/nxt_http_variables.c | 6 +- src/nxt_main.h | 1 + src/nxt_router.c | 4 +- src/nxt_router.h | 6 +- src/nxt_router_access_log.c | 27 +++--- src/nxt_tstr.c | 223 ++++++++++++++++++++++++++++++++++++++++++++ src/nxt_tstr.h | 45 +++++++++ src/nxt_var.c | 148 +++++------------------------ src/nxt_var.h | 25 ++--- 16 files changed, 402 insertions(+), 226 deletions(-) create mode 100644 src/nxt_tstr.c create mode 100644 src/nxt_tstr.h (limited to 'src') diff --git a/src/nxt_conf.h b/src/nxt_conf.h index c8a276c0..1b13f5ae 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -72,7 +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_tstr_state_t *tstr_state; 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 7fbe7e29..09b3be55 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -1227,8 +1227,8 @@ 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)) { + vldt->tstr_state = nxt_tstr_state_new(vldt->pool); + if (nxt_slow_path(vldt->tstr_state == NULL)) { return NXT_ERROR; } @@ -1364,7 +1364,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, vldt->var_fields, error) != NXT_OK) { + if (nxt_tstr_test(vldt->tstr_state, value, 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 d5bff712..e29fe60a 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -169,7 +169,8 @@ struct nxt_http_request_s { nxt_timer_t timer; void *timer_data; - nxt_var_query_t *var_query; + nxt_tstr_query_t *tstr_query; + nxt_var_cache_t var_cache; void *req_rpc_data; @@ -245,7 +246,7 @@ struct nxt_http_action_s { nxt_http_route_t *route; nxt_upstream_t *upstream; uint32_t upstream_number; - nxt_var_t *var; + nxt_tstr_t *tstr; nxt_str_t *pass; } u; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 5c1455bf..84a67415 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -282,6 +282,8 @@ nxt_http_request_create(nxt_task_t *task) task->thread->engine->requests_cnt++; + r->var_cache.pool = mp; + return r; fail: @@ -795,7 +797,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_tstr_t *log_format; nxt_http_proto_t proto; nxt_http_request_t *r; nxt_http_protocol_t protocol; diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c index 9f3c4fc5..63c7e06f 100644 --- a/src/nxt_http_return.c +++ b/src/nxt_http_return.c @@ -9,7 +9,7 @@ typedef struct { nxt_http_status_t status; - nxt_var_t *location; + nxt_tstr_t *location; nxt_str_t encoded; } nxt_http_return_conf_t; @@ -25,7 +25,7 @@ static nxt_http_action_t *nxt_http_return(nxt_task_t *task, static nxt_int_t nxt_http_return_encode(nxt_mp_t *mp, nxt_str_t *encoded, const nxt_str_t *location); static void nxt_http_return_send_ready(nxt_task_t *task, void *obj, void *data); -static void nxt_http_return_var_error(nxt_task_t *task, void *obj, void *data); +static void nxt_http_return_send_error(nxt_task_t *task, void *obj, void *data); static const nxt_http_request_state_t nxt_http_return_send_state; @@ -57,13 +57,13 @@ nxt_http_return_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, nxt_conf_get_string(acf->location, &str); - conf->location = nxt_var_compile(&str, mp, rtcf->var_fields, 0); + conf->location = nxt_tstr_compile(rtcf->tstr_state, &str, 0); if (nxt_slow_path(conf->location == NULL)) { return NXT_ERROR; } - if (nxt_var_is_const(conf->location)) { - nxt_var_raw(conf->location, &str); + if (nxt_tstr_is_const(conf->location)) { + nxt_tstr_str(conf->location, &str); return nxt_http_return_encode(mp, &conf->encoded, &str); } @@ -76,6 +76,7 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { nxt_int_t ret; + nxt_router_conf_t *rtcf; nxt_http_return_ctx_t *ctx; nxt_http_return_conf_t *conf; @@ -88,7 +89,7 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_str_set(&loc, ""); } else { - nxt_var_raw(conf->location, &loc); + nxt_tstr_str(conf->location, &loc); } nxt_debug(task, "http return: %d (loc: \"%V\")", conf->status, &loc); @@ -114,7 +115,7 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, r->status = conf->status; r->resp.content_length_n = 0; - if (ctx == NULL || nxt_var_is_const(conf->location)) { + if (ctx == NULL || nxt_tstr_is_const(conf->location)) { if (ctx != NULL) { ctx->encoded = conf->encoded; } @@ -122,16 +123,19 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, nxt_http_return_send_ready(task, r, ctx); } else { - ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->var_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } - nxt_var_query(task, r->var_query, conf->location, &ctx->location); + nxt_tstr_query(task, r->tstr_query, conf->location, &ctx->location); - nxt_var_query_resolve(task, r->var_query, ctx, - nxt_http_return_send_ready, - nxt_http_return_var_error); + nxt_tstr_query_resolve(task, r->tstr_query, ctx, + nxt_http_return_send_ready, + nxt_http_return_send_error); } return NULL; @@ -213,7 +217,7 @@ fail: static void -nxt_http_return_var_error(nxt_task_t *task, void *obj, void *data) +nxt_http_return_send_error(nxt_task_t *task, void *obj, void *data) { nxt_http_request_t *r; diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 1f2fe883..77a59e9c 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -193,8 +193,8 @@ static nxt_int_t nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action); static nxt_http_action_t *nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action); -static void nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data); -static void nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data); +static void nxt_http_pass_query_ready(nxt_task_t *task, void *obj, void *data); +static void nxt_http_pass_query_error(nxt_task_t *task, void *obj, void *data); static nxt_int_t nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, nxt_str_t *pass, nxt_http_action_t *action); static nxt_int_t nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, @@ -673,8 +673,8 @@ 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, rtcf->var_fields, 0); - if (nxt_slow_path(action->u.var == NULL)) { + action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, &pass, 0); + if (nxt_slow_path(action->u.tstr == NULL)) { return NXT_ERROR; } @@ -1272,8 +1272,8 @@ nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, return NXT_OK; } - if (nxt_var_is_const(action->u.var)) { - nxt_var_raw(action->u.var, &pass); + if (nxt_tstr_is_const(action->u.tstr)) { + nxt_tstr_str(action->u.tstr, &pass); ret = nxt_http_pass_find(tmcf->mem_pool, tmcf->router_conf, &pass, action); @@ -1293,17 +1293,21 @@ static nxt_http_action_t * nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { - nxt_int_t ret; - nxt_str_t str; - nxt_var_t *var; + nxt_int_t ret; + nxt_str_t str; + nxt_tstr_t *tstr; + nxt_router_conf_t *rtcf; - var = action->u.var; + tstr = action->u.tstr; - nxt_var_raw(var, &str); + nxt_tstr_str(tstr, &str); nxt_debug(task, "http pass: \"%V\"", &str); - ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->var_cache, + r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } @@ -1316,10 +1320,10 @@ nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, action->u.pass = nxt_pointer_to(action, sizeof(nxt_http_action_t)); - nxt_var_query(task, r->var_query, var, action->u.pass); - nxt_var_query_resolve(task, r->var_query, action, - nxt_http_pass_var_ready, - nxt_http_pass_var_error); + nxt_tstr_query(task, r->tstr_query, tstr, action->u.pass); + nxt_tstr_query_resolve(task, r->tstr_query, action, + nxt_http_pass_query_ready, + nxt_http_pass_query_error); return NULL; fail: @@ -1330,7 +1334,7 @@ fail: static void -nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data) +nxt_http_pass_query_ready(nxt_task_t *task, void *obj, void *data) { nxt_int_t ret; nxt_router_conf_t *rtcf; @@ -1359,7 +1363,7 @@ nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data) static void -nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data) +nxt_http_pass_query_error(nxt_task_t *task, void *obj, void *data) { nxt_http_request_t *r; @@ -1497,8 +1501,8 @@ nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, return NULL; } - action->u.var = nxt_var_compile(pass, mp, rtcf->var_fields, 0); - if (nxt_slow_path(action->u.var == NULL)) { + action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, pass, 0); + if (nxt_slow_path(action->u.tstr == NULL)) { return NULL; } diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 0507e038..7143ecd3 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -8,7 +8,7 @@ typedef struct { - nxt_var_t *var; + nxt_tstr_t *tstr; #if (NXT_HAVE_OPENAT2) u_char *fname; #endif @@ -21,7 +21,7 @@ typedef struct { nxt_http_static_share_t *shares; nxt_str_t index; #if (NXT_HAVE_OPENAT2) - nxt_var_t *chroot; + nxt_tstr_t *chroot; nxt_uint_t resolve; #endif nxt_http_route_rule_t *types; @@ -48,7 +48,7 @@ static nxt_http_action_t *nxt_http_static(nxt_task_t *task, static void nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_http_static_ctx_t *ctx); static void nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data); -static void nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data); +static void nxt_http_static_send_error(nxt_task_t *task, void *obj, void *data); static void nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, nxt_http_static_ctx_t *ctx, nxt_http_status_t status); #if (NXT_HAVE_OPENAT2) @@ -77,7 +77,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, uint32_t i; nxt_mp_t *mp; nxt_str_t str, *ret; - nxt_var_t *var; + nxt_tstr_t *tstr; nxt_conf_value_t *cv; nxt_router_conf_t *rtcf; nxt_http_static_conf_t *conf; @@ -104,13 +104,13 @@ 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, NXT_VAR_STRZ); - if (nxt_slow_path(var == NULL)) { + tstr = nxt_tstr_compile(rtcf->tstr_state, &str, NXT_TSTR_STRZ); + if (nxt_slow_path(tstr == NULL)) { return NXT_ERROR; } - conf->shares[i].var = var; - conf->shares[i].is_const = nxt_var_is_const(var); + conf->shares[i].tstr = tstr; + conf->shares[i].is_const = nxt_tstr_is_const(tstr); } if (acf->index == NULL) { @@ -130,20 +130,20 @@ 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, - NXT_VAR_STRZ); + conf->chroot = nxt_tstr_compile(rtcf->tstr_state, &acf->chroot, + NXT_TSTR_STRZ); if (nxt_slow_path(conf->chroot == NULL)) { return NXT_ERROR; } - is_const = nxt_var_is_const(conf->chroot); + is_const = nxt_tstr_is_const(conf->chroot); for (i = 0; i < conf->nshares; i++) { conf->shares[i].is_const &= is_const; if (conf->shares[i].is_const) { - nxt_var_raw(conf->chroot, &chr); - nxt_var_raw(conf->shares[i].var, &shr); + nxt_tstr_str(conf->chroot, &chr); + nxt_tstr_str(conf->shares[i].tstr, &shr); conf->shares[i].fname = nxt_http_static_chroot_match(chr.start, shr.start); @@ -229,6 +229,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_http_static_ctx_t *ctx) { nxt_int_t ret; + nxt_router_conf_t *rtcf; nxt_http_static_conf_t *conf; nxt_http_static_share_t *share; @@ -240,14 +241,14 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, nxt_str_t shr; nxt_str_t idx; - nxt_var_raw(share->var, &shr); + nxt_tstr_str(share->tstr, &shr); idx = conf->index; #if (NXT_HAVE_OPENAT2) nxt_str_t chr; if (conf->chroot != NULL) { - nxt_var_raw(conf->chroot, &chr); + nxt_tstr_str(conf->chroot, &chr); } else { nxt_str_set(&chr, ""); @@ -261,34 +262,37 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, #endif /* NXT_DEBUG */ if (share->is_const) { - nxt_var_raw(share->var, &ctx->share); + nxt_tstr_str(share->tstr, &ctx->share); #if (NXT_HAVE_OPENAT2) if (conf->chroot != NULL && ctx->share_idx == 0) { - nxt_var_raw(conf->chroot, &ctx->chroot); + nxt_tstr_str(conf->chroot, &ctx->chroot); } #endif nxt_http_static_send_ready(task, r, ctx); } else { - ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->var_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); return; } - nxt_var_query(task, r->var_query, share->var, &ctx->share); + nxt_tstr_query(task, r->tstr_query, share->tstr, &ctx->share); #if (NXT_HAVE_OPENAT2) if (conf->chroot != NULL && ctx->share_idx == 0) { - nxt_var_query(task, r->var_query, conf->chroot, &ctx->chroot); + nxt_tstr_query(task, r->tstr_query, conf->chroot, &ctx->chroot); } #endif - nxt_var_query_resolve(task, r->var_query, ctx, - nxt_http_static_send_ready, - nxt_http_static_var_error); + nxt_tstr_query_resolve(task, r->tstr_query, ctx, + nxt_http_static_send_ready, + nxt_http_static_send_error); } } @@ -658,7 +662,7 @@ fail: static void -nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data) +nxt_http_static_send_error(nxt_task_t *task, void *obj, void *data) { nxt_http_request_t *r; diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index eb341716..fa0244db 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -407,7 +407,7 @@ nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) rtcf = r->conf->socket_conf->router_conf; - vf = nxt_var_field_get(rtcf->var_fields, field); + vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field); args = nxt_http_arguments_parse(r); if (nxt_slow_path(args == NULL)) { @@ -450,7 +450,7 @@ nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) rtcf = r->conf->socket_conf->router_conf; - vf = nxt_var_field_get(rtcf->var_fields, field); + vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field); nxt_list_each(f, r->fields) { @@ -485,7 +485,7 @@ nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) rtcf = r->conf->socket_conf->router_conf; - vf = nxt_var_field_get(rtcf->var_fields, field); + vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field); cookies = nxt_http_cookies_parse(r); if (nxt_slow_path(cookies == NULL)) { diff --git a/src/nxt_main.h b/src/nxt_main.h index a51a1ce7..b0cdc2d3 100644 --- a/src/nxt_main.h +++ b/src/nxt_main.h @@ -68,6 +68,7 @@ typedef uint16_t nxt_port_id_t; #include #include #include +#include /* TODO: remove unused */ diff --git a/src/nxt_router.c b/src/nxt_router.c index cfd79bf5..3ad78fa4 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1060,8 +1060,8 @@ 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)) { + rtcf->tstr_state = nxt_tstr_state_new(mp); + if (nxt_slow_path(rtcf->tstr_state == NULL)) { goto fail; } diff --git a/src/nxt_router.h b/src/nxt_router.h index a6add219..11094960 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -43,7 +43,7 @@ typedef struct { uint32_t threads; nxt_mp_t *mem_pool; - nxt_array_t *var_fields; /* of nxt_var_field_t */ + nxt_tstr_state_t *tstr_state; nxt_router_t *router; nxt_http_routes_t *routes; @@ -53,7 +53,7 @@ typedef struct { nxt_lvlhsh_t apps_hash; nxt_router_access_log_t *access_log; - nxt_var_t *log_format; + nxt_tstr_t *log_format; } nxt_router_conf_t; @@ -225,7 +225,7 @@ 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_var_t *format); + nxt_tstr_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 dc2a6687..9da366f4 100644 --- a/src/nxt_router_access_log.c +++ b/src/nxt_router_access_log.c @@ -24,7 +24,7 @@ typedef struct { static void nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, nxt_router_access_log_t *access_log, - nxt_var_t *format); + nxt_tstr_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, @@ -63,7 +63,7 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, u_char *p; nxt_int_t ret; nxt_str_t str; - nxt_var_t *format; + nxt_tstr_t *format; nxt_router_t *router; nxt_router_access_log_t *access_log; nxt_router_access_log_conf_t alcf; @@ -125,8 +125,7 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, 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); + format = nxt_tstr_compile(rtcf->tstr_state, &str, NXT_TSTR_LOGGING); if (nxt_slow_path(format == NULL)) { return NXT_ERROR; } @@ -140,9 +139,10 @@ 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_var_t *format) + nxt_router_access_log_t *access_log, nxt_tstr_t *format) { nxt_int_t ret; + nxt_router_conf_t *rtcf; nxt_router_access_log_ctx_t *ctx; ctx = nxt_mp_get(r->mem_pool, sizeof(nxt_router_access_log_ctx_t)); @@ -152,21 +152,24 @@ nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, ctx->access_log = access_log; - if (nxt_var_is_const(format)) { - nxt_var_raw(format, &ctx->text); + if (nxt_tstr_is_const(format)) { + nxt_tstr_str(format, &ctx->text); nxt_router_access_log_write_ready(task, r, ctx); } else { - ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->var_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { return; } - 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); + nxt_tstr_query(task, r->tstr_query, format, &ctx->text); + nxt_tstr_query_resolve(task, r->tstr_query, ctx, + nxt_router_access_log_write_ready, + nxt_router_access_log_write_error); } } diff --git a/src/nxt_tstr.c b/src/nxt_tstr.c new file mode 100644 index 00000000..dff61952 --- /dev/null +++ b/src/nxt_tstr.c @@ -0,0 +1,223 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include + + +typedef enum { + NXT_TSTR_CONST = 0, + NXT_TSTR_VAR, +} nxt_tstr_type_t; + + +struct nxt_tstr_s { + nxt_str_t str; + nxt_var_t *var; + nxt_tstr_flags_t flags; + nxt_tstr_type_t type; +}; + + +struct nxt_tstr_query_s { + nxt_mp_t *pool; + + nxt_tstr_state_t *state; + nxt_var_cache_t *cache; + + nxt_uint_t waiting; + nxt_uint_t failed; /* 1 bit */ + + void *ctx; + void *data; + + nxt_work_handler_t ready; + nxt_work_handler_t error; +}; + + +nxt_tstr_state_t * +nxt_tstr_state_new(nxt_mp_t *mp) +{ + nxt_tstr_state_t *state; + + state = nxt_mp_get(mp, sizeof(nxt_tstr_state_t)); + if (nxt_slow_path(state == NULL)) { + return NULL; + } + + state->pool = mp; + + state->var_fields = nxt_array_create(mp, 4, sizeof(nxt_var_field_t)); + if (nxt_slow_path(state->var_fields == NULL)) { + return NULL; + } + + return state; +} + + +nxt_tstr_t * +nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str, + nxt_tstr_flags_t flags) +{ + u_char *p; + nxt_tstr_t *tstr; + nxt_bool_t strz; + + strz = (flags & NXT_TSTR_STRZ) != 0; + + tstr = nxt_mp_get(state->pool, sizeof(nxt_tstr_t)); + if (nxt_slow_path(tstr == NULL)) { + return NULL; + } + + tstr->str.length = str->length + strz; + + tstr->str.start = nxt_mp_nget(state->pool, tstr->str.length); + if (nxt_slow_path(tstr->str.start == NULL)) { + return NULL; + } + + p = nxt_cpymem(tstr->str.start, str->start, str->length); + + if (strz) { + *p = '\0'; + } + + tstr->flags = flags; + + p = nxt_memchr(str->start, '$', str->length); + + if (p != NULL) { + tstr->type = NXT_TSTR_VAR; + + tstr->var = nxt_var_compile(&tstr->str, state->pool, state->var_fields); + if (nxt_slow_path(tstr->var == NULL)) { + return NULL; + } + + } else { + tstr->type = NXT_TSTR_CONST; + } + + return tstr; +} + + +nxt_int_t +nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error) +{ + return nxt_var_test(str, state->var_fields, error); +} + + +nxt_bool_t +nxt_tstr_is_const(nxt_tstr_t *tstr) +{ + return (tstr->type == NXT_TSTR_CONST); +} + + +void +nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str) +{ + *str = tstr->str; + + if (tstr->flags & NXT_TSTR_STRZ) { + str->length--; + } +} + + +nxt_int_t +nxt_tstr_query_init(nxt_tstr_query_t **query_p, nxt_tstr_state_t *state, + nxt_var_cache_t *cache, void *ctx, nxt_mp_t *mp) +{ + nxt_tstr_query_t *query; + + query = *query_p; + + if (*query_p == NULL) { + query = nxt_mp_zget(mp, sizeof(nxt_tstr_query_t)); + if (nxt_slow_path(query == NULL)) { + return NXT_ERROR; + } + } + + query->pool = mp; + query->state = state; + query->cache = cache; + query->ctx = ctx; + + *query_p = query; + + return NXT_OK; +} + + +void +nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, + nxt_str_t *val) +{ + nxt_int_t ret; + + if (nxt_tstr_is_const(tstr)) { + nxt_tstr_str(tstr, val); + return; + } + + if (nxt_slow_path(query->failed)) { + return; + } + + ret = nxt_var_interpreter(task, query->cache, tstr->var, val, query->ctx, + tstr->flags & NXT_TSTR_LOGGING); + if (nxt_slow_path(ret != NXT_OK)) { + query->failed = 1; + return; + } + + if (tstr->flags & NXT_TSTR_STRZ) { + val->length--; + } + +#if (NXT_DEBUG) + nxt_str_t str; + + nxt_tstr_str(tstr, &str); + + nxt_debug(task, "tstr: \"%V\" -> \"%V\"", &str, val); +#endif +} + + +void +nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query, void *data, + nxt_work_handler_t ready, nxt_work_handler_t error) +{ + query->data = data; + query->ready = ready; + query->error = error; + + if (query->waiting == 0) { + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); + } +} + + +void +nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query, + nxt_bool_t failed) +{ + query->failed |= failed; + + if (--query->waiting == 0) { + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); + } +} diff --git a/src/nxt_tstr.h b/src/nxt_tstr.h new file mode 100644 index 00000000..692b9d28 --- /dev/null +++ b/src/nxt_tstr.h @@ -0,0 +1,45 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_TSTR_H_INCLUDED_ +#define _NXT_TSTR_H_INCLUDED_ + + +typedef struct nxt_tstr_s nxt_tstr_t; +typedef struct nxt_tstr_query_s nxt_tstr_query_t; + + +typedef struct { + nxt_mp_t *pool; + nxt_array_t *var_fields; +} nxt_tstr_state_t; + + +typedef enum { + NXT_TSTR_STRZ = 1 << 0, + NXT_TSTR_LOGGING = 1 << 1, +} nxt_tstr_flags_t; + + +nxt_tstr_state_t *nxt_tstr_state_new(nxt_mp_t *mp); +nxt_tstr_t *nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str, + nxt_tstr_flags_t flags); +nxt_int_t nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error); + +nxt_bool_t nxt_tstr_is_const(nxt_tstr_t *tstr); +void nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str); + +nxt_int_t nxt_tstr_query_init(nxt_tstr_query_t **query_p, + nxt_tstr_state_t *state, nxt_var_cache_t *cache, void *ctx, + nxt_mp_t *mp); +void nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, + nxt_str_t *val); +void nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query, + void *data, nxt_work_handler_t ready, nxt_work_handler_t error); +void nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query, + nxt_bool_t failed); + + +#endif /* _NXT_TSTR_H_INCLUDED_ */ diff --git a/src/nxt_var.c b/src/nxt_var.c index c4133544..e113969f 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -9,7 +9,6 @@ struct nxt_var_s { size_t length; nxt_uint_t vars; - nxt_var_flags_t flags; u_char data[]; /* @@ -29,8 +28,7 @@ typedef struct { struct nxt_var_query_s { nxt_mp_t *pool; - nxt_lvlhsh_t cache; - nxt_str_t *spare; + nxt_var_cache_t cache; nxt_uint_t waiting; nxt_uint_t failed; /* 1 bit */ @@ -58,8 +56,8 @@ 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); +static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, + uint32_t index, void *ctx); static u_char *nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part); @@ -232,21 +230,22 @@ 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) +nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index, + void *ctx) { nxt_int_t ret; nxt_str_t *value; nxt_lvlhsh_query_t lhq; - value = query->spare; + value = cache->spare; if (value == NULL) { - value = nxt_mp_zget(query->pool, sizeof(nxt_str_t)); + value = nxt_mp_zget(cache->pool, sizeof(nxt_str_t)); if (nxt_slow_path(value == NULL)) { return NULL; } - query->spare = value; + cache->spare = value; } lhq.key_hash = nxt_murmur_hash2_uint32(&index); @@ -255,21 +254,20 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index) lhq.key.start = (u_char *) &index; lhq.value = value; lhq.proto = &nxt_var_cache_proto; - lhq.pool = query->pool; + lhq.pool = cache->pool; - ret = nxt_lvlhsh_insert(&query->cache, &lhq); + ret = nxt_lvlhsh_insert(&cache->hash, &lhq); if (nxt_slow_path(ret == NXT_ERROR)) { return NULL; } if (ret == NXT_OK) { - ret = nxt_var_index[index >> 16](task, value, query->ctx, - index & 0xffff); + ret = nxt_var_index[index >> 16](task, value, ctx, index & 0xffff); if (nxt_slow_path(ret != NXT_OK)) { return NULL; } - query->spare = NULL; + cache->spare = NULL; } return lhq.value; @@ -329,21 +327,17 @@ nxt_var_index_init(void) nxt_var_t * -nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, - nxt_var_flags_t flags) +nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields) { 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; nxt_var_sub_t *subs; nxt_var_decl_t *decl; - strz = (flags & NXT_VAR_STRZ) != 0; - n = 0; p = str->start; @@ -362,24 +356,19 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, size = sizeof(nxt_var_t) + n * sizeof(nxt_var_sub_t) + str->length; - var = nxt_mp_get(mp, size + strz); + var = nxt_mp_get(mp, size); if (nxt_slow_path(var == NULL)) { return NULL; } var->length = str->length; var->vars = n; - var->flags = flags; subs = nxt_var_subs(var); src = nxt_var_raw_start(var); nxt_memcpy(src, str->start, str->length); - if (strz) { - src[str->length] = '\0'; - } - n = 0; p = str->start; @@ -514,84 +503,33 @@ nxt_var_next_part(u_char *start, u_char *end, 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) -{ - nxt_var_query_t *query; - - query = *query_p; - - if (*query_p == NULL) { - query = nxt_mp_zget(mp, sizeof(nxt_var_query_t)); - if (nxt_slow_path(query == NULL)) { - return NXT_ERROR; - } - } - - query->pool = mp; - query->ctx = ctx; - - *query_p = query; - - return NXT_OK; -} - - -void -nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, - nxt_str_t *str) +nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, nxt_var_t *var, + nxt_str_t *str, void *ctx, nxt_bool_t logging) { u_char *p, *src; 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; - if (nxt_var_is_const(var)) { - nxt_var_raw(var, str); - return; - } - - if (nxt_slow_path(query->failed)) { - return; - } - 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; + nxt_array_init(&parts, cache->pool, sizeof(nxt_str_t *)); subs = nxt_var_subs(var); length = var->length; for (i = 0; i < var->vars; i++) { - value = nxt_var_cache_value(task, query, subs[i].index); + value = nxt_var_cache_value(task, cache, subs[i].index, ctx); if (nxt_slow_path(value == NULL)) { - goto fail; + return NXT_ERROR; } part = nxt_array_add(&parts); if (nxt_slow_path(part == NULL)) { - goto fail; + return NXT_ERROR; } *part = value; @@ -603,9 +541,9 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, } } - p = nxt_mp_nget(query->pool, length + strz); + p = nxt_mp_nget(cache->pool, length); if (nxt_slow_path(p == NULL)) { - goto fail; + return NXT_ERROR; } str->length = length; @@ -636,45 +574,5 @@ 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 (strz) { - *p = '\0'; - } - - nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str); - - return; - -fail: - - query->failed = 1; -} - - -void -nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, - nxt_work_handler_t ready, nxt_work_handler_t error) -{ - query->data = data; - query->ready = ready; - query->error = error; - - if (query->waiting == 0) { - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - query->failed ? query->error : query->ready, - task, query->ctx, query->data); - } -} - - -void -nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, - nxt_bool_t failed) -{ - query->failed |= failed; - - if (--query->waiting == 0) { - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - query->failed ? query->error : query->ready, - task, query->ctx, query->data); - } + return NXT_OK; } diff --git a/src/nxt_var.h b/src/nxt_var.h index 34c8857a..2c6f13bd 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -32,10 +32,11 @@ typedef struct { } nxt_var_field_t; -typedef enum { - NXT_VAR_STRZ = 1 << 0, - NXT_VAR_LOGGING = 1 << 1, -} nxt_var_flags_t; +typedef struct { + nxt_mp_t *pool; + nxt_lvlhsh_t hash; + nxt_str_t *spare; +} nxt_var_cache_t; nxt_inline nxt_bool_t @@ -50,21 +51,11 @@ 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_var_flags_t flags); +nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields); 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); -void nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, - nxt_var_t *var, nxt_str_t *str); -void nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, - nxt_work_handler_t ready, nxt_work_handler_t error); -void nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, - nxt_bool_t failed); +nxt_int_t nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, + nxt_var_t *var, nxt_str_t *str, void *ctx, nxt_bool_t logging); #endif /* _NXT_VAR_H_INCLUDED_ */ -- cgit From 4d6d146e920667a8afeacd355e4fb6a94387066e Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Sun, 20 Nov 2022 23:16:51 +0800 Subject: Basic njs support. --- src/nxt_conf_validation.c | 33 ++++--- src/nxt_http.h | 2 +- src/nxt_http_request.c | 2 +- src/nxt_http_return.c | 2 +- src/nxt_http_route.c | 2 +- src/nxt_http_static.c | 2 +- src/nxt_js.c | 230 ++++++++++++++++++++++++++++++++++++++++++++ src/nxt_js.h | 34 +++++++ src/nxt_router.c | 7 +- src/nxt_router_access_log.c | 2 +- src/nxt_tstr.c | 128 ++++++++++++++++++++---- src/nxt_tstr.h | 38 +++++++- src/nxt_var.h | 7 -- 13 files changed, 445 insertions(+), 44 deletions(-) create mode 100644 src/nxt_js.c create mode 100644 src/nxt_js.h (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 09b3be55..e650b44d 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -34,7 +34,7 @@ typedef enum { typedef enum { NXT_CONF_VLDT_REQUIRED = 1 << 0, - NXT_CONF_VLDT_VAR = 1 << 1, + NXT_CONF_VLDT_TSTR = 1 << 1, } nxt_conf_vldt_flags_t; @@ -367,7 +367,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { .name = nxt_string("pass"), .type = NXT_CONF_VLDT_STRING, .validator = nxt_conf_vldt_pass, - .flags = NXT_CONF_VLDT_VAR, + .flags = NXT_CONF_VLDT_TSTR, }, { .name = nxt_string("application"), .type = NXT_CONF_VLDT_STRING, @@ -652,7 +652,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = { .name = nxt_string("pass"), .type = NXT_CONF_VLDT_STRING, .validator = nxt_conf_vldt_pass, - .flags = NXT_CONF_VLDT_VAR, + .flags = NXT_CONF_VLDT_TSTR, }, NXT_CONF_VLDT_END @@ -667,7 +667,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = { }, { .name = nxt_string("location"), .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_VAR, + .flags = NXT_CONF_VLDT_TSTR, }, NXT_CONF_VLDT_END @@ -697,7 +697,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { .validator = nxt_conf_vldt_unsupported, .u.string = "chroot", #endif - .flags = NXT_CONF_VLDT_VAR, + .flags = NXT_CONF_VLDT_TSTR, }, { .name = nxt_string("follow_symlinks"), .type = NXT_CONF_VLDT_BOOLEAN, @@ -1226,8 +1226,9 @@ nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt) { nxt_int_t ret; + u_char error[NXT_MAX_ERROR_STR]; - vldt->tstr_state = nxt_tstr_state_new(vldt->pool); + vldt->tstr_state = nxt_tstr_state_new(vldt->pool, 1); if (nxt_slow_path(vldt->tstr_state == NULL)) { return NXT_ERROR; } @@ -1237,7 +1238,17 @@ nxt_conf_validate(nxt_conf_validation_t *vldt) return ret; } - return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members); + ret = nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members); + if (ret != NXT_OK) { + return ret; + } + + ret = nxt_tstr_state_done(vldt->tstr_state, error); + if (ret != NXT_OK) { + return nxt_conf_vldt_error(vldt, "%s", error); + } + + return NXT_OK; } @@ -1721,7 +1732,7 @@ nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt, nxt_conf_get_string(value, &str); - if (nxt_is_var(&str)) { + if (nxt_is_tstr(&str)) { return nxt_conf_vldt_var(vldt, &share, &str); } @@ -2501,12 +2512,12 @@ nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, continue; } - if (vals->flags & NXT_CONF_VLDT_VAR + if (vals->flags & NXT_CONF_VLDT_TSTR && nxt_conf_type(member) == NXT_CONF_STRING) { nxt_conf_get_string(member, &var); - if (nxt_is_var(&var)) { + if (nxt_is_tstr(&var)) { ret = nxt_conf_vldt_var(vldt, &name, &var); if (ret != NXT_OK) { return ret; @@ -3147,7 +3158,7 @@ nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, "The \"path\" string must not be empty."); } - if (nxt_is_var(&conf.format)) { + if (nxt_is_tstr(&conf.format)) { return nxt_conf_vldt_var(vldt, &format_str, &conf.format); } diff --git a/src/nxt_http.h b/src/nxt_http.h index e29fe60a..a8725d9f 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -170,7 +170,7 @@ struct nxt_http_request_s { void *timer_data; nxt_tstr_query_t *tstr_query; - nxt_var_cache_t var_cache; + nxt_tstr_cache_t tstr_cache; void *req_rpc_data; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 84a67415..73ffd2f0 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -282,7 +282,7 @@ nxt_http_request_create(nxt_task_t *task) task->thread->engine->requests_cnt++; - r->var_cache.pool = mp; + r->tstr_cache.var.pool = mp; return r; diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c index 63c7e06f..b50e4ad0 100644 --- a/src/nxt_http_return.c +++ b/src/nxt_http_return.c @@ -126,7 +126,7 @@ nxt_http_return(nxt_task_t *task, nxt_http_request_t *r, rtcf = r->conf->socket_conf->router_conf; ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->var_cache, r, r->mem_pool); + &r->tstr_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 77a59e9c..7081ff7e 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -1306,7 +1306,7 @@ nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, rtcf = r->conf->socket_conf->router_conf; - ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->var_cache, + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { goto fail; diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 7143ecd3..68174b9d 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -276,7 +276,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, rtcf = r->conf->socket_conf->router_conf; ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->var_cache, r, r->mem_pool); + &r->tstr_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); return; diff --git a/src/nxt_js.c b/src/nxt_js.c new file mode 100644 index 00000000..52596fe6 --- /dev/null +++ b/src/nxt_js.c @@ -0,0 +1,230 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include + + +struct nxt_js_s { + uint32_t index; + njs_vm_t *vm; +}; + + +struct nxt_js_conf_s { + nxt_mp_t *pool; + njs_vm_t *vm; + nxt_array_t *funcs; +}; + + +nxt_js_conf_t * +nxt_js_conf_new(nxt_mp_t *mp) +{ + njs_vm_opt_t opts; + nxt_js_conf_t *jcf; + + jcf = nxt_mp_zget(mp, sizeof(nxt_js_conf_t)); + if (nxt_slow_path(jcf == NULL)) { + return NULL; + } + + jcf->pool = mp; + + njs_vm_opt_init(&opts); + + jcf->vm = njs_vm_create(&opts); + if (nxt_slow_path(jcf->vm == NULL)) { + return NULL; + } + + jcf->funcs = nxt_array_create(mp, 4, sizeof(nxt_str_t)); + if (nxt_slow_path(jcf->funcs == NULL)) { + return NULL; + } + + return jcf; +} + + +nxt_js_t * +nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz) +{ + size_t size; + u_char *p, *start; + nxt_js_t *js; + nxt_str_t *func; + + static nxt_str_t func_str = nxt_string("function() {" + " return "); + + /* + * Appending a terminating null character if strz is true. + */ + static nxt_str_t strz_str = nxt_string(" + '\\x00'"); + + size = func_str.length + str->length + 1; + + if (strz) { + size += strz_str.length; + } + + start = nxt_mp_nget(jcf->pool, size); + if (nxt_slow_path(start == NULL)) { + return NULL; + } + + p = start; + + p = nxt_cpymem(p, func_str.start, func_str.length); + p = nxt_cpymem(p, str->start, str->length); + + if (strz) { + p = nxt_cpymem(p, strz_str.start, strz_str.length); + } + + *p++ = '}'; + + js = nxt_mp_get(jcf->pool, sizeof(nxt_js_t)); + if (nxt_slow_path(js == NULL)) { + return NULL; + } + + js->vm = jcf->vm; + + func = nxt_array_add(jcf->funcs); + if (nxt_slow_path(func == NULL)) { + return NULL; + } + + func->start = start; + func->length = p - start; + + js->index = jcf->funcs->nelts - 1; + + return js; +} + + +nxt_int_t +nxt_js_compile(nxt_js_conf_t *jcf) +{ + size_t size; + u_char *p, *start; + njs_int_t ret; + nxt_str_t *func; + nxt_uint_t i; + + size = 2; + func = jcf->funcs->elts; + + for (i = 0; i < jcf->funcs->nelts; i++) { + size += func[i].length + 1; + } + + start = nxt_mp_nget(jcf->pool, size); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } + + p = start; + *p++ = '['; + + func = jcf->funcs->elts; + + for (i = 0; i < jcf->funcs->nelts; i++) { + p = nxt_cpymem(p, func[i].start, func[i].length); + *p++ = ','; + } + + *p++ = ']'; + + ret = njs_vm_compile(jcf->vm, &start, p); + + return (ret == NJS_OK) ? NXT_OK : NXT_ERROR; +} + + +nxt_int_t +nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error) +{ + u_char *start; + nxt_str_t err; + njs_int_t ret; + njs_str_t res; + + start = nxt_mp_nget(jcf->pool, str->length); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } + + nxt_memcpy(start, str->start, str->length); + + ret = njs_vm_compile(jcf->vm, &start, start + str->length); + + if (nxt_slow_path(ret != NJS_OK)) { + (void) njs_vm_retval_string(jcf->vm, &res); + + err.start = res.start; + err.length = res.length; + + nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "\"%V\"%Z", &err); + + return NXT_ERROR; + } + + return NXT_OK; +} + + +nxt_int_t +nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js, + nxt_str_t *str, void *ctx) +{ + njs_vm_t *vm; + njs_int_t rc, ret; + njs_str_t res; + njs_value_t *array, *value; + njs_function_t *func; + njs_opaque_value_t opaque_value; + + vm = cache->vm; + + if (vm == NULL) { + vm = njs_vm_clone(js->vm, ctx); + if (nxt_slow_path(vm == NULL)) { + return NXT_ERROR; + } + + ret = njs_vm_start(vm); + if (ret != NJS_OK) { + return NXT_ERROR; + } + + array = njs_vm_retval(vm); + + cache->vm = vm; + cache->array = *array; + } + + value = njs_vm_array_prop(vm, &cache->array, js->index, &opaque_value); + func = njs_value_function(value); + + ret = njs_vm_call(vm, func, NULL, 0); + + rc = njs_vm_retval_string(vm, &res); + if (rc != NJS_OK) { + return NXT_ERROR; + } + + if (ret != NJS_OK) { + nxt_alert(task, "js exception: %V", &res); + return NXT_ERROR; + } + + str->length = res.length; + str->start = res.start; + + return NXT_OK; +} diff --git a/src/nxt_js.h b/src/nxt_js.h new file mode 100644 index 00000000..321041ae --- /dev/null +++ b/src/nxt_js.h @@ -0,0 +1,34 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_JS_H_INCLUDED_ +#define _NXT_JS_H_INCLUDED_ + +#if (NXT_HAVE_NJS) + +#include + + +typedef struct nxt_js_s nxt_js_t; +typedef struct nxt_js_conf_s nxt_js_conf_t; + + +typedef struct { + njs_vm_t *vm; + njs_value_t array; +} nxt_js_cache_t; + + +nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp); +nxt_js_t *nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz); +nxt_int_t nxt_js_compile(nxt_js_conf_t *jcf); +nxt_int_t nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error); +nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js, + nxt_str_t *str, void *ctx); + + +#endif /* NXT_HAVE_NJS */ + +#endif /* _NXT_JS_H_INCLUDED_ */ diff --git a/src/nxt_router.c b/src/nxt_router.c index 3ad78fa4..26aa9fb1 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1060,7 +1060,7 @@ nxt_router_temp_conf(nxt_task_t *task) rtcf->mem_pool = mp; - rtcf->tstr_state = nxt_tstr_state_new(mp); + rtcf->tstr_state = nxt_tstr_state_new(mp, 0); if (nxt_slow_path(rtcf->tstr_state == NULL)) { goto fail; } @@ -2042,6 +2042,11 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } } + ret = nxt_tstr_state_done(rtcf->tstr_state, NULL); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + nxt_queue_add(&deleting_sockets, &router->sockets); nxt_queue_init(&router->sockets); diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c index 9da366f4..ccbddb96 100644 --- a/src/nxt_router_access_log.c +++ b/src/nxt_router_access_log.c @@ -161,7 +161,7 @@ nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, rtcf = r->conf->socket_conf->router_conf; ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, - &r->var_cache, r, r->mem_pool); + &r->tstr_cache, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { return; } diff --git a/src/nxt_tstr.c b/src/nxt_tstr.c index dff61952..fd01797c 100644 --- a/src/nxt_tstr.c +++ b/src/nxt_tstr.c @@ -9,12 +9,22 @@ typedef enum { NXT_TSTR_CONST = 0, NXT_TSTR_VAR, +#if (NXT_HAVE_NJS) + NXT_TSTR_JS, +#endif } nxt_tstr_type_t; struct nxt_tstr_s { nxt_str_t str; - nxt_var_t *var; + + union { + nxt_var_t *var; +#if (NXT_HAVE_NJS) + nxt_js_t *js; +#endif + } u; + nxt_tstr_flags_t flags; nxt_tstr_type_t type; }; @@ -24,7 +34,7 @@ struct nxt_tstr_query_s { nxt_mp_t *pool; nxt_tstr_state_t *state; - nxt_var_cache_t *cache; + nxt_tstr_cache_t *cache; nxt_uint_t waiting; nxt_uint_t failed; /* 1 bit */ @@ -37,8 +47,12 @@ struct nxt_tstr_query_s { }; +#define nxt_tstr_is_js(str) \ + nxt_strchr_start(str, '`') + + nxt_tstr_state_t * -nxt_tstr_state_new(nxt_mp_t *mp) +nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test) { nxt_tstr_state_t *state; @@ -48,12 +62,20 @@ nxt_tstr_state_new(nxt_mp_t *mp) } state->pool = mp; + state->test = test; state->var_fields = nxt_array_create(mp, 4, sizeof(nxt_var_field_t)); if (nxt_slow_path(state->var_fields == NULL)) { return NULL; } +#if (NXT_HAVE_NJS) + state->jcf = nxt_js_conf_new(mp); + if (nxt_slow_path(state->jcf == NULL)) { + return NULL; + } +#endif + return state; } @@ -88,18 +110,38 @@ nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str, tstr->flags = flags; - p = nxt_memchr(str->start, '$', str->length); + if (nxt_tstr_is_js(str)) { + +#if (NXT_HAVE_NJS) + + nxt_str_t tpl; - if (p != NULL) { - tstr->type = NXT_TSTR_VAR; + tstr->type = NXT_TSTR_JS; - tstr->var = nxt_var_compile(&tstr->str, state->pool, state->var_fields); - if (nxt_slow_path(tstr->var == NULL)) { + nxt_tstr_str(tstr, &tpl); + + tstr->u.js = nxt_js_add_tpl(state->jcf, &tpl, strz); + if (nxt_slow_path(tstr->u.js == NULL)) { return NULL; } +#endif + } else { - tstr->type = NXT_TSTR_CONST; + p = memchr(str->start, '$', str->length); + + if (p != NULL) { + tstr->type = NXT_TSTR_VAR; + + tstr->u.var = nxt_var_compile(&tstr->str, state->pool, + state->var_fields); + if (nxt_slow_path(tstr->u.var == NULL)) { + return NULL; + } + + } else { + tstr->type = NXT_TSTR_CONST; + } } return tstr; @@ -109,7 +151,46 @@ nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str, nxt_int_t nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error) { - return nxt_var_test(str, state->var_fields, error); + u_char *p; + + if (nxt_tstr_is_js(str)) { +#if (NXT_HAVE_NJS) + return nxt_js_test(state->jcf, str, error); + +#else + nxt_sprintf(error, error + NXT_MAX_ERROR_STR, + "Unit is built without support of njs: " + "\"--njs\" ./configure option is missing."); + return NXT_ERROR; +#endif + + } else { + p = memchr(str->start, '$', str->length); + + if (p != NULL) { + return nxt_var_test(str, state->var_fields, error); + } + } + + return NXT_OK; +} + + +nxt_int_t +nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error) +{ +#if (NXT_HAVE_NJS) + if (!state->test) { + nxt_int_t ret; + + ret = nxt_js_compile(state->jcf); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + } +#endif + + return NXT_OK; } @@ -133,7 +214,7 @@ nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str) nxt_int_t nxt_tstr_query_init(nxt_tstr_query_t **query_p, nxt_tstr_state_t *state, - nxt_var_cache_t *cache, void *ctx, nxt_mp_t *mp) + nxt_tstr_cache_t *cache, void *ctx, nxt_mp_t *mp) { nxt_tstr_query_t *query; @@ -172,11 +253,24 @@ nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, return; } - ret = nxt_var_interpreter(task, query->cache, tstr->var, val, query->ctx, - tstr->flags & NXT_TSTR_LOGGING); - if (nxt_slow_path(ret != NXT_OK)) { - query->failed = 1; - return; + if (tstr->type == NXT_TSTR_VAR) { + ret = nxt_var_interpreter(task, &query->cache->var, tstr->u.var, val, + query->ctx, tstr->flags & NXT_TSTR_LOGGING); + + if (nxt_slow_path(ret != NXT_OK)) { + query->failed = 1; + return; + } + + } else { +#if (NXT_HAVE_NJS) + ret = nxt_js_call(task, &query->cache->js, tstr->u.js, val, query->ctx); + + if (nxt_slow_path(ret != NXT_OK)) { + query->failed = 1; + return; + } +#endif } if (tstr->flags & NXT_TSTR_STRZ) { @@ -188,7 +282,7 @@ nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, nxt_tstr_str(tstr, &str); - nxt_debug(task, "tstr: \"%V\" -> \"%V\"", &str, val); + nxt_debug(task, "tstr query: \"%V\", result: \"%V\"", &str, val); #endif } diff --git a/src/nxt_tstr.h b/src/nxt_tstr.h index 692b9d28..0cc24292 100644 --- a/src/nxt_tstr.h +++ b/src/nxt_tstr.h @@ -7,6 +7,8 @@ #define _NXT_TSTR_H_INCLUDED_ +#include + typedef struct nxt_tstr_s nxt_tstr_t; typedef struct nxt_tstr_query_s nxt_tstr_query_t; @@ -14,25 +16,38 @@ typedef struct nxt_tstr_query_s nxt_tstr_query_t; typedef struct { nxt_mp_t *pool; nxt_array_t *var_fields; +#if (NXT_HAVE_NJS) + nxt_js_conf_t *jcf; +#endif + uint8_t test; /* 1 bit */ } nxt_tstr_state_t; +typedef struct { + nxt_var_cache_t var; +#if (NXT_HAVE_NJS) + nxt_js_cache_t js; +#endif +} nxt_tstr_cache_t; + + typedef enum { NXT_TSTR_STRZ = 1 << 0, NXT_TSTR_LOGGING = 1 << 1, } nxt_tstr_flags_t; -nxt_tstr_state_t *nxt_tstr_state_new(nxt_mp_t *mp); +nxt_tstr_state_t *nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test); nxt_tstr_t *nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str, nxt_tstr_flags_t flags); nxt_int_t nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error); +nxt_int_t nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error); nxt_bool_t nxt_tstr_is_const(nxt_tstr_t *tstr); void nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str); nxt_int_t nxt_tstr_query_init(nxt_tstr_query_t **query_p, - nxt_tstr_state_t *state, nxt_var_cache_t *cache, void *ctx, + nxt_tstr_state_t *state, nxt_tstr_cache_t *cache, void *ctx, nxt_mp_t *mp); void nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, nxt_str_t *val); @@ -42,4 +57,23 @@ void nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query, nxt_bool_t failed); +nxt_inline nxt_bool_t +nxt_is_tstr(nxt_str_t *str) +{ + u_char *p; + + p = memchr(str->start, '`', str->length); + if (p != NULL) { + return 1; + } + + p = memchr(str->start, '$', str->length); + if (p != NULL) { + return 1; + } + + return 0; +} + + #endif /* _NXT_TSTR_H_INCLUDED_ */ diff --git a/src/nxt_var.h b/src/nxt_var.h index 2c6f13bd..4f30a002 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -39,13 +39,6 @@ typedef struct { } nxt_var_cache_t; -nxt_inline nxt_bool_t -nxt_is_var(nxt_str_t *str) -{ - return (memchr(str->start, '$', str->length) != NULL); -} - - nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n); nxt_int_t nxt_var_index_init(void); -- cgit From e3bbf5b3b5be384a39bbd1c42d44379b17d94185 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Tue, 22 Nov 2022 10:13:18 +0800 Subject: NJS: added http request prototype. --- src/nxt_http_js.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nxt_js.c | 75 ++++++++++++++- src/nxt_js.h | 4 + src/nxt_router.c | 4 + src/nxt_runtime.h | 3 + src/nxt_var.h | 2 + 6 files changed, 358 insertions(+), 3 deletions(-) create mode 100644 src/nxt_http_js.c (limited to 'src') diff --git a/src/nxt_http_js.c b/src/nxt_http_js.c new file mode 100644 index 00000000..5a08a309 --- /dev/null +++ b/src/nxt_http_js.c @@ -0,0 +1,273 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include + + +static njs_int_t nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t nxt_http_js_ext_remote_addr(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t nxt_http_js_ext_get_arg(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t nxt_http_js_ext_get_header(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); +static njs_int_t nxt_http_js_ext_get_cookie(njs_vm_t *vm, + njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, + njs_value_t *retval); + + +static njs_external_t nxt_http_js_proto[] = { + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("uri"), + .enumerable = 1, + .u.property = { + .handler = nxt_http_js_ext_uri, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("host"), + .enumerable = 1, + .u.property = { + .handler = nxt_http_js_ext_host, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("remoteAddr"), + .enumerable = 1, + .u.property = { + .handler = nxt_http_js_ext_remote_addr, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("args"), + .enumerable = 1, + .u.object = { + .enumerable = 1, + .prop_handler = nxt_http_js_ext_get_arg, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("headers"), + .enumerable = 1, + .u.object = { + .enumerable = 1, + .prop_handler = nxt_http_js_ext_get_header, + } + }, + + { + .flags = NJS_EXTERN_OBJECT, + .name.string = njs_str("cookies"), + .enumerable = 1, + .u.object = { + .enumerable = 1, + .prop_handler = nxt_http_js_ext_get_cookie, + } + }, +}; + + +void +nxt_http_register_js_proto(nxt_js_conf_t *jcf) +{ + nxt_js_set_proto(jcf, nxt_http_js_proto, njs_nitems(nxt_http_js_proto)); +} + + +static njs_int_t +nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + return njs_vm_value_string_set(vm, retval, r->path->start, r->path->length); +} + + +static njs_int_t +nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + return njs_vm_value_string_set(vm, retval, r->host.start, r->host.length); +} + + +static njs_int_t +nxt_http_js_ext_remote_addr(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + return njs_vm_value_string_set(vm, retval, + nxt_sockaddr_address(r->remote), + r->remote->address_length); +} + + +static njs_int_t +nxt_http_js_ext_get_arg(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t rc; + njs_str_t key; + nxt_array_t *args; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start, *end; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + args = nxt_http_arguments_parse(r); + if (nxt_slow_path(args == NULL)) { + return NJS_ERROR; + } + + start = args->elts; + end = start + args->nelts; + + for (nv = start; nv < end; nv++) { + + if (key.length == nv->name_length + && memcmp(key.start, nv->name, nv->name_length) == 0) + { + return njs_vm_value_string_set(vm, retval, nv->value, + nv->value_length); + } + } + + njs_value_undefined_set(retval); + + return NJS_DECLINED; +} + + +static njs_int_t +nxt_http_js_ext_get_header(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t rc; + njs_str_t key; + nxt_http_field_t *f; + nxt_http_request_t *r; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + nxt_list_each(f, r->fields) { + + if (key.length == f->name_length + && memcmp(key.start, f->name, f->name_length) == 0) + { + return njs_vm_value_string_set(vm, retval, f->value, + f->value_length); + } + + } nxt_list_loop; + + njs_value_undefined_set(retval); + + return NJS_DECLINED; +} + + +static njs_int_t +nxt_http_js_ext_get_cookie(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t rc; + njs_str_t key; + nxt_array_t *cookies; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start, *end; + + r = njs_vm_external(vm, nxt_js_proto_id, value); + if (r == NULL) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + rc = njs_vm_prop_name(vm, prop, &key); + if (rc != NJS_OK) { + njs_value_undefined_set(retval); + return NJS_DECLINED; + } + + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return NJS_ERROR; + } + + start = cookies->elts; + end = start + cookies->nelts; + + for (nv = start; nv < end; nv++) { + + if (key.length == nv->name_length + && memcmp(key.start, nv->name, nv->name_length) == 0) + { + return njs_vm_value_string_set(vm, retval, nv->value, + nv->value_length); + } + } + + njs_value_undefined_set(retval); + + return NJS_DECLINED; +} diff --git a/src/nxt_js.c b/src/nxt_js.c index 52596fe6..aa3c4af5 100644 --- a/src/nxt_js.c +++ b/src/nxt_js.c @@ -15,10 +15,15 @@ struct nxt_js_s { struct nxt_js_conf_s { nxt_mp_t *pool; njs_vm_t *vm; + njs_uint_t protos; + njs_external_t *proto; nxt_array_t *funcs; }; +njs_int_t nxt_js_proto_id; + + nxt_js_conf_t * nxt_js_conf_new(nxt_mp_t *mp) { @@ -48,6 +53,14 @@ nxt_js_conf_new(nxt_mp_t *mp) } +void +nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, njs_uint_t n) +{ + jcf->protos = n; + jcf->proto = proto; +} + + nxt_js_t * nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz) { @@ -56,7 +69,8 @@ nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz) nxt_js_t *js; nxt_str_t *func; - static nxt_str_t func_str = nxt_string("function() {" + static nxt_str_t func_str = nxt_string("function(uri, host, remoteAddr, " + "args, headers, cookies) {" " return "); /* @@ -140,6 +154,12 @@ nxt_js_compile(nxt_js_conf_t *jcf) *p++ = ']'; + nxt_js_proto_id = njs_vm_external_prototype(jcf->vm, jcf->proto, + jcf->protos); + if (nxt_slow_path(nxt_js_proto_id < 0)) { + return NXT_ERROR; + } + ret = njs_vm_compile(jcf->vm, &start, p); return (ret == NJS_OK) ? NXT_OK : NXT_ERROR; @@ -187,7 +207,14 @@ nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js, njs_str_t res; njs_value_t *array, *value; njs_function_t *func; - njs_opaque_value_t opaque_value; + njs_opaque_value_t opaque_value, arguments[6]; + + static const njs_str_t uri_str = njs_str("uri"); + static const njs_str_t host_str = njs_str("host"); + static const njs_str_t remote_addr_str = njs_str("remoteAddr"); + static const njs_str_t args_str = njs_str("args"); + static const njs_str_t headers_str = njs_str("headers"); + static const njs_str_t cookies_str = njs_str("cookies"); vm = cache->vm; @@ -211,7 +238,49 @@ nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js, value = njs_vm_array_prop(vm, &cache->array, js->index, &opaque_value); func = njs_value_function(value); - ret = njs_vm_call(vm, func, NULL, 0); + ret = njs_vm_external_create(vm, njs_value_arg(&opaque_value), + nxt_js_proto_id, ctx, 0); + if (nxt_slow_path(ret != NJS_OK)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &uri_str, + &arguments[0]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &host_str, + &arguments[1]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), + &remote_addr_str, &arguments[2]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &args_str, + &arguments[3]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &headers_str, + &arguments[4]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &cookies_str, + &arguments[5]); + if (nxt_slow_path(value == NULL)) { + return NXT_ERROR; + } + + ret = njs_vm_call(vm, func, njs_value_arg(&arguments), 6); rc = njs_vm_retval_string(vm, &res); if (rc != NJS_OK) { diff --git a/src/nxt_js.h b/src/nxt_js.h index 321041ae..dea43fe3 100644 --- a/src/nxt_js.h +++ b/src/nxt_js.h @@ -22,6 +22,7 @@ typedef struct { nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp); +void nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, nxt_uint_t n); nxt_js_t *nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz); nxt_int_t nxt_js_compile(nxt_js_conf_t *jcf); nxt_int_t nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error); @@ -29,6 +30,9 @@ nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js, nxt_str_t *str, void *ctx); +extern njs_int_t nxt_js_proto_id; + + #endif /* NXT_HAVE_NJS */ #endif /* _NXT_JS_H_INCLUDED_ */ diff --git a/src/nxt_router.c b/src/nxt_router.c index 26aa9fb1..edc015c5 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1065,6 +1065,10 @@ nxt_router_temp_conf(nxt_task_t *task) goto fail; } +#if (NXT_HAVE_NJS) + nxt_http_register_js_proto(rtcf->tstr_state->jcf); +#endif + tmp = nxt_mp_create(1024, 128, 256, 32); if (nxt_slow_path(tmp == NULL)) { goto fail; diff --git a/src/nxt_runtime.h b/src/nxt_runtime.h index d7fe2f38..687914f0 100644 --- a/src/nxt_runtime.h +++ b/src/nxt_runtime.h @@ -138,6 +138,9 @@ void nxt_cdecl nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log, void nxt_stream_connection_init(nxt_task_t *task, void *obj, void *data); nxt_int_t nxt_http_register_variables(void); +#if (NXT_HAVE_NJS) +void nxt_http_register_js_proto(nxt_js_conf_t *jcf); +#endif #define nxt_runtime_process_each(rt, process) \ diff --git a/src/nxt_var.h b/src/nxt_var.h index 4f30a002..ab25800d 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -49,6 +49,8 @@ nxt_int_t nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error); nxt_int_t nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, nxt_var_t *var, nxt_str_t *str, void *ctx, nxt_bool_t logging); +nxt_str_t *nxt_var_get(nxt_task_t *task, nxt_var_cache_t *cache, + nxt_str_t *name, void *ctx); #endif /* _NXT_VAR_H_INCLUDED_ */ -- cgit From 491d0f700f5690eba0f1fcf2124f3a37ef73eb1a Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 17 Nov 2022 21:56:58 +0000 Subject: Python: Added support for Python 3.11. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python 3.8 added a new Python initialisation configuration API[0]. Python 3.11 marked the old API as deprecated resulting in the following compiler warnings which we treat as errors, failing the build src/python/nxt_python.c: In function ‘nxt_python_start’: src/python/nxt_python.c:130:13: error: ‘Py_SetProgramName’ is deprecated [-Werror=deprecated-declarations] 130 | Py_SetProgramName(nxt_py_home); | ^~~~~~~~~~~~~~~~~ In file included from /opt/python-3.11/include/python3.11/Python.h:94, from src/python/nxt_python.c:7: /opt/python-3.11/include/python3.11/pylifecycle.h:37:38: note: declared here 37 | Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); | ^~~~~~~~~~~~~~~~~ src/python/nxt_python.c:134:13: error: ‘Py_SetPythonHome’ is deprecated [-Werror=deprecated-declarations] 134 | Py_SetPythonHome(nxt_py_home); | ^~~~~~~~~~~~~~~~ /opt/python-3.11/include/python3.11/pylifecycle.h:40:38: note: declared here 40 | Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); | ^~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors We actually have a few config scenarios: Python < 3, Python >= 3.0 < 3.8 and for Python 3 we have two configs where we select one based on virtual environment setup. Factor out the Python 3 config initialisation into its own function. We actually create two functions, one for Python 3.8+ and one for older Python 3. We pick the right function to use at build time. The new API also has error checking (where the old API doesn't) which we handle. [0]: https://peps.python.org/pep-0587/ Closes: [ Andrew: Expanded upon patch from @sandeep-gh ] Signed-off-by: Andrew Clayton --- src/python/nxt_python.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 37204051..8983815c 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -22,6 +22,10 @@ typedef struct { } nxt_py_thread_info_t; +#if PY_MAJOR_VERSION == 3 +static nxt_int_t nxt_python3_init_config(nxt_int_t pep405); +#endif + static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_python_set_target(nxt_task_t *task, @@ -64,6 +68,63 @@ static nxt_py_thread_info_t *nxt_py_threads; static nxt_python_proto_t nxt_py_proto; +#if PY_VERSION_HEX >= NXT_PYTHON_VER(3, 8) + +static nxt_int_t +nxt_python3_init_config(nxt_int_t pep405) +{ + PyStatus status; + PyConfig config; + + PyConfig_InitIsolatedConfig(&config); + + if (pep405) { + status = PyConfig_SetString(&config, &config.program_name, + nxt_py_home); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + + } else { + status =PyConfig_SetString(&config, &config.home, nxt_py_home); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + } + + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) { + goto pyinit_exception; + } + PyConfig_Clear(&config); + + return NXT_OK; + +pyinit_exception: + + PyConfig_Clear(&config); + + return NXT_ERROR; +} + +#elif PY_MAJOR_VERSION == 3 + +static nxt_int_t +nxt_python3_init_config(nxt_int_t pep405) +{ + if (pep405) { + Py_SetProgramName(nxt_py_home); + + } else { + Py_SetPythonHome(nxt_py_home); + } + + return NXT_OK; +} + +#endif + + static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) { @@ -127,11 +188,15 @@ nxt_python_start(nxt_task_t *task, nxt_process_data_t *data) if (pep405) { mbstowcs(nxt_py_home, c->home, len); mbstowcs(nxt_py_home + len, bin_python, sizeof(bin_python)); - Py_SetProgramName(nxt_py_home); } else { mbstowcs(nxt_py_home, c->home, len + 1); - Py_SetPythonHome(nxt_py_home); + } + + ret = nxt_python3_init_config(pep405); + if (nxt_slow_path(ret == NXT_ERROR)) { + nxt_alert(task, "Failed to initialise config"); + return NXT_ERROR; } #else -- cgit From d862f581db968519fb7adb38c8872d020f4f21e6 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 6 Dec 2022 14:30:13 +0000 Subject: Node.js: added "shortCircuit" option for ES modules hook. Starting from Node.js v18.6.0 return value from all hooks must have "shortCircuit: true" option specified. For more information see: https://github.com/nodejs/node/commit/10bcad5c6e --- src/nodejs/unit-http/loader.mjs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nodejs/unit-http/loader.mjs b/src/nodejs/unit-http/loader.mjs index 546548f5..83985b0f 100644 --- a/src/nodejs/unit-http/loader.mjs +++ b/src/nodejs/unit-http/loader.mjs @@ -4,13 +4,15 @@ export async function resolve(specifier, context, defaultResolver) { case "websocket": return { url: new URL("./websocket.js", import.meta.url).href, - format: "commonjs" + format: "commonjs", + shortCircuit: true, } case "http": return { url: new URL("./http.js", import.meta.url).href, - format: "commonjs" + format: "commonjs", + shortCircuit: true, } } -- cgit From e70653c76606293e3687b05bbd8b5c06d700fb8b Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Tue, 6 Dec 2022 20:57:16 +0000 Subject: Fix compilation with GCC and -O0. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Andrei reported an issue with building unit when using '-O0' with GCC producing the following compiler errors cc -c -pipe -fPIC -fvisibility=hidden -O -W -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wmissing-prototypes -Werror -g -O0 -I src -I build \ \ \ -o build/src/nxt_unit.o \ -MMD -MF build/src/nxt_unit.dep -MT build/src/nxt_unit.o \ src/nxt_unit.c src/nxt_unit.c: In function ‘nxt_unit_log’: src/nxt_unit.c:6601:9: error: ‘msg’ may be used uninitialized [-Werror=maybe-uninitialized] 6601 | p = nxt_unit_snprint_prefix(p, end, pid, level); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/nxt_unit.c:6682:1: note: by argument 2 of type ‘const char *’ to ‘nxt_unit_snprint_prefix’ declared here 6682 | nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, int level) | ^~~~~~~~~~~~~~~~~~~~~~~ src/nxt_unit.c:6582:22: note: ‘msg’ declared here 6582 | char msg[NXT_MAX_ERROR_STR], *p, *end; | ^~~ src/nxt_unit.c: In function ‘nxt_unit_req_log’: src/nxt_unit.c:6645:9: error: ‘msg’ may be used uninitialized [-Werror=maybe-uninitialized] 6645 | p = nxt_unit_snprint_prefix(p, end, pid, level); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/nxt_unit.c:6682:1: note: by argument 2 of type ‘const char *’ to ‘nxt_unit_snprint_prefix’ declared here 6682 | nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, int level) | ^~~~~~~~~~~~~~~~~~~~~~~ src/nxt_unit.c:6625:35: note: ‘msg’ declared here 6625 | char msg[NXT_MAX_ERROR_STR], *p, *end; | ^~~ cc1: all warnings being treated as errors The above was reproduced with $ ./configure --cc-opt=-O0 && ./configure python && make -j4 This warning doesn't happen on clang (15.0.4) or GCC (8.3) and seems to have been introduced in GCC 11. The above is from GCC (12.2.1, Fedora 37). The trigger of this GCC issue is actually part of a commit I introduced a few months back to constify some function parameters and it seems the consensus for how to resolve this problem is to simply remove the const qualifier from the *end parameter to nxt_unit_snprint_prefix(). Reported-by: Andrei Zeliankou Link: Link: Link: Fixes: 4418f99 ("Constified numerous function parameters.") Signed-off-by: Andrew Clayton --- src/nxt_unit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 3932b2ab..e1b1897a 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -196,7 +196,7 @@ 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, const char *end, pid_t pid, +static char * nxt_unit_snprint_prefix(char *p, 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); @@ -6679,7 +6679,7 @@ static const char * nxt_unit_log_levels[] = { static char * -nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, int level) +nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level) { struct tm tm; struct timespec ts; -- cgit From 9466daf9bdafa3e00f521a47f4ce218353bf7f86 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 1 Dec 2022 01:39:57 +0000 Subject: Added simple wrappers for fopen(3) and fclose(3). Add simple wrapper functions for fopen(3) and fclose(3) that are somewhat akin to the nxt_file_open() and nxt_file_close() wrappers that log errors. Suggested-by: Alejandro Colomar Reviewed-by: Alejandro Colomar Signed-off-by: Andrew Clayton --- src/nxt_file.c | 37 +++++++++++++++++++++++++++++++++++++ src/nxt_file.h | 4 ++++ 2 files changed, 41 insertions(+) (limited to 'src') diff --git a/src/nxt_file.c b/src/nxt_file.c index 5d38d57e..a3fcda76 100644 --- a/src/nxt_file.c +++ b/src/nxt_file.c @@ -500,6 +500,43 @@ nxt_fd_close(nxt_fd_t fd) } +FILE * +nxt_file_fopen(nxt_task_t *task, const char *pathname, const char *mode) +{ + int err; + FILE *fp; + +#if (NXT_DEBUG) + nxt_thread_time_update(task->thread); +#endif + + fp = fopen(pathname, mode); + err = (fp == NULL) ? nxt_errno : 0; + + nxt_debug(task, "fopen(\"%s\", \"%s\"): fp:%p err:%d", pathname, mode, fp, + err); + + if (nxt_fast_path(fp != NULL)) { + return fp; + } + + nxt_alert(task, "fopen(\"%s\") failed %E", pathname, err); + + return NULL; +} + + +void +nxt_file_fclose(nxt_task_t *task, FILE *fp) +{ + nxt_debug(task, "fclose(%p)", fp); + + if (nxt_slow_path(fclose(fp) == -1)) { + nxt_alert(task, "fclose() failed %E", nxt_errno); + } +} + + /* * nxt_file_redirect() redirects the file to the fd descriptor. * Then the fd descriptor is closed. diff --git a/src/nxt_file.h b/src/nxt_file.h index 07c7a22b..945717b3 100644 --- a/src/nxt_file.h +++ b/src/nxt_file.h @@ -186,6 +186,10 @@ NXT_EXPORT ssize_t nxt_fd_write(nxt_fd_t fd, u_char *buf, size_t size); NXT_EXPORT ssize_t nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size); NXT_EXPORT void nxt_fd_close(nxt_fd_t fd); +NXT_EXPORT FILE *nxt_file_fopen(nxt_task_t *task, const char *pathname, + const char *mode); +NXT_EXPORT void nxt_file_fclose(nxt_task_t *task, FILE *fp); + NXT_EXPORT nxt_int_t nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd); NXT_EXPORT nxt_int_t nxt_file_stderr(nxt_file_t *file); NXT_EXPORT nxt_int_t nxt_stderr_start(void); -- cgit From 7d177faf3b8a483fd7ef958e884ec5625e058ca0 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Mon, 24 Oct 2022 17:33:23 +0100 Subject: Isolation: added core cgroup infrastructure. Firstly, this is not to be confused with CLONE_NEWCGROUP which unit already supports and is related to namespaces. To re-cap, namespaces allow processes to have different views of various parts of the system such as filesystem mounts, networking, hostname etc. Whereas cgroup[0] is a Linux kernel facility for collecting a bunch of processes together to perform some task on the group as a whole, for example to implement resource limits. There are two parts to cgroup, the core part of organising processes into a hierarchy and the controllers which are responsible for enforcing resource limits etc. There are currently two versions of the cgroup sub-system, the original cgroup and a version 2[1] introduced in 3.16 (August 2014) and marked stable in 4.5 (March 2016). This commit supports the cgroup V2 API and implements the ability to place applications into their own cgroup on a per-application basis. You can put them each into their own cgroup or you can group some together. The ability to set resource limits can easily be added in future. The initial use case of this would be to aid in observability of unit applications which becomes much easier if you can just monitor them on a per cgroup basis. One thing to note about cgroup, is that unlike namespaces which are controlled via system calls such as clone(2) and unshare(2), cgroups are setup and controlled through the cgroupfs pseudo-filesystem. cgroup is Linux only and this support will only be enabled if configure finds the cgroup2 filesystem mount, e.g cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot) The cgroups are removed on shutdown or as required on reconfiguration. This commit just adds the basic infrastructure for using cgroups within unit. Subsequent commits will wire up this support. It supports creating cgroups relative to the main cgroup root and also below the cgroup of the main unit process. [0]: [1]: Cc: Alejandro Colomar Signed-off-by: Andrew Clayton --- src/nxt_cgroup.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nxt_cgroup.h | 14 +++++ 2 files changed, 188 insertions(+) create mode 100644 src/nxt_cgroup.c create mode 100644 src/nxt_cgroup.h (limited to 'src') diff --git a/src/nxt_cgroup.c b/src/nxt_cgroup.c new file mode 100644 index 00000000..2c404acc --- /dev/null +++ b/src/nxt_cgroup.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) Andrew Clayton + * Copyright (C) F5, Inc. + */ + +#include + +#include + + +static int nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, + char *cgpath); +static nxt_int_t nxt_mk_cgpath(nxt_task_t *task, const char *dir, + char *cgpath); + + +nxt_int_t +nxt_cgroup_proc_add(nxt_task_t *task, nxt_process_t *process) +{ + int len; + char cgprocs[NXT_MAX_PATH_LEN]; + FILE *fp; + nxt_int_t ret; + + if (task->thread->runtime->type != NXT_PROCESS_MAIN + || nxt_process_type(process) != NXT_PROCESS_PROTOTYPE + || process->isolation.cgroup.path == NULL) + { + return NXT_OK; + } + + ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgprocs); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } + + ret = nxt_fs_mkdir_all((const u_char *) cgprocs, 0777); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NXT_ERROR; + } + + len = strlen(cgprocs); + + len = snprintf(cgprocs + len, NXT_MAX_PATH_LEN - len, "/cgroup.procs"); + if (nxt_slow_path(len >= NXT_MAX_PATH_LEN - len)) { + nxt_errno = ENAMETOOLONG; + return NXT_ERROR; + } + + fp = nxt_file_fopen(task, cgprocs, "we"); + if (nxt_slow_path(fp == NULL)) { + return NXT_ERROR; + } + + setvbuf(fp, NULL, _IONBF, 0); + len = fprintf(fp, "%d\n", process->pid); + nxt_file_fclose(task, fp); + + if (nxt_slow_path(len < 0)) { + return NXT_ERROR; + } + + return NXT_OK; +} + + +void +nxt_cgroup_cleanup(nxt_task_t *task, const nxt_process_t *process) +{ + char *ptr; + char cgroot[NXT_MAX_PATH_LEN], cgpath[NXT_MAX_PATH_LEN]; + nxt_int_t ret; + + ret = nxt_mk_cgpath(task, "", cgroot); + if (nxt_slow_path(ret == NXT_ERROR)) { + return; + } + + ret = nxt_mk_cgpath(task, process->isolation.cgroup.path, cgpath); + if (nxt_slow_path(ret == NXT_ERROR)) { + return; + } + + while (*cgpath != '\0' && strcmp(cgroot, cgpath) != 0) { + rmdir(cgpath); + ptr = strrchr(cgpath, '/'); + *ptr = '\0'; + } +} + + +static int +nxt_mk_cgpath_relative(nxt_task_t *task, const char *dir, char *cgpath) +{ + int i, len; + char *buf, *ptr; + FILE *fp; + size_t size; + ssize_t nread; + nxt_bool_t found; + + fp = nxt_file_fopen(task, "/proc/self/cgroup", "re"); + if (nxt_slow_path(fp == NULL)) { + return -1; + } + + len = -1; + buf = NULL; + found = 0; + while ((nread = getline(&buf, &size, fp)) != -1) { + if (strncmp(buf, "0::", 3) == 0) { + found = 1; + break; + } + } + + nxt_file_fclose(task, fp); + + if (!found) { + nxt_errno = ENODATA; + goto out_free_buf; + } + + buf[nread - 1] = '\0'; /* lose the trailing '\n' */ + ptr = buf; + for (i = 0; i < 2; i++) { + ptr = strchr(ptr, ':'); + if (ptr == NULL) { + nxt_errno = ENODATA; + goto out_free_buf; + } + + ptr++; + } + + len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s/%s", + ptr, dir); + +out_free_buf: + + nxt_free(buf); + + return len; +} + + +static nxt_int_t +nxt_mk_cgpath(nxt_task_t *task, const char *dir, char *cgpath) +{ + int len; + + /* + * If the path from the config is relative, we need to make + * the cgroup path include the main unit processes cgroup. I.e + * + * NXT_CGROUP_ROOT/
/ + */ + if (dir[0] != '/') { + len = nxt_mk_cgpath_relative(task, dir, cgpath); + } else { + len = snprintf(cgpath, NXT_MAX_PATH_LEN, NXT_CGROUP_ROOT "%s", dir); + } + + if (len == -1) { + return NXT_ERROR; + } + + if (len >= NXT_MAX_PATH_LEN) { + nxt_errno = ENAMETOOLONG; + return NXT_ERROR; + } + + return NXT_OK; +} diff --git a/src/nxt_cgroup.h b/src/nxt_cgroup.h new file mode 100644 index 00000000..0b9055d2 --- /dev/null +++ b/src/nxt_cgroup.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) Andrew Clayton + * Copyright (C) F5, Inc. + */ + +#ifndef _NXT_CGROUP_H_INCLUDED_ +#define _NXT_CGROUP_H_INCLUDED_ + + +nxt_int_t nxt_cgroup_proc_add(nxt_task_t *task, nxt_process_t *process); +void nxt_cgroup_cleanup(nxt_task_t *task, const nxt_process_t *process); + + +#endif /* _NXT_CGROUP_H_INCLUDED_ */ -- cgit From 867a839f103bf7859b76eb98cfc28e7f0155dd1b Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Mon, 24 Oct 2022 17:35:04 +0100 Subject: Isolation: wired up per-application cgroup support internally. This commit hooks into the cgroup infrastructure added in the previous commit to create per-application cgroups. It does this by adding each "prototype process" into its own cgroup, then each child process inherits its parents cgroup. If we fail to create a cgroup we simply fail the process. This behaviour may get enhanced in the future. This won't actually do anything yet. Subsequent commits will hook this up to the build and config systems. Reviewed-by: Alejandro Colomar Signed-off-by: Andrew Clayton --- src/nxt_isolation.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/nxt_main_process.c | 4 ++++ src/nxt_process.c | 12 ++++++++++++ src/nxt_process.h | 13 +++++++++++++ 4 files changed, 79 insertions(+) (limited to 'src') diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index 796da4c6..b6b13c59 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -6,6 +6,7 @@ #include #include #include +#include #if (NXT_HAVE_MNTENT_H) #include @@ -15,6 +16,11 @@ static nxt_int_t nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation, nxt_process_t *process); +#if (NXT_HAVE_CGROUP) +static nxt_int_t nxt_isolation_set_cgroup(nxt_task_t *task, + nxt_conf_value_t *isolation, nxt_process_t *process); +#endif + #if (NXT_HAVE_CLONE) static nxt_int_t nxt_isolation_set_namespaces(nxt_task_t *task, nxt_conf_value_t *isolation, nxt_process_t *process); @@ -155,6 +161,14 @@ static nxt_int_t nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation, nxt_process_t *process) { +#if (NXT_HAVE_CGROUP) + if (nxt_slow_path(nxt_isolation_set_cgroup(task, isolation, process) + != NXT_OK)) + { + return NXT_ERROR; + } +#endif + #if (NXT_HAVE_CLONE) if (nxt_slow_path(nxt_isolation_set_namespaces(task, isolation, process) != NXT_OK)) @@ -197,6 +211,42 @@ nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation, } +#if (NXT_HAVE_CGROUP) + +static nxt_int_t +nxt_isolation_set_cgroup(nxt_task_t *task, nxt_conf_value_t *isolation, + nxt_process_t *process) +{ + nxt_str_t str; + nxt_conf_value_t *obj; + + static nxt_str_t cgname = nxt_string("cgroup"); + static nxt_str_t path = nxt_string("path"); + + obj = nxt_conf_get_object_member(isolation, &cgname, NULL); + if (obj == NULL) { + return NXT_OK; + } + + obj = nxt_conf_get_object_member(obj, &path, NULL); + if (obj == NULL) { + return NXT_ERROR; + } + + nxt_conf_get_string(obj, &str); + process->isolation.cgroup.path = nxt_mp_alloc(process->mem_pool, + str.length + 1); + nxt_memcpy(process->isolation.cgroup.path, str.start, str.length); + process->isolation.cgroup.path[str.length] = '\0'; + + process->isolation.cgroup_cleanup = nxt_cgroup_cleanup; + + return NXT_OK; +} + +#endif + + #if (NXT_HAVE_CLONE) static nxt_int_t diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index f21482d5..de41e8d7 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -1007,6 +1007,10 @@ nxt_main_process_cleanup(nxt_task_t *task, nxt_process_t *process) if (process->isolation.cleanup != NULL) { process->isolation.cleanup(task, process); } + + if (process->isolation.cgroup_cleanup != NULL) { + process->isolation.cgroup_cleanup(task, process); + } } diff --git a/src/nxt_process.c b/src/nxt_process.c index 738a03bf..d8836ad2 100644 --- a/src/nxt_process.c +++ b/src/nxt_process.c @@ -5,6 +5,7 @@ */ #include +#include #if (NXT_HAVE_CLONE) #include @@ -378,6 +379,17 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process) nxt_runtime_process_add(task, process); } +#if (NXT_HAVE_CGROUP) + ret = nxt_cgroup_proc_add(task, process); + if (nxt_slow_path(ret != NXT_OK)) { + nxt_alert(task, "cgroup: failed to add process %s to %s %E", + process->name, process->isolation.cgroup.path, nxt_errno); + nxt_cgroup_cleanup(task, process); + kill(pid, SIGTERM); + return -1; + } +#endif + return pid; } diff --git a/src/nxt_process.h b/src/nxt_process.h index 15fd4e7f..0db68d45 100644 --- a/src/nxt_process.h +++ b/src/nxt_process.h @@ -61,8 +61,11 @@ typedef enum { typedef struct nxt_port_mmap_s nxt_port_mmap_t; typedef struct nxt_process_s nxt_process_t; +typedef struct nxt_cgroup_s nxt_cgroup_t; typedef void (*nxt_isolation_cleanup_t)(nxt_task_t *task, nxt_process_t *process); +typedef void (*nxt_cgroup_cleanup_t)(nxt_task_t *task, + const nxt_process_t *process); typedef struct { @@ -80,6 +83,11 @@ typedef struct { } nxt_process_automount_t; +struct nxt_cgroup_s { + char *path; +}; + + typedef struct { u_char *rootfs; nxt_process_automount_t automount; @@ -87,6 +95,11 @@ typedef struct { nxt_isolation_cleanup_t cleanup; + nxt_cgroup_cleanup_t cgroup_cleanup; +#if (NXT_HAVE_CGROUP) + nxt_cgroup_t cgroup; +#endif + #if (NXT_HAVE_CLONE) nxt_clone_t clone; #endif -- cgit From f67a01b88fd7c7057767e18a3dd06c24e94c8aa8 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Mon, 24 Oct 2022 17:14:06 +0100 Subject: Isolation: wired up cgroup support to the config system. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This hooks the cgroup support up to the config system so it can actually be used. To make use of this in unit a new "cgroup" section has been added to the isolation configuration. e.g "applications": { "python": { "type": "python", "processes": 5, "path": "/opt/unit/unit-cgroup-test/", "module": "app", "isolation": { "cgroup": { "path": "app/python" } } } } Now there are two ways to specify the path, relative, like the above (without a leading '/') and absolute (with a leading '/'). In the above case the "python" application is placed into its own cgroup under CGROUP_ROOT/
/app/python. Whereas if you specified say "path": "/unit/app/python" Then the python application would be placed under CGROUP_ROOT/unit/app/python The first option allows you to easily take advantage of any resource limits that have already been configured for unit. With the second method (absolute pathname) if you know of an already existing cgroup where you'd like to place it, you can, e.g "path": "/system.slice/unit/python" Where system.slice has already been created by systemd and may already have some overall system limits applied which would also apply to unit. Limits apply down the hierarchy and lower groups can't exceed the previous group limits. So what does this actually look like? Lets take the unit-calculator application[0] and have each of its applications placed into their own cgroup. If we give each application a new section like "isolation": { "cgroup": { "path": "/unit/unit-calculator/add" } } changing the path for each one, we can visualise the result with the systemd-cgls command, e.g │ └─session-5.scope (#4561) │ ├─ 6667 sshd: andrew [priv] │ ├─ 6684 sshd: andrew@pts/0 │ ├─ 6685 -bash │ ├─ 12632 unit: main v1.28.0 [/opt/unit/sbin/unitd --control 127.0.0.1:808> │ ├─ 12634 unit: controller │ ├─ 12635 unit: router │ ├─ 13550 systemd-cgls │ └─ 13551 less ├─unit (#4759) │ └─unit-calculator (#5037) │ ├─subtract (#5069) │ │ ├─ 12650 unit: "subtract" prototype │ │ └─ 12651 unit: "subtract" application │ ├─multiply (#5085) │ │ ├─ 12653 unit: "multiply" prototype │ │ └─ 12654 unit: "multiply" application │ ├─divide (#5101) │ │ ├─ 12671 unit: "divide" prototype │ │ └─ 12672 node divide.js │ ├─sqroot (#5117) │ │ ├─ 12679 unit: "sqroot" prototype │ │ └─ 12680 /home/andrew/src/unit-calculator/sqroot/sqroot │ └─add (#5053) │ ├─ 12648 unit: "add" prototype │ └─ 12649 unit: "add" application We used an absolute path so the cgroups will be created relative to the main cgroupfs mount, e.g /sys/fs/cgroup We can see that the main unit processes are in the same cgroup as the shell from where they were started, by default child process are placed into the same cgroup as the parent. Then we can see that each application has been placed into its own cgroup under /sys/fs/cgroup Taking another example of a simple 5 process python application, with "isolation": { "cgroup": { "path": "app/python" } } Here we have specified a relative path and thus the python application will be placed below the existing cgroup that contains the main unit process. E.g │ │ │ ├─app-glib-cinnamon\x2dcustom\x2dlauncher\x2d3-43951.scope (#90951) │ │ │ │ ├─ 988 unit: main v1.28.0 [/opt/unit/sbin/unitd --no-daemon] │ │ │ │ ├─ 990 unit: controller │ │ │ │ ├─ 991 unit: router │ │ │ │ ├─ 43951 xterm -bg rgb:20/20/20 -fg white -fa DejaVu Sans Mono │ │ │ │ ├─ 43956 bash │ │ │ │ ├─ 58828 sudo -i │ │ │ │ ├─ 58831 -bash │ │ │ │ └─app (#107351) │ │ │ │ └─python (#107367) │ │ │ │ ├─ 992 unit: "python" prototype │ │ │ │ ├─ 993 unit: "python" application │ │ │ │ ├─ 994 unit: "python" application │ │ │ │ ├─ 995 unit: "python" application │ │ │ │ ├─ 996 unit: "python" application │ │ │ │ └─ 997 unit: "python" application [0]: Reviewed-by: Alejandro Colomar Signed-off-by: Andrew Clayton --- src/nxt_conf_validation.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index e650b44d..0f22c540 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -219,6 +219,11 @@ static nxt_int_t nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); #endif +#if (NXT_HAVE_CGROUP) +static nxt_int_t nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); +#endif + static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[]; @@ -240,6 +245,9 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[]; +#if (NXT_HAVE_CGROUP) +static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[]; +#endif #if (NXT_HAVE_ISOLATION_ROOTFS) static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[]; #endif @@ -1094,6 +1102,15 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = { }, #endif +#if (NXT_HAVE_CGROUP) + { + .name = nxt_string("cgroup"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_app_cgroup_members, + }, +#endif + NXT_CONF_VLDT_END }; @@ -1166,6 +1183,22 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[] = { #endif +#if (NXT_HAVE_CGROUP) + +static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[] = { + { + .name = nxt_string("path"), + .type = NXT_CONF_VLDT_STRING, + .flags = NXT_CONF_VLDT_REQUIRED, + .validator = nxt_conf_vldt_cgroup_path, + }, + + NXT_CONF_VLDT_END +}; + +#endif + + #if (NXT_HAVE_CLONE_NEWUSER) static nxt_conf_vldt_object_t nxt_conf_vldt_app_procmap_members[] = { @@ -2798,6 +2831,35 @@ nxt_conf_vldt_target(nxt_conf_validation_t *vldt, nxt_str_t *name, } +#if (NXT_HAVE_CGROUP) + +static nxt_int_t +nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, + void *data) +{ + char path[NXT_MAX_PATH_LEN]; + nxt_str_t cgpath; + + nxt_conf_get_string(value, &cgpath); + if (cgpath.length >= NXT_MAX_PATH_LEN - strlen(NXT_CGROUP_ROOT) - 1) { + return nxt_conf_vldt_error(vldt, "The cgroup path \"%V\" is too long.", + &cgpath); + } + + sprintf(path, "/%*s/", (int) cgpath.length, cgpath.start); + + if (cgpath.length == 0 || strstr(path, "/../") != NULL) { + return nxt_conf_vldt_error(vldt, + "The cgroup path \"%V\" is invalid.", + &cgpath); + } + + return NXT_OK; +} + +#endif + + static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) -- cgit From dad7ef9a12f2cf16f2be011f167fc19b011ffe03 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 4 May 2022 16:13:19 +0100 Subject: Configuration: made large_header_buffer_size a valid setting. @JanMikes and @tagur87 on GitHub both reported issues with long URLs that were exceeding the 8192 byte large_header_buffer_size setting, which resulted in a HTTP 431 error (Request Header Fields Too Large). This can be resolved in the code by updating the following line in src/nxt_router.c::nxt_router_conf_create() skcf->large_header_buffer_size = 8192; However, requiring users to modify unit and install custom versions is less than ideal. We could increase the value, but to what? This commit takes the option of allowing the user to set this option in their config by making large_header_buffer_size a valid configuration setting. large_header_buffer_size is already set by the configuration system in nxt_router.c it just isn't set as a valid config option in nxt_conf_validation.c With this change users can set this option in their config if required by the following "settings": { "http": { "large_header_buffer_size": 16384 } }, It retains its default value of 8192 bytes if this is not set. With this commit, without the above setting or too low a value, with a long URL you get a 431 error. With the above setting set to a large enough value, the request is successful. NOTE: This setting really determines the maximum size of any single header _value_. Also, unit will try and place multiple values into a buffer _if_ they fully fit. NOTE: This is being released as undocumented and subject to change as it exposes internal workings of unit. Closes: Signed-off-by: Andrew Clayton --- src/nxt_conf_validation.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 0f22c540..218254bf 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -314,6 +314,9 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = { }, { .name = nxt_string("idle_timeout"), .type = NXT_CONF_VLDT_INTEGER, + }, { + .name = nxt_string("large_header_buffer_size"), + .type = NXT_CONF_VLDT_INTEGER, }, { .name = nxt_string("body_buffer_size"), .type = NXT_CONF_VLDT_INTEGER, -- cgit From f88371ff1d5173da44b8bf152e1b261e444a6eac Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Tue, 6 Dec 2022 12:56:03 +0000 Subject: Configuration: made large_header_buffers a valid setting. This is an extension to the previous commit, which made large_header_buffer_size a valid configuration setting. This commit makes a related value, large_header_buffers, a valid configuration setting. While large_header_buffer_size effectively limits the maximum size of any single header (although unit will try to pack multiple headers into a buffer if they wholly fit). large_header_buffers limits how many of these 'large' buffers are available. It makes sense to also allow this to be user set. large_header_buffers is already set by the configuration system in nxt_router.c it just isn't set as a valid config option in nxt_conf_validation.c With this change users can set this option in their config if required by the following "settings": { "http": { "large_header_buffers": 8 } }, It retains its default value of 4 if this is not set. NOTE: This is being released as undocumented and subject to change as it exposes internal workings of unit. Signed-off-by: Andrew Clayton --- src/nxt_conf_validation.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 218254bf..c6e63c25 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -317,6 +317,9 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = { }, { .name = nxt_string("large_header_buffer_size"), .type = NXT_CONF_VLDT_INTEGER, + }, { + .name = nxt_string("large_header_buffers"), + .type = NXT_CONF_VLDT_INTEGER, }, { .name = nxt_string("body_buffer_size"), .type = NXT_CONF_VLDT_INTEGER, -- cgit From 7a81d9d61d0c4e3cc7e6b74b6be367cbf26ea2ab Mon Sep 17 00:00:00 2001 From: OutOfFocus4 Date: Tue, 22 Nov 2022 15:03:59 -0500 Subject: Removed dead code. Signed-off-by: Alejandro Colomar --- src/nxt_application.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/nxt_application.h b/src/nxt_application.h index 239f357b..4d624448 100644 --- a/src/nxt_application.h +++ b/src/nxt_application.h @@ -49,7 +49,6 @@ typedef struct { typedef struct { char *home; nxt_conf_value_t *path; - char *callable; nxt_str_t protocol; uint32_t threads; uint32_t thread_stack_size; -- cgit From 6dae517ebd20baa2066541e703d6aa594326dd69 Mon Sep 17 00:00:00 2001 From: OutOfFocus4 Date: Sun, 14 Nov 2021 10:47:07 -0500 Subject: Python: Added "prefix" to configuration. This patch gives users the option to set a `"prefix"` attribute for Python applications, either at the top level or for specific `"target"`s. If the attribute is present, the value of `"prefix"` must be a string beginning with `"/"`. If the value of the `"prefix"` attribute is longer than 1 character and ends in `"/"`, the trailing `"/"` is stripped. The purpose of the `"prefix"` attribute is to set the `SCRIPT_NAME` context value for WSGI applications and the `root_path` context value for ASGI applications, allowing applications to properly route requests regardless of the path that the server uses to expose the application. The context value is only set if the request's URL path begins with the value of the `"prefix"` attribute. In all other cases, the `SCRIPT_NAME` or `root_path` values are not set. In addition, for WSGI applications, the value of `"prefix"` will be stripped from the beginning of the request's URL path before it is sent to the application. Reviewed-by: Andrei Zeliankou Reviewed-by: Artem Konev Signed-off-by: Alejandro Colomar --- src/nxt_conf_validation.c | 37 +++++++++++++++++++++++++ src/python/nxt_python.c | 60 ++++++++++++++++++++++++++++++++++++++-- src/python/nxt_python.h | 2 ++ src/python/nxt_python_asgi.c | 28 ++++++++++++++----- src/python/nxt_python_asgi_str.c | 2 +- src/python/nxt_python_wsgi.c | 49 +++++++++++++++++++++++--------- 6 files changed, 155 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index c6e63c25..bf8aa760 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -128,6 +128,8 @@ static nxt_int_t nxt_conf_vldt_python_path_element(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); +static nxt_int_t nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_threads(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt, @@ -795,6 +797,11 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = { .type = NXT_CONF_VLDT_STRING, .validator = nxt_conf_vldt_targets_exclusive, .u.string = "callable", + }, { + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_targets_exclusive, + .u.string = "prefix", }, { .name = nxt_string("targets"), .type = NXT_CONF_VLDT_OBJECT, @@ -814,6 +821,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[] = { }, { .name = nxt_string("callable"), .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_python_prefix, }, NXT_CONF_VLDT_END @@ -828,6 +839,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_python_notargets_members[] = { }, { .name = nxt_string("callable"), .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("prefix"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_conf_vldt_python_prefix, }, NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members) @@ -1870,6 +1885,28 @@ nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt, } +static nxt_int_t +nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data) +{ + nxt_str_t prefix; + + if (nxt_conf_type(value) != NXT_CONF_STRING) { + return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string " + "beginning with \"/\"."); + } + + nxt_conf_get_string(value, &prefix); + + if (!nxt_strchr_start(&prefix, '/')) { + return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string " + "beginning with \"/\"."); + } + + return NXT_OK; +} + + static nxt_int_t nxt_conf_vldt_threads(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c index 8983815c..bdb04579 100644 --- a/src/python/nxt_python.c +++ b/src/python/nxt_python.c @@ -30,6 +30,8 @@ static nxt_int_t nxt_python_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, nxt_conf_value_t *conf); +nxt_inline nxt_int_t nxt_python_set_prefix(nxt_task_t *task, + nxt_python_target_t *target, nxt_conf_value_t *value); static nxt_int_t nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value); static int nxt_python_init_threads(nxt_python_app_conf_t *c); static int nxt_python_ready_handler(nxt_unit_ctx_t *ctx); @@ -389,6 +391,7 @@ nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, static nxt_str_t module_str = nxt_string("module"); static nxt_str_t callable_str = nxt_string("callable"); + static nxt_str_t prefix_str = nxt_string("prefix"); module = obj = NULL; @@ -436,6 +439,11 @@ nxt_python_set_target(nxt_task_t *task, nxt_python_target_t *target, goto fail; } + value = nxt_conf_get_object_member(conf, &prefix_str, NULL); + if (nxt_slow_path(nxt_python_set_prefix(task, target, value) != NXT_OK)) { + goto fail; + } + target->application = obj; obj = NULL; @@ -453,6 +461,48 @@ fail: } +nxt_inline nxt_int_t +nxt_python_set_prefix(nxt_task_t *task, nxt_python_target_t *target, + nxt_conf_value_t *value) +{ + u_char *prefix; + nxt_str_t str; + + if (value == NULL) { + return NXT_OK; + } + + nxt_conf_get_string(value, &str); + + if (str.length == 0) { + return NXT_OK; + } + + if (str.start[str.length - 1] == '/') { + str.length--; + } + target->prefix.length = str.length; + prefix = nxt_malloc(str.length); + if (nxt_slow_path(prefix == NULL)) { + nxt_alert(task, "Failed to allocate target prefix string"); + return NXT_ERROR; + } + + target->py_prefix = PyString_FromStringAndSize((char *)str.start, + str.length); + if (nxt_slow_path(target->py_prefix == NULL)) { + nxt_free(prefix); + nxt_alert(task, "Python failed to allocate target prefix " + "string"); + return NXT_ERROR; + } + nxt_memcpy(prefix, str.start, str.length); + target->prefix.start = prefix; + + return NXT_OK; +} + + static nxt_int_t nxt_python_set_path(nxt_task_t *task, nxt_conf_value_t *value) { @@ -730,7 +780,8 @@ nxt_python_done_strings(nxt_python_string_t *pstr) static void nxt_python_atexit(void) { - nxt_int_t i; + nxt_int_t i; + nxt_python_target_t *target; if (nxt_py_proto.done != NULL) { nxt_py_proto.done(); @@ -740,7 +791,12 @@ nxt_python_atexit(void) if (nxt_py_targets != NULL) { for (i = 0; i < nxt_py_targets->count; i++) { - Py_XDECREF(nxt_py_targets->target[i].application); + target = &nxt_py_targets->target[i]; + + Py_XDECREF(target->application); + Py_XDECREF(target->py_prefix); + + nxt_free(target->prefix.start); } nxt_unit_free(NULL, nxt_py_targets); diff --git a/src/python/nxt_python.h b/src/python/nxt_python.h index eddb1cfc..37e6265e 100644 --- a/src/python/nxt_python.h +++ b/src/python/nxt_python.h @@ -40,6 +40,8 @@ typedef struct { PyObject *application; + PyObject *py_prefix; + nxt_str_t prefix; nxt_bool_t asgi_legacy; } nxt_python_target_t; diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 256bcdcc..587a17cf 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -27,7 +27,8 @@ static void nxt_py_asgi_remove_reader(nxt_unit_ctx_t *ctx, static void nxt_py_asgi_request_handler(nxt_unit_request_info_t *req); 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_http_scope(nxt_unit_request_info_t *req, + nxt_python_target_t *app_target); 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, @@ -455,16 +456,16 @@ nxt_py_asgi_request_handler(nxt_unit_request_info_t *req) goto release_send; } - scope = nxt_py_asgi_create_http_scope(req); + req->data = asgi; + target = &nxt_py_targets->target[req->request->app_target]; + + scope = nxt_py_asgi_create_http_scope(req, target); if (nxt_slow_path(scope == NULL)) { nxt_unit_request_done(req, NXT_UNIT_ERROR); goto release_done; } - req->data = asgi; - target = &nxt_py_targets->target[req->request->app_target]; - if (!target->asgi_legacy) { nxt_unit_req_debug(req, "Python call ASGI 3.0 application"); @@ -573,12 +574,14 @@ 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) +nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req, + nxt_python_target_t *app_target) { char *p, *target, *query; - uint32_t target_length, i; + uint32_t target_length, i, path_length; PyObject *scope, *v, *type, *scheme; PyObject *headers, *header; + nxt_str_t prefix; nxt_unit_field_t *f; nxt_unit_request_t *r; @@ -612,6 +615,17 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) return NULL; } + prefix = app_target->prefix; + path_length = r->path_length; + p = nxt_unit_sptr_get(&r->path); + if (prefix.length > 0 + && ((path_length > prefix.length && p[prefix.length] == '/') + || path_length == prefix.length) + && memcmp(prefix.start, p, prefix.length) == 0) + { + SET_ITEM(scope, root_path, app_target->py_prefix); + } + p = nxt_unit_sptr_get(&r->version); SET_ITEM(scope, http_version, p[7] == '1' ? nxt_py_1_1_str : nxt_py_1_0_str) diff --git a/src/python/nxt_python_asgi_str.c b/src/python/nxt_python_asgi_str.c index 34422973..7171d52b 100644 --- a/src/python/nxt_python_asgi_str.c +++ b/src/python/nxt_python_asgi_str.c @@ -99,7 +99,7 @@ static nxt_python_string_t nxt_py_asgi_strings[] = { { nxt_string("query_string"), &nxt_py_query_string_str }, { nxt_string("raw_path"), &nxt_py_raw_path_str }, { nxt_string("result"), &nxt_py_result_str }, - { nxt_string("root_path"), &nxt_py_root_path_str }, // not used + { nxt_string("root_path"), &nxt_py_root_path_str }, { nxt_string("scheme"), &nxt_py_scheme_str }, { nxt_string("server"), &nxt_py_server_str }, { nxt_string("set_exception"), &nxt_py_set_exception_str }, diff --git a/src/python/nxt_python_wsgi.c b/src/python/nxt_python_wsgi.c index 34afd9a9..dfb31509 100644 --- a/src/python/nxt_python_wsgi.c +++ b/src/python/nxt_python_wsgi.c @@ -60,7 +60,8 @@ static void nxt_python_request_handler(nxt_unit_request_info_t *req); static PyObject *nxt_python_create_environ(nxt_python_app_conf_t *c); static PyObject *nxt_python_copy_environ(nxt_unit_request_info_t *req); -static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx); +static PyObject *nxt_python_get_environ(nxt_python_ctx_t *pctx, + nxt_python_target_t *app_target); static int nxt_python_add_sptr(nxt_python_ctx_t *pctx, PyObject *name, nxt_unit_sptr_t *sptr, uint32_t size); static int nxt_python_add_char(nxt_python_ctx_t *pctx, PyObject *name, @@ -141,6 +142,7 @@ static PyObject *nxt_py_query_string_str; static PyObject *nxt_py_remote_addr_str; static PyObject *nxt_py_request_method_str; static PyObject *nxt_py_request_uri_str; +static PyObject *nxt_py_script_name_str; static PyObject *nxt_py_server_addr_str; static PyObject *nxt_py_server_name_str; static PyObject *nxt_py_server_port_str; @@ -160,6 +162,7 @@ static nxt_python_string_t nxt_python_strings[] = { { nxt_string("REMOTE_ADDR"), &nxt_py_remote_addr_str }, { nxt_string("REQUEST_METHOD"), &nxt_py_request_method_str }, { nxt_string("REQUEST_URI"), &nxt_py_request_uri_str }, + { nxt_string("SCRIPT_NAME"), &nxt_py_script_name_str }, { nxt_string("SERVER_ADDR"), &nxt_py_server_addr_str }, { nxt_string("SERVER_NAME"), &nxt_py_server_name_str }, { nxt_string("SERVER_PORT"), &nxt_py_server_port_str }, @@ -304,11 +307,12 @@ nxt_python_wsgi_done(void) static void nxt_python_request_handler(nxt_unit_request_info_t *req) { - int rc; - PyObject *environ, *args, *response, *iterator, *item; - PyObject *close, *result, *application; - nxt_bool_t prepare_environ; - nxt_python_ctx_t *pctx; + int rc; + PyObject *environ, *args, *response, *iterator, *item; + PyObject *close, *result; + nxt_bool_t prepare_environ; + nxt_python_ctx_t *pctx; + nxt_python_target_t *target; pctx = req->ctx->data; @@ -331,7 +335,9 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) prepare_environ = 1; - environ = nxt_python_get_environ(pctx); + target = &nxt_py_targets->target[req->request->app_target]; + + environ = nxt_python_get_environ(pctx, target); if (nxt_slow_path(environ == NULL)) { rc = NXT_UNIT_ERROR; goto done; @@ -352,8 +358,7 @@ nxt_python_request_handler(nxt_unit_request_info_t *req) Py_INCREF(pctx->start_resp); PyTuple_SET_ITEM(args, 1, pctx->start_resp); - application = nxt_py_targets->target[req->request->app_target].application; - response = PyObject_CallObject(application, args); + response = PyObject_CallObject(target->application, args); Py_DECREF(args); @@ -584,11 +589,14 @@ nxt_python_copy_environ(nxt_unit_request_info_t *req) static PyObject * -nxt_python_get_environ(nxt_python_ctx_t *pctx) +nxt_python_get_environ(nxt_python_ctx_t *pctx, + nxt_python_target_t *app_target) { int rc; - uint32_t i, j, vl; + char *path; + uint32_t i, j, vl, path_length; PyObject *environ; + nxt_str_t prefix; nxt_unit_field_t *f, *f2; nxt_unit_request_t *r; @@ -608,8 +616,23 @@ nxt_python_get_environ(nxt_python_ctx_t *pctx) r->target_length)); RC(nxt_python_add_sptr(pctx, nxt_py_query_string_str, &r->query, r->query_length)); - RC(nxt_python_add_sptr(pctx, nxt_py_path_info_str, &r->path, - r->path_length)); + + prefix = app_target->prefix; + path_length = r->path_length; + path = nxt_unit_sptr_get(&r->path); + if (prefix.length > 0 + && ((path_length > prefix.length && path[prefix.length] == '/') + || path_length == prefix.length) + && memcmp(prefix.start, path, prefix.length) == 0) + { + RC(nxt_python_add_py_string(pctx, nxt_py_script_name_str, + app_target->py_prefix)); + + path += prefix.length; + path_length -= prefix.length; + } + + RC(nxt_python_add_char(pctx, nxt_py_path_info_str, path, path_length)); RC(nxt_python_add_sptr(pctx, nxt_py_remote_addr_str, &r->remote, r->remote_length)); -- cgit