summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorKonstantin Pavlov <thresh@nginx.com>2022-12-15 08:17:39 -0800
committerKonstantin Pavlov <thresh@nginx.com>2022-12-15 08:17:39 -0800
commite22669f2728814aba82da14702d18bfa9685311e (patch)
treec9c9471dab359e8e33fca24c5d4f035ab5b278db /src
parenta1d28488f9df8e28ee25ea438c275b96b9afe5b6 (diff)
parent4409a10ff0bd6bb45fb88716bd383cd867958a8a (diff)
downloadunit-e22669f2728814aba82da14702d18bfa9685311e.tar.gz
unit-e22669f2728814aba82da14702d18bfa9685311e.tar.bz2
Merged with the default branch.
Diffstat (limited to 'src')
-rw-r--r--src/java/nxt_jni_Request.c20
-rw-r--r--src/nodejs/unit-http/loader.mjs6
-rw-r--r--src/nodejs/unit-http/unit.cpp3
-rw-r--r--src/nxt_application.c2
-rw-r--r--src/nxt_application.h2
-rw-r--r--src/nxt_capability.c2
-rw-r--r--src/nxt_cgroup.c174
-rw-r--r--src/nxt_cgroup.h14
-rw-r--r--src/nxt_conf.c6
-rw-r--r--src/nxt_conf.h2
-rw-r--r--src/nxt_conf_validation.c175
-rw-r--r--src/nxt_conn.h3
-rw-r--r--src/nxt_conn_close.c8
-rw-r--r--src/nxt_controller.c14
-rw-r--r--src/nxt_errno.c6
-rw-r--r--src/nxt_file.c37
-rw-r--r--src/nxt_file.h4
-rw-r--r--src/nxt_fs.c250
-rw-r--r--src/nxt_fs.h33
-rw-r--r--src/nxt_fs_mount.c230
-rw-r--r--src/nxt_fs_mount.h48
-rw-r--r--src/nxt_h1proto.c8
-rw-r--r--src/nxt_http.h7
-rw-r--r--src/nxt_http_js.c273
-rw-r--r--src/nxt_http_parse.c6
-rw-r--r--src/nxt_http_request.c13
-rw-r--r--src/nxt_http_return.c30
-rw-r--r--src/nxt_http_route.c66
-rw-r--r--src/nxt_http_route_addr.c16
-rw-r--r--src/nxt_http_static.c52
-rw-r--r--src/nxt_http_variables.c43
-rw-r--r--src/nxt_isolation.c50
-rw-r--r--src/nxt_js.c299
-rw-r--r--src/nxt_js.h38
-rw-r--r--src/nxt_main.h2
-rw-r--r--src/nxt_main_process.c16
-rw-r--r--src/nxt_openssl.c20
-rw-r--r--src/nxt_php_sapi.c112
-rw-r--r--src/nxt_port.c4
-rw-r--r--src/nxt_process.c12
-rw-r--r--src/nxt_process.h13
-rw-r--r--src/nxt_router.c23
-rw-r--r--src/nxt_router.h6
-rw-r--r--src/nxt_router_access_log.c27
-rw-r--r--src/nxt_runtime.c2
-rw-r--r--src/nxt_runtime.h3
-rw-r--r--src/nxt_sockaddr.c14
-rw-r--r--src/nxt_string.c4
-rw-r--r--src/nxt_string.h14
-rw-r--r--src/nxt_tstr.c317
-rw-r--r--src/nxt_tstr.h79
-rw-r--r--src/nxt_unit.c42
-rw-r--r--src/nxt_unit_request.h6
-rw-r--r--src/nxt_var.c223
-rw-r--r--src/nxt_var.h34
-rw-r--r--src/perl/nxt_perl_psgi.c4
-rw-r--r--src/python/nxt_python.c133
-rw-r--r--src/python/nxt_python.h2
-rw-r--r--src/python/nxt_python_asgi.c70
-rw-r--r--src/python/nxt_python_asgi_str.c2
-rw-r--r--src/python/nxt_python_wsgi.c83
-rw-r--r--src/ruby/nxt_ruby.c13
-rw-r--r--src/test/nxt_http_parse_test.c2
-rw-r--r--src/test/nxt_tests.c2
-rw-r--r--src/test/nxt_unit_app_test.c2
-rw-r--r--src/test/nxt_unit_websocket_chat.c2
-rw-r--r--src/test/nxt_unit_websocket_echo.c2
-rw-r--r--src/test/nxt_utf8_file_name_test.c2
-rw-r--r--src/test/nxt_utf8_test.c2
69 files changed, 2457 insertions, 777 deletions
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/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,
}
}
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_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_application.h b/src/nxt_application.h
index 30a1a12f..4d624448 100644
--- a/src/nxt_application.h
+++ b/src/nxt_application.h
@@ -49,8 +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;
uint32_t thread_stack_size;
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_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 <nxt_main.h>
+
+#include <nxt_cgroup.h>
+
+
+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/<main process cgroup>/<cgroup path>
+ */
+ 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_ */
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_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 fe6c22e5..bf8aa760 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;
@@ -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,
@@ -219,6 +221,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 +247,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
@@ -307,6 +317,12 @@ 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("large_header_buffers"),
+ .type = NXT_CONF_VLDT_INTEGER,
+ }, {
.name = nxt_string("body_buffer_size"),
.type = NXT_CONF_VLDT_INTEGER,
}, {
@@ -367,7 +383,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 +668,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 +683,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 +713,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,
@@ -782,6 +798,11 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = {
.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,
.validator = nxt_conf_vldt_targets,
@@ -800,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
@@ -814,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)
@@ -1094,6 +1123,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 +1204,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[] = {
@@ -1226,9 +1280,10 @@ nxt_int_t
nxt_conf_validate(nxt_conf_validation_t *vldt)
{
nxt_int_t ret;
+ u_char error[NXT_MAX_ERROR_STR];
- 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, 1);
+ if (nxt_slow_path(vldt->tstr_state == NULL)) {
return NXT_ERROR;
}
@@ -1237,7 +1292,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;
}
@@ -1364,7 +1429,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);
}
@@ -1690,11 +1755,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 +1767,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);
}
@@ -1742,7 +1786,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);
}
@@ -1842,6 +1886,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)
{
@@ -2522,12 +2588,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;
@@ -2731,12 +2797,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.");
}
@@ -2748,7 +2814,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);
}
@@ -2808,6 +2874,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)
@@ -2947,7 +3042,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.");
}
@@ -3006,7 +3101,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.");
}
@@ -3027,7 +3122,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.");
}
@@ -3168,7 +3263,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_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,
diff --git a/src/nxt_controller.c b/src/nxt_controller.c
index 09168821..b5e0d831 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;
}
@@ -1255,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;
}
@@ -1629,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;
@@ -1932,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_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);
diff --git a/src/nxt_fs.c b/src/nxt_fs.c
index 71498f99..a467da98 100644
--- a/src/nxt_fs.c
+++ b/src/nxt_fs.c
@@ -4,235 +4,10 @@
#include <nxt_main.h>
-#if (NXT_HAVE_FREEBSD_NMOUNT)
-#include <sys/param.h>
-#include <sys/uio.h>
-#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)
{
@@ -273,6 +48,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..c8868d80 100644
--- a/src/nxt_fs.h
+++ b/src/nxt_fs.h
@@ -6,39 +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 <nxt_main.h>
+
+#if (NXT_HAVE_FREEBSD_NMOUNT)
+#include <sys/param.h>
+#include <sys/uio.h>
+#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_h1proto.c b/src/nxt_h1proto.c
index 852b4866..1e37273f 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;
@@ -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;
@@ -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.h b/src/nxt_http.h
index c2e85840..a8725d9f 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;
@@ -167,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_tstr_cache_t tstr_cache;
void *req_rpc_data;
@@ -243,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_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 <nxt_router.h>
+#include <nxt_http.h>
+#include <njs.h>
+
+
+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_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_request.c b/src/nxt_http_request.c
index 943ad82d..73ffd2f0 100644
--- a/src/nxt_http_request.c
+++ b/src/nxt_http_request.c
@@ -278,8 +278,12 @@ 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++;
+ r->tstr_cache.var.pool = mp;
+
return r;
fail:
@@ -793,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;
@@ -1035,14 +1039,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;
diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c
index 9f3c4fc5..b50e4ad0 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->tstr_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 cdc9077f..7081ff7e 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;
}
@@ -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. */
@@ -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->tstr_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;
@@ -1414,7 +1418,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--;
@@ -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;
}
@@ -1740,15 +1744,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 +1790,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 +1941,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 +2019,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 +2162,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..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))) {
@@ -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;
@@ -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)) {
@@ -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;
@@ -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_http_static.c b/src/nxt_http_static.c
index 0507e038..68174b9d 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->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;
}
- 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 5a632b24..fa0244db 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,
@@ -46,6 +48,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,
}, {
@@ -111,6 +116,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)
{
nxt_http_request_t *r;
@@ -374,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)) {
@@ -388,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;
@@ -417,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) {
@@ -452,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)) {
@@ -466,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_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 <nxt_application.h>
#include <nxt_process.h>
#include <nxt_isolation.h>
+#include <nxt_cgroup.h>
#if (NXT_HAVE_MNTENT_H)
#include <mntent.h>
@@ -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_js.c b/src/nxt_js.c
new file mode 100644
index 00000000..aa3c4af5
--- /dev/null
+++ b/src/nxt_js.c
@@ -0,0 +1,299 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+
+
+struct nxt_js_s {
+ uint32_t index;
+ njs_vm_t *vm;
+};
+
+
+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)
+{
+ 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;
+}
+
+
+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)
+{
+ size_t size;
+ u_char *p, *start;
+ nxt_js_t *js;
+ nxt_str_t *func;
+
+ static nxt_str_t func_str = nxt_string("function(uri, host, remoteAddr, "
+ "args, headers, cookies) {"
+ " 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++ = ']';
+
+ 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;
+}
+
+
+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, 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;
+
+ 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_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) {
+ 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..dea43fe3
--- /dev/null
+++ b/src/nxt_js.h
@@ -0,0 +1,38 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_JS_H_INCLUDED_
+#define _NXT_JS_H_INCLUDED_
+
+#if (NXT_HAVE_NJS)
+
+#include <njs_main.h>
+
+
+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);
+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);
+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_main.h b/src/nxt_main.h
index dca4b6dc..b0cdc2d3 100644
--- a/src/nxt_main.h
+++ b/src/nxt_main.h
@@ -59,6 +59,7 @@ typedef uint16_t nxt_port_id_t;
#include <nxt_process_type.h>
#include <nxt_capability.h>
#include <nxt_credential.h>
+#include <nxt_fs_mount.h>
#include <nxt_fs.h>
#include <nxt_process.h>
#include <nxt_utf8.h>
@@ -67,6 +68,7 @@ typedef uint16_t nxt_port_id_t;
#include <nxt_sprintf.h>
#include <nxt_parse.h>
#include <nxt_var.h>
+#include <nxt_tstr.h>
/* TODO: remove unused */
diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c
index 39a8e112..de41e8d7 100644
--- a/src/nxt_main_process.c
+++ b/src/nxt_main_process.c
@@ -191,18 +191,6 @@ static nxt_conf_map_t nxt_python_app_conf[] = {
},
{
- 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,
offsetof(nxt_common_app_conf_t, u.python.protocol),
@@ -1019,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_openssl.c b/src/nxt_openssl.c
index e19b1381..f56135f3 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)
@@ -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;
}
@@ -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;
}
diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c
index 68ef07eb..126a4684 100644
--- a/src/nxt_php_sapi.c
+++ b/src/nxt_php_sapi.c
@@ -14,22 +14,23 @@
#include <nxt_router.h>
#include <nxt_unit.h>
#include <nxt_unit_request.h>
+#include <nxt_http.h>
-#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 +74,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
@@ -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);
@@ -139,7 +142,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 +358,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 +380,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);
@@ -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
+ || 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
@@ -1150,7 +1228,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
}
@@ -1365,7 +1447,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_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/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 <nxt_main.h>
+#include <nxt_cgroup.h>
#if (NXT_HAVE_CLONE)
#include <nxt_clone.h>
@@ -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
diff --git a/src/nxt_router.c b/src/nxt_router.c
index f02bf3f2..edc015c5 100644
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -1060,11 +1060,15 @@ 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, 0);
+ if (nxt_slow_path(rtcf->tstr_state == NULL)) {
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;
@@ -2042,6 +2046,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);
@@ -5249,11 +5258,17 @@ 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';
+ 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_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..ccbddb96 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->tstr_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_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);
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_sockaddr.c b/src/nxt_sockaddr.c
index 86c3335e..32941893 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)) {
@@ -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.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..18ea5490 100644
--- a/src/nxt_string.h
+++ b/src/nxt_string.h
@@ -66,14 +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)
-
-
#define nxt_strcmp(s1, s2) \
strcmp((char *) s1, (char *) s2)
@@ -132,7 +124,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 +133,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/nxt_tstr.c b/src/nxt_tstr.c
new file mode 100644
index 00000000..fd01797c
--- /dev/null
+++ b/src/nxt_tstr.c
@@ -0,0 +1,317 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+
+
+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;
+
+ 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;
+};
+
+
+struct nxt_tstr_query_s {
+ nxt_mp_t *pool;
+
+ nxt_tstr_state_t *state;
+ nxt_tstr_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;
+};
+
+
+#define nxt_tstr_is_js(str) \
+ nxt_strchr_start(str, '`')
+
+
+nxt_tstr_state_t *
+nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test)
+{
+ 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->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;
+}
+
+
+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;
+
+ if (nxt_tstr_is_js(str)) {
+
+#if (NXT_HAVE_NJS)
+
+ nxt_str_t tpl;
+
+ tstr->type = NXT_TSTR_JS;
+
+ 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 {
+ 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;
+}
+
+
+nxt_int_t
+nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *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;
+}
+
+
+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_tstr_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;
+ }
+
+ 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) {
+ val->length--;
+ }
+
+#if (NXT_DEBUG)
+ nxt_str_t str;
+
+ nxt_tstr_str(tstr, &str);
+
+ nxt_debug(task, "tstr query: \"%V\", result: \"%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..0cc24292
--- /dev/null
+++ b/src/nxt_tstr.h
@@ -0,0 +1,79 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_TSTR_H_INCLUDED_
+#define _NXT_TSTR_H_INCLUDED_
+
+
+#include <nxt_js.h>
+
+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;
+#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_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_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);
+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);
+
+
+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_unit.c b/src/nxt_unit.c
index e5cb0b58..e1b1897a 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);
@@ -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);
@@ -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);
}
@@ -6661,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;
diff --git a/src/nxt_unit_request.h b/src/nxt_unit_request.h
index 5dbf648d..a6ebf0b6 100644
--- a/src/nxt_unit_request.h
+++ b/src/nxt_unit_request.h
@@ -18,7 +18,8 @@ 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 local_port_length;
uint8_t tls;
uint8_t websocket_handshake;
uint8_t app_target;
@@ -38,7 +39,8 @@ 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 local_port;
nxt_unit_sptr_t server_name;
nxt_unit_sptr_t target;
nxt_unit_sptr_t path;
diff --git a/src/nxt_var.c b/src/nxt_var.c
index f55a2d30..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,11 +56,10 @@ 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, 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) = {
@@ -233,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);
@@ -256,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;
@@ -330,65 +327,55 @@ 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_bool_t is_var;
nxt_var_sub_t *subs;
nxt_var_decl_t *decl;
- strz = (flags & NXT_VAR_STRZ) != 0;
-
n = 0;
p = str->start;
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++;
}
}
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;
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 +400,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 +415,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 +434,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 = nxt_memchr(start, '$', length);
+ p = memchr(start, '$', end - start);
if (p == start) {
- *is_var = 1;
-
p++;
if (p == end) {
@@ -480,129 +462,74 @@ 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;
-
- return end;
-}
-
-
-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;
- }
+ nxt_str_null(part);
}
- query->pool = mp;
- query->ctx = ctx;
-
- *query_p = query;
-
- return NXT_OK;
+ return p;
}
-void
-nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var,
- nxt_str_t *str)
+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)
{
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;
@@ -614,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;
@@ -647,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 cc7ff502..ab25800d 100644
--- a/src/nxt_var.h
+++ b/src/nxt_var.h
@@ -32,17 +32,11 @@ typedef struct {
} nxt_var_field_t;
-typedef enum {
- NXT_VAR_STRZ = 1 << 0,
- NXT_VAR_LOGGING = 1 << 1,
-} nxt_var_flags_t;
-
-
-nxt_inline nxt_bool_t
-nxt_is_var(nxt_str_t *str)
-{
- return (nxt_memchr(str->start, '$', str->length) != NULL);
-}
+typedef struct {
+ nxt_mp_t *pool;
+ nxt_lvlhsh_t hash;
+ nxt_str_t *spare;
+} nxt_var_cache_t;
nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n);
@@ -50,21 +44,13 @@ 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);
+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_ */
diff --git a/src/perl/nxt_perl_psgi.c b/src/perl/nxt_perl_psgi.c
index 08a6f29e..5e8d1aee 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));
@@ -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;
}
diff --git a/src/python/nxt_python.c b/src/python/nxt_python.c
index 188c4920..bdb04579 100644
--- a/src/python/nxt_python.c
+++ b/src/python/nxt_python.c
@@ -22,10 +22,16 @@ 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,
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);
@@ -64,13 +70,70 @@ 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)
{
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;
@@ -127,11 +190,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
@@ -154,7 +221,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 +373,6 @@ fail:
}
Py_XDECREF(obj);
- Py_XDECREF(module);
nxt_python_atexit();
@@ -326,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;
@@ -373,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;
@@ -390,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)
{
@@ -667,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();
@@ -677,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 4ad0857d..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)
@@ -674,7 +688,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;
@@ -738,42 +752,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);
}
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 87dcfaa2..dfb31509 100644
--- a/src/python/nxt_python_wsgi.c
+++ b/src/python/nxt_python_wsgi.c
@@ -60,9 +60,14 @@ 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,
+ 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);
@@ -137,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;
@@ -156,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 },
@@ -300,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;
@@ -327,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;
@@ -348,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);
@@ -580,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;
@@ -604,13 +616,28 @@ 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));
- 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,
@@ -692,10 +719,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 +740,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;
}
diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c
index f316d8a5..bcb48f6b 100644
--- a/src/ruby/nxt_ruby.c
+++ b/src/ruby/nxt_ruby.c
@@ -480,14 +480,19 @@ 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");
+ nxt_ruby_exception_log(NULL, NXT_LOG_ALERT, "Invalid rack config file");
return Qnil;
}
@@ -747,8 +752,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_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_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));
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;
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++) {