Due to the sandboxed nature of WebAssembly, by default WASM modules
don't have any access to the underlying filesystem.
There is however a capabilities based mechanism[0] for allowing such
access.
This adds a config option to the 'wasm' application type;
'access.filesystem' which takes an array of directory paths that are
then made available to the WASM module. This access works recursively,
i.e everything under a specific path is allowed access to.
Example config might look like
"access" {
"filesystem": [
"/tmp",
"/var/tmp"
]
}
The actual mechanism used allows directories to be mapped differently in
the guest. But at the moment we don't support that and just map say /tmp
to /tmp. This can be revisited if it's something users clamour for.
Network sockets are another resource that may be controlled in this
manner, for example there is a wasi_config_preopen_socket() function,
however this requires the runtime to open the network socket then
effectively pass this through to the guest.
This is something that can be revisited in the future if users desire
it.
[0]:
<https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-capabilities.md>
Reviewed-by: Alejandro Colomar <alx@nginx.com>
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
3444 lines
96 KiB
C
3444 lines
96 KiB
C
|
|
/*
|
|
* Copyright (C) Valentin V. Bartenev
|
|
* Copyright (C) NGINX, Inc.
|
|
*/
|
|
|
|
#include <nxt_main.h>
|
|
#include <nxt_conf.h>
|
|
#include <nxt_cert.h>
|
|
#include <nxt_script.h>
|
|
#include <nxt_router.h>
|
|
#include <nxt_http.h>
|
|
#include <nxt_sockaddr.h>
|
|
#include <nxt_http_route_addr.h>
|
|
#include <nxt_regex.h>
|
|
|
|
|
|
typedef enum {
|
|
NXT_CONF_VLDT_NULL = 1 << NXT_CONF_NULL,
|
|
NXT_CONF_VLDT_BOOLEAN = 1 << NXT_CONF_BOOLEAN,
|
|
NXT_CONF_VLDT_INTEGER = 1 << NXT_CONF_INTEGER,
|
|
NXT_CONF_VLDT_NUMBER = (1 << NXT_CONF_NUMBER) | NXT_CONF_VLDT_INTEGER,
|
|
NXT_CONF_VLDT_STRING = 1 << NXT_CONF_STRING,
|
|
NXT_CONF_VLDT_ARRAY = 1 << NXT_CONF_ARRAY,
|
|
NXT_CONF_VLDT_OBJECT = 1 << NXT_CONF_OBJECT,
|
|
} nxt_conf_vldt_type_t;
|
|
|
|
#define NXT_CONF_VLDT_ANY_TYPE (NXT_CONF_VLDT_NULL \
|
|
|NXT_CONF_VLDT_BOOLEAN \
|
|
|NXT_CONF_VLDT_NUMBER \
|
|
|NXT_CONF_VLDT_STRING \
|
|
|NXT_CONF_VLDT_ARRAY \
|
|
|NXT_CONF_VLDT_OBJECT)
|
|
|
|
|
|
typedef enum {
|
|
NXT_CONF_VLDT_REQUIRED = 1 << 0,
|
|
NXT_CONF_VLDT_TSTR = 1 << 1,
|
|
} nxt_conf_vldt_flags_t;
|
|
|
|
|
|
typedef nxt_int_t (*nxt_conf_vldt_handler_t)(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value,
|
|
void *data);
|
|
typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name,
|
|
nxt_conf_value_t *value);
|
|
typedef nxt_int_t (*nxt_conf_vldt_element_t)(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
|
|
|
|
typedef struct nxt_conf_vldt_object_s nxt_conf_vldt_object_t;
|
|
|
|
struct nxt_conf_vldt_object_s {
|
|
nxt_str_t name;
|
|
nxt_conf_vldt_type_t type:32;
|
|
nxt_conf_vldt_flags_t flags:32;
|
|
nxt_conf_vldt_handler_t validator;
|
|
|
|
union {
|
|
nxt_conf_vldt_object_t *members;
|
|
nxt_conf_vldt_object_t *next;
|
|
nxt_conf_vldt_member_t object;
|
|
nxt_conf_vldt_element_t array;
|
|
const char *string;
|
|
} u;
|
|
};
|
|
|
|
|
|
#define NXT_CONF_VLDT_NEXT(next) { .u.members = next }
|
|
#define NXT_CONF_VLDT_END { .name = nxt_null_string }
|
|
|
|
|
|
static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type);
|
|
static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt,
|
|
const char *fmt, ...);
|
|
static nxt_int_t nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_str_t *value);
|
|
nxt_inline nxt_int_t nxt_conf_vldt_unsupported(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
NXT_MAYBE_UNUSED;
|
|
|
|
static nxt_int_t nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
#if (NXT_TLS)
|
|
static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
#if (NXT_HAVE_OPENSSL_CONF_CMD)
|
|
static nxt_int_t nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
#endif
|
|
static nxt_int_t nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_tls_cache_size(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_tls_timeout(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
#if (NXT_HAVE_OPENSSL_TLSEXT)
|
|
static nxt_int_t nxt_conf_vldt_ticket_key(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_ticket_key_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
#endif
|
|
#endif
|
|
static nxt_int_t nxt_conf_vldt_action(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_pass(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_return(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_share(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_python(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_python_path(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
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,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_routes(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets(
|
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set(
|
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set_member(
|
|
nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns(
|
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_match_encoded_pattern(
|
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_match_patterns_set_member(
|
|
nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_response_header(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_targets_exclusive(
|
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_targets(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_target(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_php(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
|
|
static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
|
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
|
static nxt_int_t nxt_conf_vldt_clone_procmap(nxt_conf_validation_t *vldt,
|
|
const char* mapfile, nxt_conf_value_t *value);
|
|
static nxt_int_t nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
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
|
|
|
|
#if (NXT_HAVE_NJS)
|
|
static nxt_int_t nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data);
|
|
static nxt_int_t nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value);
|
|
#endif
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[];
|
|
#if (NXT_TLS)
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_session_members[];
|
|
#endif
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_access_members[];
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[];
|
|
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
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[];
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
|
|
{
|
|
.name = nxt_string("settings"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_setting_members,
|
|
}, {
|
|
.name = nxt_string("listeners"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object_iterator,
|
|
.u.object = nxt_conf_vldt_listener,
|
|
}, {
|
|
.name = nxt_string("routes"),
|
|
.type = NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_routes,
|
|
}, {
|
|
.name = nxt_string("applications"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object_iterator,
|
|
.u.object = nxt_conf_vldt_app,
|
|
}, {
|
|
.name = nxt_string("upstreams"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object_iterator,
|
|
.u.object = nxt_conf_vldt_upstream,
|
|
}, {
|
|
.name = nxt_string("access_log"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_access_log,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = {
|
|
{
|
|
.name = nxt_string("http"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_http_members,
|
|
#if (NXT_HAVE_NJS)
|
|
}, {
|
|
.name = nxt_string("js_module"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_js_module,
|
|
#endif
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = {
|
|
{
|
|
.name = nxt_string("header_read_timeout"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("body_read_timeout"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("send_timeout"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.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,
|
|
}, {
|
|
.name = nxt_string("max_body_size"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("body_temp_path"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("discard_unsafe_fields"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
}, {
|
|
.name = nxt_string("websocket"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_websocket_members,
|
|
}, {
|
|
.name = nxt_string("static"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_static_members,
|
|
}, {
|
|
.name = nxt_string("log_route"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
}, {
|
|
.name = nxt_string("server_version"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[] = {
|
|
{
|
|
.name = nxt_string("read_timeout"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
|
|
.name = nxt_string("keepalive_interval"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("max_frame_size"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[] = {
|
|
{
|
|
.name = nxt_string("mime_types"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_mtypes,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
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_TSTR,
|
|
}, {
|
|
.name = nxt_string("application"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.validator = nxt_conf_vldt_app_name,
|
|
}, {
|
|
.name = nxt_string("forwarded"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_forwarded,
|
|
}, {
|
|
.name = nxt_string("client_ip"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_client_ip_members
|
|
},
|
|
|
|
#if (NXT_TLS)
|
|
{
|
|
.name = nxt_string("tls"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_tls_members,
|
|
},
|
|
#endif
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[] = {
|
|
{
|
|
.name = nxt_string("client_ip"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("protocol"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("source"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_addrs,
|
|
.flags = NXT_CONF_VLDT_REQUIRED
|
|
}, {
|
|
.name = nxt_string("recursive"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[] = {
|
|
{
|
|
.name = nxt_string("source"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_addrs,
|
|
.flags = NXT_CONF_VLDT_REQUIRED
|
|
}, {
|
|
.name = nxt_string("header"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED
|
|
}, {
|
|
.name = nxt_string("recursive"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
#if (NXT_TLS)
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = {
|
|
{
|
|
.name = nxt_string("certificate"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
.validator = nxt_conf_vldt_certificate,
|
|
}, {
|
|
.name = nxt_string("conf_commands"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
#if (NXT_HAVE_OPENSSL_CONF_CMD)
|
|
.validator = nxt_conf_vldt_object_conf_commands,
|
|
#else
|
|
.validator = nxt_conf_vldt_unsupported,
|
|
.u.string = "conf_commands",
|
|
#endif
|
|
}, {
|
|
.name = nxt_string("session"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_session_members,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_session_members[] = {
|
|
{
|
|
.name = nxt_string("cache_size"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_tls_cache_size,
|
|
}, {
|
|
.name = nxt_string("timeout"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_tls_timeout,
|
|
}, {
|
|
.name = nxt_string("tickets"),
|
|
.type = NXT_CONF_VLDT_STRING
|
|
| NXT_CONF_VLDT_ARRAY
|
|
| NXT_CONF_VLDT_BOOLEAN,
|
|
#if (NXT_HAVE_OPENSSL_TLSEXT)
|
|
.validator = nxt_conf_vldt_ticket_key,
|
|
#else
|
|
.validator = nxt_conf_vldt_unsupported,
|
|
.u.string = "tickets",
|
|
#endif
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_tls_cache_size(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
int64_t cache_size;
|
|
|
|
cache_size = nxt_conf_get_number(value);
|
|
|
|
if (cache_size < 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"cache_size\" number must not "
|
|
"be negative.");
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_tls_timeout(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
int64_t timeout;
|
|
|
|
timeout = nxt_conf_get_number(value);
|
|
|
|
if (timeout <= 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"timeout\" number must be "
|
|
"greater than zero.");
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if (NXT_HAVE_OPENSSL_TLSEXT)
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_ticket_key(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
if (nxt_conf_type(value) == NXT_CONF_BOOLEAN) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_ticket_key_element);
|
|
}
|
|
|
|
/* NXT_CONF_STRING */
|
|
|
|
return nxt_conf_vldt_ticket_key_element(vldt, value);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_ticket_key_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
ssize_t ret;
|
|
nxt_str_t key;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"key\" array must "
|
|
"contain only string values.");
|
|
}
|
|
|
|
nxt_conf_get_string(value, &key);
|
|
|
|
ret = nxt_base64_decode(NULL, key.start, key.length);
|
|
if (ret == NXT_ERROR) {
|
|
return nxt_conf_vldt_error(vldt, "Invalid Base64 format for the ticket "
|
|
"key \"%V\".", &key);
|
|
}
|
|
|
|
if (ret != 48 && ret != 80) {
|
|
return nxt_conf_vldt_error(vldt, "Invalid length %d of the ticket "
|
|
"key \"%V\". Must be 48 or 80 bytes.",
|
|
ret, &key);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_route_members[] = {
|
|
{
|
|
.name = nxt_string("match"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_match_members,
|
|
}, {
|
|
.name = nxt_string("action"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_action,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = {
|
|
{
|
|
.name = nxt_string("method"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_patterns,
|
|
.u.string = "method",
|
|
}, {
|
|
.name = nxt_string("scheme"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.validator = nxt_conf_vldt_match_scheme_pattern,
|
|
}, {
|
|
.name = nxt_string("host"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_patterns,
|
|
.u.string = "host",
|
|
}, {
|
|
.name = nxt_string("source"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_addrs,
|
|
}, {
|
|
.name = nxt_string("destination"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_addrs,
|
|
}, {
|
|
.name = nxt_string("uri"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_encoded_patterns,
|
|
.u.string = "uri"
|
|
}, {
|
|
.name = nxt_string("query"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_encoded_patterns,
|
|
.u.string = "query"
|
|
}, {
|
|
.name = nxt_string("arguments"),
|
|
.type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_encoded_patterns_sets,
|
|
}, {
|
|
.name = nxt_string("headers"),
|
|
.type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_patterns_sets,
|
|
.u.string = "headers"
|
|
}, {
|
|
.name = nxt_string("cookies"),
|
|
.type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_patterns_sets,
|
|
.u.string = "cookies"
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_action_common_members[] = {
|
|
{
|
|
.name = nxt_string("rewrite"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
},
|
|
{
|
|
.name = nxt_string("response_headers"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object_iterator,
|
|
.u.object = nxt_conf_vldt_response_header,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
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_TSTR,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = {
|
|
{
|
|
.name = nxt_string("return"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_return,
|
|
}, {
|
|
.name = nxt_string("location"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_TSTR,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = {
|
|
{
|
|
.name = nxt_string("share"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_share,
|
|
}, {
|
|
.name = nxt_string("index"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("types"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_match_patterns,
|
|
}, {
|
|
.name = nxt_string("fallback"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_action,
|
|
}, {
|
|
.name = nxt_string("chroot"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
#if !(NXT_HAVE_OPENAT2)
|
|
.validator = nxt_conf_vldt_unsupported,
|
|
.u.string = "chroot",
|
|
#endif
|
|
.flags = NXT_CONF_VLDT_TSTR,
|
|
}, {
|
|
.name = nxt_string("follow_symlinks"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
#if !(NXT_HAVE_OPENAT2)
|
|
.validator = nxt_conf_vldt_unsupported,
|
|
.u.string = "follow_symlinks",
|
|
#endif
|
|
}, {
|
|
.name = nxt_string("traverse_mounts"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
#if !(NXT_HAVE_OPENAT2)
|
|
.validator = nxt_conf_vldt_unsupported,
|
|
.u.string = "traverse_mounts",
|
|
#endif
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = {
|
|
{
|
|
.name = nxt_string("proxy"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.validator = nxt_conf_vldt_proxy,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = {
|
|
{
|
|
.name = nxt_string("executable"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("arguments"),
|
|
.type = NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_array_iterator,
|
|
.u.array = nxt_conf_vldt_argument,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_python_common_members[] = {
|
|
{
|
|
.name = nxt_string("home"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("path"),
|
|
.type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_python_path,
|
|
}, {
|
|
.name = nxt_string("protocol"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.validator = nxt_conf_vldt_python_protocol,
|
|
}, {
|
|
.name = nxt_string("threads"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_threads,
|
|
}, {
|
|
.name = nxt_string("thread_stack_size"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_thread_stack_size,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
|
|
};
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = {
|
|
{
|
|
.name = nxt_string("module"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.validator = nxt_conf_vldt_targets_exclusive,
|
|
.u.string = "module",
|
|
}, {
|
|
.name = nxt_string("callable"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.validator = nxt_conf_vldt_targets_exclusive,
|
|
.u.string = "callable",
|
|
}, {
|
|
.name = nxt_string("prefix"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.validator = nxt_conf_vldt_targets_exclusive,
|
|
.u.string = "prefix",
|
|
}, {
|
|
.name = nxt_string("targets"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_targets,
|
|
.u.members = nxt_conf_vldt_python_target_members
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[] = {
|
|
{
|
|
.name = nxt_string("module"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.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
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_python_notargets_members[] = {
|
|
{
|
|
.name = nxt_string("module"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.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)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = {
|
|
{
|
|
.name = nxt_string("root"),
|
|
.type = NXT_CONF_VLDT_ANY_TYPE,
|
|
.validator = nxt_conf_vldt_targets_exclusive,
|
|
.u.string = "root",
|
|
}, {
|
|
.name = nxt_string("script"),
|
|
.type = NXT_CONF_VLDT_ANY_TYPE,
|
|
.validator = nxt_conf_vldt_targets_exclusive,
|
|
.u.string = "script",
|
|
}, {
|
|
.name = nxt_string("index"),
|
|
.type = NXT_CONF_VLDT_ANY_TYPE,
|
|
.validator = nxt_conf_vldt_targets_exclusive,
|
|
.u.string = "index",
|
|
}, {
|
|
.name = nxt_string("targets"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_targets,
|
|
.u.members = nxt_conf_vldt_php_target_members
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_php_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[] = {
|
|
{
|
|
.name = nxt_string("options"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_php_options_members,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[] = {
|
|
{
|
|
.name = nxt_string("file"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("admin"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object_iterator,
|
|
.u.object = nxt_conf_vldt_php_option,
|
|
}, {
|
|
.name = nxt_string("user"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object_iterator,
|
|
.u.object = nxt_conf_vldt_php_option,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[] = {
|
|
{
|
|
.name = nxt_string("root"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("script"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("index"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_php_notargets_members[] = {
|
|
{
|
|
.name = nxt_string("root"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("script"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("index"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_php_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = {
|
|
{
|
|
.name = nxt_string("script"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("threads"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_threads,
|
|
}, {
|
|
.name = nxt_string("thread_stack_size"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_thread_stack_size,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = {
|
|
{
|
|
.name = nxt_string("script"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("threads"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_threads,
|
|
}, {
|
|
.name = nxt_string("hooks"),
|
|
.type = NXT_CONF_VLDT_STRING
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = {
|
|
{
|
|
.name = nxt_string("classpath"),
|
|
.type = NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_array_iterator,
|
|
.u.array = nxt_conf_vldt_java_classpath,
|
|
}, {
|
|
.name = nxt_string("webapp"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("options"),
|
|
.type = NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_array_iterator,
|
|
.u.array = nxt_conf_vldt_java_option,
|
|
}, {
|
|
.name = nxt_string("unit_jars"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("threads"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_threads,
|
|
}, {
|
|
.name = nxt_string("thread_stack_size"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
.validator = nxt_conf_vldt_thread_stack_size,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_members[] = {
|
|
{
|
|
.name = nxt_string("module"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("request_handler"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
},{
|
|
.name = nxt_string("malloc_handler"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("free_handler"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
.flags = NXT_CONF_VLDT_REQUIRED,
|
|
}, {
|
|
.name = nxt_string("module_init_handler"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("module_end_handler"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("request_init_handler"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("request_end_handler"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("response_end_handler"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("access"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_wasm_access_members,
|
|
},
|
|
|
|
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_access_members[] = {
|
|
{
|
|
.name = nxt_string("filesystem"),
|
|
.type = NXT_CONF_VLDT_ARRAY,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = {
|
|
{
|
|
.name = nxt_string("type"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("limits"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_app_limits_members,
|
|
}, {
|
|
.name = nxt_string("processes"),
|
|
.type = NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_processes,
|
|
.u.members = nxt_conf_vldt_app_processes_members,
|
|
}, {
|
|
.name = nxt_string("user"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("group"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("working_directory"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("environment"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object_iterator,
|
|
.u.object = nxt_conf_vldt_environment,
|
|
}, {
|
|
.name = nxt_string("isolation"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_isolation,
|
|
.u.members = nxt_conf_vldt_app_isolation_members,
|
|
}, {
|
|
.name = nxt_string("stdout"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("stderr"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = {
|
|
{
|
|
.name = nxt_string("timeout"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("requests"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("shm"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = {
|
|
{
|
|
.name = nxt_string("spare"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("max"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("idle_timeout"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = {
|
|
{
|
|
.name = nxt_string("namespaces"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_clone_namespaces,
|
|
.u.members = nxt_conf_vldt_app_namespaces_members,
|
|
},
|
|
|
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
|
{
|
|
.name = nxt_string("uidmap"),
|
|
.type = NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_array_iterator,
|
|
.u.array = nxt_conf_vldt_clone_uidmap,
|
|
}, {
|
|
.name = nxt_string("gidmap"),
|
|
.type = NXT_CONF_VLDT_ARRAY,
|
|
.validator = nxt_conf_vldt_array_iterator,
|
|
.u.array = nxt_conf_vldt_clone_gidmap,
|
|
},
|
|
#endif
|
|
|
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
|
{
|
|
.name = nxt_string("rootfs"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("automount"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object,
|
|
.u.members = nxt_conf_vldt_app_automount_members,
|
|
},
|
|
#endif
|
|
|
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
|
{
|
|
.name = nxt_string("new_privs"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
#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
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[] = {
|
|
|
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
|
{
|
|
.name = nxt_string("credential"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
#endif
|
|
|
|
#if (NXT_HAVE_CLONE_NEWPID)
|
|
{
|
|
.name = nxt_string("pid"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
#endif
|
|
|
|
#if (NXT_HAVE_CLONE_NEWNET)
|
|
{
|
|
.name = nxt_string("network"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
#endif
|
|
|
|
#if (NXT_HAVE_CLONE_NEWNS)
|
|
{
|
|
.name = nxt_string("mount"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
#endif
|
|
|
|
#if (NXT_HAVE_CLONE_NEWUTS)
|
|
{
|
|
.name = nxt_string("uname"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
#endif
|
|
|
|
#if (NXT_HAVE_CLONE_NEWCGROUP)
|
|
{
|
|
.name = nxt_string("cgroup"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
#endif
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[] = {
|
|
{
|
|
.name = nxt_string("language_deps"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
}, {
|
|
.name = nxt_string("tmpfs"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
}, {
|
|
.name = nxt_string("procfs"),
|
|
.type = NXT_CONF_VLDT_BOOLEAN,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
#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[] = {
|
|
{
|
|
.name = nxt_string("container"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("host"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
}, {
|
|
.name = nxt_string("size"),
|
|
.type = NXT_CONF_VLDT_INTEGER,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_members[] = {
|
|
{
|
|
.name = nxt_string("servers"),
|
|
.type = NXT_CONF_VLDT_OBJECT,
|
|
.validator = nxt_conf_vldt_object_iterator,
|
|
.u.object = nxt_conf_vldt_server,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = {
|
|
{
|
|
.name = nxt_string("weight"),
|
|
.type = NXT_CONF_VLDT_NUMBER,
|
|
.validator = nxt_conf_vldt_server_weight,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[] = {
|
|
{
|
|
.name = nxt_string("path"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
}, {
|
|
.name = nxt_string("format"),
|
|
.type = NXT_CONF_VLDT_STRING,
|
|
},
|
|
|
|
NXT_CONF_VLDT_END
|
|
};
|
|
|
|
|
|
nxt_int_t
|
|
nxt_conf_validate(nxt_conf_validation_t *vldt)
|
|
{
|
|
nxt_int_t ret;
|
|
u_char error[NXT_MAX_ERROR_STR];
|
|
|
|
vldt->tstr_state = nxt_tstr_state_new(vldt->pool, 1);
|
|
if (nxt_slow_path(vldt->tstr_state == NULL)) {
|
|
return NXT_ERROR;
|
|
}
|
|
|
|
ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
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) {
|
|
ret = nxt_conf_vldt_error(vldt, "%s", error);
|
|
return ret;
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
#define NXT_CONF_VLDT_ANY_TYPE_STR \
|
|
"either a null, a boolean, an integer, " \
|
|
"a number, a string, an array, or an object"
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value, nxt_conf_vldt_type_t type)
|
|
{
|
|
u_char *p;
|
|
nxt_str_t expected;
|
|
nxt_bool_t comma;
|
|
nxt_uint_t value_type, n, t;
|
|
u_char buf[nxt_length(NXT_CONF_VLDT_ANY_TYPE_STR)];
|
|
|
|
static nxt_str_t type_name[] = {
|
|
nxt_string("a null"),
|
|
nxt_string("a boolean"),
|
|
nxt_string("an integer number"),
|
|
nxt_string("a fractional number"),
|
|
nxt_string("a string"),
|
|
nxt_string("an array"),
|
|
nxt_string("an object"),
|
|
};
|
|
|
|
value_type = nxt_conf_type(value);
|
|
|
|
if ((1 << value_type) & type) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
p = buf;
|
|
|
|
n = nxt_popcount(type);
|
|
|
|
if (n > 1) {
|
|
p = nxt_cpymem(p, "either ", 7);
|
|
}
|
|
|
|
comma = (n > 2);
|
|
|
|
for ( ;; ) {
|
|
t = __builtin_ffs(type) - 1;
|
|
|
|
p = nxt_cpymem(p, type_name[t].start, type_name[t].length);
|
|
|
|
n--;
|
|
|
|
if (n == 0) {
|
|
break;
|
|
}
|
|
|
|
if (comma) {
|
|
*p++ = ',';
|
|
}
|
|
|
|
if (n == 1) {
|
|
p = nxt_cpymem(p, " or", 3);
|
|
}
|
|
|
|
*p++ = ' ';
|
|
|
|
type = type & ~(1 << t);
|
|
}
|
|
|
|
expected.length = p - buf;
|
|
expected.start = buf;
|
|
|
|
if (name == NULL) {
|
|
return nxt_conf_vldt_error(vldt,
|
|
"The configuration must be %V, but not %V.",
|
|
&expected, &type_name[value_type]);
|
|
}
|
|
|
|
return nxt_conf_vldt_error(vldt,
|
|
"The \"%V\" value must be %V, but not %V.",
|
|
name, &expected, &type_name[value_type]);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...)
|
|
{
|
|
u_char *p, *end;
|
|
size_t size;
|
|
va_list args;
|
|
u_char error[NXT_MAX_ERROR_STR];
|
|
|
|
va_start(args, fmt);
|
|
end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args);
|
|
va_end(args);
|
|
|
|
size = end - error;
|
|
|
|
p = nxt_mp_nget(vldt->pool, size);
|
|
if (p == NULL) {
|
|
return NXT_ERROR;
|
|
}
|
|
|
|
nxt_memcpy(p, error, size);
|
|
|
|
vldt->error.length = size;
|
|
vldt->error.start = p;
|
|
|
|
return NXT_DECLINED;
|
|
}
|
|
|
|
|
|
nxt_inline nxt_int_t
|
|
nxt_conf_vldt_unsupported(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
return nxt_conf_vldt_error(vldt, "Unit is built without the \"%s\" "
|
|
"option support.", data);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_str_t *value)
|
|
{
|
|
u_char error[NXT_MAX_ERROR_STR];
|
|
|
|
if (nxt_tstr_test(vldt->tstr_state, value, error) != NXT_OK) {
|
|
return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.",
|
|
error, name);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
nxt_mp_t *pool;
|
|
nxt_str_t *type;
|
|
nxt_lvlhsh_t hash;
|
|
} nxt_conf_vldt_mtypes_ctx_t;
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_conf_vldt_mtypes_ctx_t ctx;
|
|
|
|
ctx.pool = nxt_mp_create(1024, 128, 256, 32);
|
|
if (nxt_slow_path(ctx.pool == NULL)) {
|
|
return NXT_ERROR;
|
|
}
|
|
|
|
nxt_lvlhsh_init(&ctx.hash);
|
|
|
|
vldt->ctx = &ctx;
|
|
|
|
ret = nxt_conf_vldt_object_iterator(vldt, value,
|
|
&nxt_conf_vldt_mtypes_type);
|
|
|
|
vldt->ctx = NULL;
|
|
|
|
nxt_mp_destroy(ctx.pool);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_conf_vldt_mtypes_ctx_t *ctx;
|
|
|
|
ret = nxt_conf_vldt_type(vldt, name, value,
|
|
NXT_CONF_VLDT_STRING|NXT_CONF_VLDT_ARRAY);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
ctx = vldt->ctx;
|
|
|
|
ctx->type = nxt_mp_get(ctx->pool, sizeof(nxt_str_t));
|
|
if (nxt_slow_path(ctx->type == NULL)) {
|
|
return NXT_ERROR;
|
|
}
|
|
|
|
*ctx->type = *name;
|
|
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_mtypes_extension);
|
|
}
|
|
|
|
/* NXT_CONF_STRING */
|
|
|
|
return nxt_conf_vldt_mtypes_extension(vldt, value);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t exten, *dup_type;
|
|
nxt_conf_vldt_mtypes_ctx_t *ctx;
|
|
|
|
ctx = vldt->ctx;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" MIME type array must "
|
|
"contain only strings.", ctx->type);
|
|
}
|
|
|
|
nxt_conf_get_string(value, &exten);
|
|
|
|
if (exten.length == 0) {
|
|
return nxt_conf_vldt_error(vldt, "An empty file extension for "
|
|
"the \"%V\" MIME type.", ctx->type);
|
|
}
|
|
|
|
dup_type = nxt_http_static_mtype_get(&ctx->hash, &exten);
|
|
|
|
if (dup_type->length != 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" file extension has been "
|
|
"declared for \"%V\" and \"%V\" "
|
|
"MIME types at the same time.",
|
|
&exten, dup_type, ctx->type);
|
|
}
|
|
|
|
return nxt_http_static_mtypes_hash_add(ctx->pool, &ctx->hash, &exten,
|
|
ctx->type);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_str_t str;
|
|
nxt_sockaddr_t *sa;
|
|
|
|
if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) {
|
|
return NXT_ERROR;
|
|
}
|
|
|
|
sa = nxt_sockaddr_parse(vldt->pool, &str);
|
|
if (nxt_slow_path(sa == NULL)) {
|
|
return nxt_conf_vldt_error(vldt,
|
|
"The listener address \"%V\" is invalid.",
|
|
name);
|
|
}
|
|
|
|
ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_action(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_uint_t i;
|
|
nxt_conf_value_t *action;
|
|
nxt_conf_vldt_object_t *members;
|
|
|
|
static struct {
|
|
nxt_str_t name;
|
|
nxt_conf_vldt_object_t *members;
|
|
|
|
} actions[] = {
|
|
{ nxt_string("pass"), nxt_conf_vldt_pass_action_members },
|
|
{ nxt_string("return"), nxt_conf_vldt_return_action_members },
|
|
{ nxt_string("share"), nxt_conf_vldt_share_action_members },
|
|
{ nxt_string("proxy"), nxt_conf_vldt_proxy_action_members },
|
|
};
|
|
|
|
members = NULL;
|
|
|
|
for (i = 0; i < nxt_nitems(actions); i++) {
|
|
action = nxt_conf_get_object_member(value, &actions[i].name, NULL);
|
|
|
|
if (action == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if (members != NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"action\" object must have "
|
|
"just one of \"pass\", \"return\", "
|
|
"\"share\", or \"proxy\" options set.");
|
|
}
|
|
|
|
members = actions[i].members;
|
|
}
|
|
|
|
if (members == NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"action\" object must have "
|
|
"either \"pass\", \"return\", \"share\", "
|
|
"or \"proxy\" option set.");
|
|
}
|
|
|
|
return nxt_conf_vldt_object(vldt, value, members);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_str_t pass;
|
|
nxt_int_t ret;
|
|
nxt_str_t segments[3];
|
|
|
|
static nxt_str_t targets_str = nxt_string("targets");
|
|
|
|
nxt_conf_get_string(value, &pass);
|
|
|
|
ret = nxt_http_pass_segments(vldt->pool, &pass, segments, 3);
|
|
|
|
if (ret != NXT_OK) {
|
|
if (ret == NXT_DECLINED) {
|
|
return nxt_conf_vldt_error(vldt, "Request \"pass\" value \"%V\" "
|
|
"is invalid.", &pass);
|
|
}
|
|
|
|
return NXT_ERROR;
|
|
}
|
|
|
|
if (nxt_str_eq(&segments[0], "applications", 12)) {
|
|
|
|
if (segments[1].length == 0) {
|
|
goto error;
|
|
}
|
|
|
|
value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
|
|
|
|
if (value == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
value = nxt_conf_get_object_member(value, &segments[1], NULL);
|
|
|
|
if (value == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
if (segments[2].length > 0) {
|
|
value = nxt_conf_get_object_member(value, &targets_str, NULL);
|
|
|
|
if (value == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
value = nxt_conf_get_object_member(value, &segments[2], NULL);
|
|
|
|
if (value == NULL) {
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
if (nxt_str_eq(&segments[0], "upstreams", 9)) {
|
|
|
|
if (segments[1].length == 0 || segments[2].length != 0) {
|
|
goto error;
|
|
}
|
|
|
|
value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
|
|
|
|
if (value == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
value = nxt_conf_get_object_member(value, &segments[1], NULL);
|
|
|
|
if (value == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
if (nxt_str_eq(&segments[0], "routes", 6)) {
|
|
|
|
if (segments[2].length != 0) {
|
|
goto error;
|
|
}
|
|
|
|
value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
|
|
|
|
if (value == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
if (segments[1].length == 0) {
|
|
if (nxt_conf_type(value) != NXT_CONF_ARRAY) {
|
|
goto error;
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
|
|
goto error;
|
|
}
|
|
|
|
value = nxt_conf_get_object_member(value, &segments[1], NULL);
|
|
|
|
if (value == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
error:
|
|
|
|
return nxt_conf_vldt_error(vldt, "Request \"pass\" points to invalid "
|
|
"location \"%V\".", &pass);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_return(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
int64_t status;
|
|
|
|
status = nxt_conf_get_number(value);
|
|
|
|
if (status < NXT_HTTP_INVALID || status > NXT_HTTP_STATUS_MAX) {
|
|
return nxt_conf_vldt_error(vldt, "The \"return\" value is out of "
|
|
"allowed HTTP status code range 0-999.");
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_share(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
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 "
|
|
"must contain at least one element.");
|
|
}
|
|
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_share_element);
|
|
}
|
|
|
|
/* NXT_CONF_STRING */
|
|
|
|
return nxt_conf_vldt_share_element(vldt, value);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t str;
|
|
|
|
static nxt_str_t share = nxt_string("share");
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"share\" array must "
|
|
"contain only string values.");
|
|
}
|
|
|
|
nxt_conf_get_string(value, &str);
|
|
|
|
if (nxt_is_tstr(&str)) {
|
|
return nxt_conf_vldt_var(vldt, &share, &str);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_str_t name;
|
|
nxt_sockaddr_t *sa;
|
|
|
|
nxt_conf_get_string(value, &name);
|
|
|
|
if (nxt_str_start(&name, "http://", 7)) {
|
|
name.length -= 7;
|
|
name.start += 7;
|
|
|
|
sa = nxt_sockaddr_parse(vldt->pool, &name);
|
|
if (sa != NULL) {
|
|
return NXT_OK;
|
|
}
|
|
}
|
|
|
|
return nxt_conf_vldt_error(vldt, "The \"proxy\" address is invalid \"%V\"",
|
|
&name);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_python(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_conf_value_t *targets;
|
|
|
|
static nxt_str_t targets_str = nxt_string("targets");
|
|
|
|
targets = nxt_conf_get_object_member(value, &targets_str, NULL);
|
|
|
|
if (targets != NULL) {
|
|
return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_python_members);
|
|
}
|
|
|
|
return nxt_conf_vldt_object(vldt, value,
|
|
nxt_conf_vldt_python_notargets_members);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_python_path(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_python_path_element);
|
|
}
|
|
|
|
/* NXT_CONF_STRING */
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_python_path_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"path\" array must contain "
|
|
"only string values.");
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
nxt_str_t proto;
|
|
|
|
static const nxt_str_t wsgi = nxt_string("wsgi");
|
|
static const nxt_str_t asgi = nxt_string("asgi");
|
|
|
|
nxt_conf_get_string(value, &proto);
|
|
|
|
if (nxt_strstr_eq(&proto, &wsgi) || nxt_strstr_eq(&proto, &asgi)) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
return nxt_conf_vldt_error(vldt, "The \"protocol\" can either be "
|
|
"\"wsgi\" or \"asgi\".");
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
int64_t threads;
|
|
|
|
threads = nxt_conf_get_number(value);
|
|
|
|
if (threads < 1) {
|
|
return nxt_conf_vldt_error(vldt, "The \"threads\" number must be "
|
|
"equal to or greater than 1.");
|
|
}
|
|
|
|
if (threads > NXT_INT32_T_MAX) {
|
|
return nxt_conf_vldt_error(vldt, "The \"threads\" number must "
|
|
"not exceed %d.", NXT_INT32_T_MAX);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
int64_t size, min_size;
|
|
|
|
size = nxt_conf_get_number(value);
|
|
min_size = sysconf(_SC_THREAD_STACK_MIN);
|
|
|
|
if (size < min_size) {
|
|
return nxt_conf_vldt_error(vldt, "The \"thread_stack_size\" number "
|
|
"must be equal to or greater than %d.",
|
|
min_size);
|
|
}
|
|
|
|
if ((size % nxt_pagesize) != 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"thread_stack_size\" number "
|
|
"must be a multiple of the system page size (%d).",
|
|
nxt_pagesize);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_route);
|
|
}
|
|
|
|
/* NXT_CONF_OBJECT */
|
|
|
|
return nxt_conf_vldt_object_iterator(vldt, value,
|
|
&nxt_conf_vldt_routes_member);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
|
|
ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_ARRAY);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_route);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_route(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
|
{
|
|
if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
|
|
return nxt_conf_vldt_error(vldt, "The \"routes\" array must contain "
|
|
"only object values.");
|
|
}
|
|
|
|
return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_route_members);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
nxt_int_t ret;
|
|
|
|
vldt->ctx = data;
|
|
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
ret = nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_match_pattern);
|
|
|
|
} else {
|
|
/* NXT_CONF_STRING */
|
|
ret = nxt_conf_vldt_match_pattern(vldt, value);
|
|
}
|
|
|
|
vldt->ctx = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t pattern;
|
|
nxt_uint_t i, first, last;
|
|
#if (NXT_HAVE_REGEX)
|
|
nxt_regex_t *re;
|
|
nxt_regex_err_t err;
|
|
#endif
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" "
|
|
"must be strings.", vldt->ctx);
|
|
}
|
|
|
|
nxt_conf_get_string(value, &pattern);
|
|
|
|
if (pattern.length == 0) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
first = (pattern.start[0] == '!');
|
|
|
|
if (first < pattern.length && pattern.start[first] == '~') {
|
|
#if (NXT_HAVE_REGEX)
|
|
pattern.start += first + 1;
|
|
pattern.length -= first + 1;
|
|
|
|
re = nxt_regex_compile(vldt->pool, &pattern, &err);
|
|
if (nxt_slow_path(re == NULL)) {
|
|
if (err.offset < pattern.length) {
|
|
return nxt_conf_vldt_error(vldt, "Invalid regular expression: "
|
|
"%s at offset %d",
|
|
err.msg, err.offset);
|
|
}
|
|
|
|
return nxt_conf_vldt_error(vldt, "Invalid regular expression: %s",
|
|
err.msg);
|
|
}
|
|
|
|
return NXT_OK;
|
|
#else
|
|
return nxt_conf_vldt_error(vldt, "Unit is built without support of "
|
|
"regular expressions: \"--no-regex\" "
|
|
"./configure option was set.");
|
|
#endif
|
|
}
|
|
|
|
last = pattern.length - 1;
|
|
|
|
for (i = first; i < last; i++) {
|
|
if (pattern.start[i] == '*' && pattern.start[i + 1] == '*') {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern must "
|
|
"not contain double \"*\" markers.");
|
|
}
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets(
|
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data)
|
|
{
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_match_encoded_patterns_set);
|
|
}
|
|
|
|
/* NXT_CONF_OBJECT */
|
|
|
|
return nxt_conf_vldt_match_encoded_patterns_set(vldt, value);
|
|
}
|
|
|
|
|
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set(
|
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
|
{
|
|
if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
|
|
"\"arguments\" must be an object.");
|
|
}
|
|
|
|
return nxt_conf_vldt_object_iterator(vldt, value,
|
|
&nxt_conf_vldt_match_encoded_patterns_set_member);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_encoded_patterns_set_member(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value)
|
|
{
|
|
u_char *p, *end;
|
|
|
|
if (nxt_slow_path(name->length == 0)) {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must "
|
|
"not contain empty member names.");
|
|
}
|
|
|
|
p = nxt_mp_nget(vldt->pool, name->length);
|
|
if (nxt_slow_path(p == NULL)) {
|
|
return NXT_ERROR;
|
|
}
|
|
|
|
end = nxt_decode_uri(p, name->start, name->length);
|
|
if (nxt_slow_path(end == NULL)) {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
|
|
"\"arguments\" is encoded but is invalid.");
|
|
}
|
|
|
|
return nxt_conf_vldt_match_encoded_patterns(vldt, value,
|
|
(void *) "arguments");
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_encoded_patterns(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
nxt_int_t ret;
|
|
|
|
vldt->ctx = data;
|
|
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
ret = nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_match_encoded_pattern);
|
|
|
|
} else {
|
|
/* NXT_CONF_STRING */
|
|
ret = nxt_conf_vldt_match_encoded_pattern(vldt, value);
|
|
}
|
|
|
|
vldt->ctx = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_encoded_pattern(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
u_char *p, *end;
|
|
nxt_int_t ret;
|
|
nxt_str_t pattern;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" "
|
|
"must be a string.", vldt->ctx);
|
|
}
|
|
|
|
ret = nxt_conf_vldt_match_pattern(vldt, value);
|
|
if (nxt_slow_path(ret != NXT_OK)) {
|
|
return ret;
|
|
}
|
|
|
|
nxt_conf_get_string(value, &pattern);
|
|
|
|
p = nxt_mp_nget(vldt->pool, pattern.length);
|
|
if (nxt_slow_path(p == NULL)) {
|
|
return NXT_ERROR;
|
|
}
|
|
|
|
end = nxt_decode_uri(p, pattern.start, pattern.length);
|
|
if (nxt_slow_path(end == NULL)) {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" "
|
|
"is encoded but is invalid.", vldt->ctx);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_match_addr);
|
|
}
|
|
|
|
return nxt_conf_vldt_match_addr(vldt, value);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_http_route_addr_pattern_t pattern;
|
|
|
|
switch (nxt_http_route_addr_pattern_parse(vldt->pool, &pattern, value)) {
|
|
|
|
case NXT_OK:
|
|
return NXT_OK;
|
|
|
|
case NXT_ADDR_PATTERN_PORT_ERROR:
|
|
return nxt_conf_vldt_error(vldt, "The \"address\" port an invalid "
|
|
"port.");
|
|
|
|
case NXT_ADDR_PATTERN_CV_TYPE_ERROR:
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
|
|
"\"address\" must be a string.");
|
|
|
|
case NXT_ADDR_PATTERN_LENGTH_ERROR:
|
|
return nxt_conf_vldt_error(vldt, "The \"address\" is too short.");
|
|
|
|
case NXT_ADDR_PATTERN_FORMAT_ERROR:
|
|
return nxt_conf_vldt_error(vldt, "The \"address\" format is invalid.");
|
|
|
|
case NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR:
|
|
return nxt_conf_vldt_error(vldt, "The \"address\" range is "
|
|
"overlapping.");
|
|
|
|
case NXT_ADDR_PATTERN_CIDR_ERROR:
|
|
return nxt_conf_vldt_error(vldt, "The \"address\" has an invalid CIDR "
|
|
"prefix.");
|
|
|
|
case NXT_ADDR_PATTERN_NO_IPv6_ERROR:
|
|
return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
|
|
"IPv6 with your configuration.");
|
|
|
|
case NXT_ADDR_PATTERN_NO_UNIX_ERROR:
|
|
return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
|
|
"UNIX domain sockets with your "
|
|
"configuration.");
|
|
|
|
default:
|
|
return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown "
|
|
"format.");
|
|
}
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
nxt_str_t scheme;
|
|
|
|
static const nxt_str_t http = nxt_string("http");
|
|
static const nxt_str_t https = nxt_string("https");
|
|
|
|
nxt_conf_get_string(value, &scheme);
|
|
|
|
if (nxt_strcasestr_eq(&scheme, &http)
|
|
|| nxt_strcasestr_eq(&scheme, &https))
|
|
{
|
|
return NXT_OK;
|
|
}
|
|
|
|
return nxt_conf_vldt_error(vldt, "The \"scheme\" can either be "
|
|
"\"http\" or \"https\".");
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
nxt_int_t ret;
|
|
|
|
vldt->ctx = data;
|
|
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
ret = nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_match_patterns_set);
|
|
|
|
} else {
|
|
/* NXT_CONF_OBJECT */
|
|
ret = nxt_conf_vldt_match_patterns_set(vldt, value);
|
|
}
|
|
|
|
vldt->ctx = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" patterns for "
|
|
"\"%s\" must be objects.", vldt->ctx);
|
|
}
|
|
|
|
return nxt_conf_vldt_object_iterator(vldt, value,
|
|
&nxt_conf_vldt_match_patterns_set_member);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_match_patterns_set_member(nxt_conf_validation_t *vldt,
|
|
nxt_str_t *name, nxt_conf_value_t *value)
|
|
{
|
|
if (name->length == 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must "
|
|
"not contain empty member names.");
|
|
}
|
|
|
|
return nxt_conf_vldt_match_patterns(vldt, value, vldt->ctx);
|
|
}
|
|
|
|
|
|
#if (NXT_TLS)
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
if (nxt_conf_array_elements_count(value) == 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"certificate\" array "
|
|
"must contain at least one element.");
|
|
}
|
|
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_certificate_element);
|
|
}
|
|
|
|
/* NXT_CONF_STRING */
|
|
|
|
return nxt_conf_vldt_certificate_element(vldt, value);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t name;
|
|
nxt_conf_value_t *cert;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"certificate\" array must "
|
|
"contain only string values.");
|
|
}
|
|
|
|
nxt_conf_get_string(value, &name);
|
|
|
|
cert = nxt_cert_info_get(&name);
|
|
|
|
if (cert == NULL) {
|
|
return nxt_conf_vldt_error(vldt, "Certificate \"%V\" is not found.",
|
|
&name);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
#if (NXT_HAVE_OPENSSL_CONF_CMD)
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
uint32_t index;
|
|
nxt_int_t ret;
|
|
nxt_str_t name;
|
|
nxt_conf_value_t *member;
|
|
|
|
index = 0;
|
|
|
|
for ( ;; ) {
|
|
member = nxt_conf_next_object_member(value, &name, &index);
|
|
|
|
if (member == NULL) {
|
|
break;
|
|
}
|
|
|
|
ret = nxt_conf_vldt_type(vldt, &name, member, NXT_CONF_VLDT_STRING);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_response_header(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_uint_t type;
|
|
|
|
static nxt_str_t content_length = nxt_string("Content-Length");
|
|
|
|
if (name->length == 0) {
|
|
return nxt_conf_vldt_error(vldt, "The response header name "
|
|
"must not be empty.");
|
|
}
|
|
|
|
if (nxt_strstr_eq(name, &content_length)) {
|
|
return nxt_conf_vldt_error(vldt, "The \"Content-Length\" response "
|
|
"header value is not supported");
|
|
}
|
|
|
|
type = nxt_conf_type(value);
|
|
|
|
if (type == NXT_CONF_STRING || type == NXT_CONF_NULL) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" response header value "
|
|
"must either be a string or a null", name);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_str_t name;
|
|
nxt_conf_value_t *apps, *app;
|
|
|
|
static nxt_str_t apps_str = nxt_string("applications");
|
|
|
|
nxt_conf_get_string(value, &name);
|
|
|
|
apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL);
|
|
|
|
if (nxt_slow_path(apps == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
app = nxt_conf_get_object_member(apps, &name, NULL);
|
|
|
|
if (nxt_slow_path(app == NULL)) {
|
|
goto error;
|
|
}
|
|
|
|
return NXT_OK;
|
|
|
|
error:
|
|
|
|
return nxt_conf_vldt_error(vldt, "Listening socket is assigned for "
|
|
"a non existing application \"%V\".",
|
|
&name);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_conf_value_t *client_ip, *protocol;
|
|
|
|
static nxt_str_t client_ip_str = nxt_string("client_ip");
|
|
static nxt_str_t protocol_str = nxt_string("protocol");
|
|
|
|
client_ip = nxt_conf_get_object_member(value, &client_ip_str, NULL);
|
|
protocol = nxt_conf_get_object_member(value, &protocol_str, NULL);
|
|
|
|
if (client_ip == NULL && protocol == NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"forwarded\" object must have "
|
|
"either \"client_ip\" or \"protocol\" "
|
|
"option set.");
|
|
}
|
|
|
|
return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_forwarded_members);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_str_t type;
|
|
nxt_thread_t *thread;
|
|
nxt_conf_value_t *type_value;
|
|
nxt_app_lang_module_t *lang;
|
|
|
|
static nxt_str_t type_str = nxt_string("type");
|
|
|
|
static struct {
|
|
nxt_conf_vldt_handler_t validator;
|
|
nxt_conf_vldt_object_t *members;
|
|
|
|
} types[] = {
|
|
{ nxt_conf_vldt_object, nxt_conf_vldt_external_members },
|
|
{ nxt_conf_vldt_python, NULL },
|
|
{ nxt_conf_vldt_php, NULL },
|
|
{ nxt_conf_vldt_object, nxt_conf_vldt_perl_members },
|
|
{ nxt_conf_vldt_object, nxt_conf_vldt_ruby_members },
|
|
{ nxt_conf_vldt_object, nxt_conf_vldt_java_members },
|
|
{ nxt_conf_vldt_object, nxt_conf_vldt_wasm_members },
|
|
};
|
|
|
|
ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
type_value = nxt_conf_get_object_member(value, &type_str, NULL);
|
|
|
|
if (type_value == NULL) {
|
|
return nxt_conf_vldt_error(vldt,
|
|
"Application must have the \"type\" property set.");
|
|
}
|
|
|
|
ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_VLDT_STRING);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
nxt_conf_get_string(type_value, &type);
|
|
|
|
thread = nxt_thread();
|
|
|
|
lang = nxt_app_lang_module(thread->runtime, &type);
|
|
if (lang == NULL) {
|
|
return nxt_conf_vldt_error(vldt,
|
|
"The module to run \"%V\" is not found "
|
|
"among the available application modules.",
|
|
&type);
|
|
}
|
|
|
|
return types[lang->type].validator(vldt, value, types[lang->type].members);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
uint32_t index;
|
|
nxt_int_t ret;
|
|
nxt_str_t name, var;
|
|
nxt_conf_value_t *member;
|
|
nxt_conf_vldt_object_t *vals;
|
|
|
|
vals = data;
|
|
|
|
for ( ;; ) {
|
|
if (vals->name.length == 0) {
|
|
|
|
if (vals->u.members != NULL) {
|
|
vals = vals->u.members;
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (vals->flags & NXT_CONF_VLDT_REQUIRED) {
|
|
member = nxt_conf_get_object_member(value, &vals->name, NULL);
|
|
|
|
if (member == NULL) {
|
|
return nxt_conf_vldt_error(vldt, "Required parameter \"%V\" "
|
|
"is missing.", &vals->name);
|
|
}
|
|
}
|
|
|
|
vals++;
|
|
}
|
|
|
|
index = 0;
|
|
|
|
for ( ;; ) {
|
|
member = nxt_conf_next_object_member(value, &name, &index);
|
|
|
|
if (member == NULL) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
vals = data;
|
|
|
|
for ( ;; ) {
|
|
if (vals->name.length == 0) {
|
|
|
|
if (vals->u.members != NULL) {
|
|
vals = vals->u.members;
|
|
continue;
|
|
}
|
|
|
|
return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".",
|
|
&name);
|
|
}
|
|
|
|
if (!nxt_strstr_eq(&vals->name, &name)) {
|
|
vals++;
|
|
continue;
|
|
}
|
|
|
|
if (vals->flags & NXT_CONF_VLDT_TSTR
|
|
&& nxt_conf_type(member) == NXT_CONF_STRING)
|
|
{
|
|
nxt_conf_get_string(member, &var);
|
|
|
|
if (nxt_is_tstr(&var)) {
|
|
ret = nxt_conf_vldt_var(vldt, &name, &var);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
ret = nxt_conf_vldt_type(vldt, &name, member, vals->type);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
if (vals->validator != NULL) {
|
|
ret = vals->validator(vldt, member, vals->u.members);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
typedef struct {
|
|
int64_t spare;
|
|
int64_t max;
|
|
int64_t idle_timeout;
|
|
} nxt_conf_vldt_processes_conf_t;
|
|
|
|
|
|
static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = {
|
|
{
|
|
nxt_string("spare"),
|
|
NXT_CONF_MAP_INT64,
|
|
offsetof(nxt_conf_vldt_processes_conf_t, spare),
|
|
},
|
|
|
|
{
|
|
nxt_string("max"),
|
|
NXT_CONF_MAP_INT64,
|
|
offsetof(nxt_conf_vldt_processes_conf_t, max),
|
|
},
|
|
|
|
{
|
|
nxt_string("idle_timeout"),
|
|
NXT_CONF_MAP_INT64,
|
|
offsetof(nxt_conf_vldt_processes_conf_t, idle_timeout),
|
|
},
|
|
};
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
int64_t int_value;
|
|
nxt_int_t ret;
|
|
nxt_conf_vldt_processes_conf_t proc;
|
|
|
|
if (nxt_conf_type(value) == NXT_CONF_NUMBER) {
|
|
int_value = nxt_conf_get_number(value);
|
|
|
|
if (int_value < 1) {
|
|
return nxt_conf_vldt_error(vldt, "The \"processes\" number must be "
|
|
"equal to or greater than 1.");
|
|
}
|
|
|
|
if (int_value > NXT_INT32_T_MAX) {
|
|
return nxt_conf_vldt_error(vldt, "The \"processes\" number must "
|
|
"not exceed %d.", NXT_INT32_T_MAX);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
ret = nxt_conf_vldt_object(vldt, value, data);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
proc.spare = 0;
|
|
proc.max = 1;
|
|
proc.idle_timeout = 15;
|
|
|
|
ret = nxt_conf_map_object(vldt->pool, value,
|
|
nxt_conf_vldt_processes_conf_map,
|
|
nxt_nitems(nxt_conf_vldt_processes_conf_map),
|
|
&proc);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
if (proc.spare < 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be "
|
|
"negative.");
|
|
}
|
|
|
|
if (proc.spare > NXT_INT32_T_MAX) {
|
|
return nxt_conf_vldt_error(vldt, "The \"spare\" number must not "
|
|
"exceed %d.", NXT_INT32_T_MAX);
|
|
}
|
|
|
|
if (proc.max < 1) {
|
|
return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal "
|
|
"to or greater than 1.");
|
|
}
|
|
|
|
if (proc.max > NXT_INT32_T_MAX) {
|
|
return nxt_conf_vldt_error(vldt, "The \"max\" number must not "
|
|
"exceed %d.", NXT_INT32_T_MAX);
|
|
}
|
|
|
|
if (proc.max < proc.spare) {
|
|
return nxt_conf_vldt_error(vldt, "The \"spare\" number must be "
|
|
"less than or equal to \"max\".");
|
|
}
|
|
|
|
if (proc.idle_timeout < 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
|
|
"be negative.");
|
|
}
|
|
|
|
if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) {
|
|
return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
|
|
"exceed %d.", NXT_INT32_T_MAX / 1000);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
uint32_t index;
|
|
nxt_int_t ret;
|
|
nxt_str_t name;
|
|
nxt_conf_value_t *member;
|
|
nxt_conf_vldt_member_t validator;
|
|
|
|
validator = (nxt_conf_vldt_member_t) data;
|
|
index = 0;
|
|
|
|
for ( ;; ) {
|
|
member = nxt_conf_next_object_member(value, &name, &index);
|
|
|
|
if (member == NULL) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
ret = validator(vldt, &name, member);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
uint32_t index;
|
|
nxt_int_t ret;
|
|
nxt_conf_value_t *element;
|
|
nxt_conf_vldt_element_t validator;
|
|
|
|
validator = (nxt_conf_vldt_element_t) data;
|
|
|
|
for (index = 0; /* void */ ; index++) {
|
|
element = nxt_conf_get_array_element(value, index);
|
|
|
|
if (element == NULL) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
ret = validator(vldt, element);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t str;
|
|
|
|
if (name->length == 0) {
|
|
return nxt_conf_vldt_error(vldt,
|
|
"The environment name must not be empty.");
|
|
}
|
|
|
|
if (memchr(name->start, '\0', name->length) != NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The environment name must not "
|
|
"contain null character.");
|
|
}
|
|
|
|
if (memchr(name->start, '=', name->length) != NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The environment name must not "
|
|
"contain '=' character.");
|
|
}
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must be "
|
|
"a string.", name);
|
|
}
|
|
|
|
nxt_conf_get_string(value, &str);
|
|
|
|
if (memchr(str.start, '\0', str.length) != NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must "
|
|
"not contain null character.", name);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_targets_exclusive(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
return nxt_conf_vldt_error(vldt, "The \"%s\" option is mutually exclusive "
|
|
"with the \"targets\" object.", data);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_targets(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_uint_t n;
|
|
|
|
n = nxt_conf_object_members_count(value);
|
|
|
|
if (n > 254) {
|
|
return nxt_conf_vldt_error(vldt, "The \"targets\" object must not "
|
|
"contain more than 254 members.");
|
|
}
|
|
|
|
vldt->ctx = data;
|
|
|
|
ret = nxt_conf_vldt_object_iterator(vldt, value, &nxt_conf_vldt_target);
|
|
|
|
vldt->ctx = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_target(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
if (name->length == 0) {
|
|
return nxt_conf_vldt_error(vldt,
|
|
"The target name must not be empty.");
|
|
}
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" target must be "
|
|
"an object.", name);
|
|
}
|
|
|
|
return nxt_conf_vldt_object(vldt, value, vldt->ctx);
|
|
}
|
|
|
|
|
|
#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)
|
|
{
|
|
return nxt_conf_vldt_object(vldt, value, data);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
return nxt_conf_vldt_object(vldt, value, data);
|
|
}
|
|
|
|
|
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
|
|
|
typedef struct {
|
|
nxt_int_t container;
|
|
nxt_int_t host;
|
|
nxt_int_t size;
|
|
} nxt_conf_vldt_clone_procmap_conf_t;
|
|
|
|
|
|
static nxt_conf_map_t nxt_conf_vldt_clone_procmap_conf_map[] = {
|
|
{
|
|
nxt_string("container"),
|
|
NXT_CONF_MAP_INT32,
|
|
offsetof(nxt_conf_vldt_clone_procmap_conf_t, container),
|
|
},
|
|
|
|
{
|
|
nxt_string("host"),
|
|
NXT_CONF_MAP_INT32,
|
|
offsetof(nxt_conf_vldt_clone_procmap_conf_t, host),
|
|
},
|
|
|
|
{
|
|
nxt_string("size"),
|
|
NXT_CONF_MAP_INT32,
|
|
offsetof(nxt_conf_vldt_clone_procmap_conf_t, size),
|
|
},
|
|
|
|
};
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_clone_procmap(nxt_conf_validation_t *vldt, const char *mapfile,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_conf_vldt_clone_procmap_conf_t procmap;
|
|
|
|
procmap.container = -1;
|
|
procmap.host = -1;
|
|
procmap.size = -1;
|
|
|
|
ret = nxt_conf_map_object(vldt->pool, value,
|
|
nxt_conf_vldt_clone_procmap_conf_map,
|
|
nxt_nitems(nxt_conf_vldt_clone_procmap_conf_map),
|
|
&procmap);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
if (procmap.container == -1) {
|
|
return nxt_conf_vldt_error(vldt, "The %s requires the "
|
|
"\"container\" field set.", mapfile);
|
|
}
|
|
|
|
if (procmap.host == -1) {
|
|
return nxt_conf_vldt_error(vldt, "The %s requires the "
|
|
"\"host\" field set.", mapfile);
|
|
}
|
|
|
|
if (procmap.size == -1) {
|
|
return nxt_conf_vldt_error(vldt, "The %s requires the "
|
|
"\"size\" field set.", mapfile);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
|
|
return nxt_conf_vldt_error(vldt, "The \"uidmap\" array "
|
|
"must contain only object values.");
|
|
}
|
|
|
|
ret = nxt_conf_vldt_object(vldt, value,
|
|
(void *) nxt_conf_vldt_app_procmap_members);
|
|
if (nxt_slow_path(ret != NXT_OK)) {
|
|
return ret;
|
|
}
|
|
|
|
return nxt_conf_vldt_clone_procmap(vldt, "uid_map", value);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
|
|
return nxt_conf_vldt_error(vldt, "The \"gidmap\" array "
|
|
"must contain only object values.");
|
|
}
|
|
|
|
ret = nxt_conf_vldt_object(vldt, value,
|
|
(void *) nxt_conf_vldt_app_procmap_members);
|
|
if (nxt_slow_path(ret != NXT_OK)) {
|
|
return ret;
|
|
}
|
|
|
|
return nxt_conf_vldt_clone_procmap(vldt, "gid_map", value);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t str;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"arguments\" array "
|
|
"must contain only string values.");
|
|
}
|
|
|
|
nxt_conf_get_string(value, &str);
|
|
|
|
if (memchr(str.start, '\0', str.length) != NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not "
|
|
"contain strings with null character.");
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_php(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_conf_value_t *targets;
|
|
|
|
static nxt_str_t targets_str = nxt_string("targets");
|
|
|
|
targets = nxt_conf_get_object_member(value, &targets_str, NULL);
|
|
|
|
if (targets != NULL) {
|
|
return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_php_members);
|
|
}
|
|
|
|
return nxt_conf_vldt_object(vldt, value,
|
|
nxt_conf_vldt_php_notargets_members);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
if (name->length == 0) {
|
|
return nxt_conf_vldt_error(vldt,
|
|
"The PHP option name must not be empty.");
|
|
}
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" PHP option must be "
|
|
"a string.", name);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t str;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"classpath\" array "
|
|
"must contain only string values.");
|
|
}
|
|
|
|
nxt_conf_get_string(value, &str);
|
|
|
|
if (memchr(str.start, '\0', str.length) != NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not "
|
|
"contain strings with null character.");
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t str;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"options\" array "
|
|
"must contain only string values.");
|
|
}
|
|
|
|
nxt_conf_get_string(value, &str);
|
|
|
|
if (memchr(str.start, '\0', str.length) != NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"options\" array must not "
|
|
"contain strings with null character.");
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_conf_value_t *conf;
|
|
|
|
static nxt_str_t servers = nxt_string("servers");
|
|
|
|
ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_upstream_members);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
conf = nxt_conf_get_object_member(value, &servers, NULL);
|
|
if (conf == NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" upstream must contain "
|
|
"\"servers\" object value.", name);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_sockaddr_t *sa;
|
|
|
|
ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
|
|
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
sa = nxt_sockaddr_parse(vldt->pool, name);
|
|
|
|
if (sa == NULL) {
|
|
return nxt_conf_vldt_error(vldt, "The \"%V\" is not valid "
|
|
"server address.", name);
|
|
}
|
|
|
|
return nxt_conf_vldt_object(vldt, value,
|
|
nxt_conf_vldt_upstream_server_members);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value, void *data)
|
|
{
|
|
double num_value;
|
|
|
|
num_value = nxt_conf_get_number(value);
|
|
|
|
if (num_value < 0) {
|
|
return nxt_conf_vldt_error(vldt, "The \"weight\" number must be "
|
|
"positive.");
|
|
}
|
|
|
|
if (num_value > 1000000) {
|
|
return nxt_conf_vldt_error(vldt, "The \"weight\" number must "
|
|
"not exceed 1,000,000");
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
#if (NXT_HAVE_NJS)
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
|
&nxt_conf_vldt_js_module_element);
|
|
}
|
|
|
|
/* NXT_CONF_STRING */
|
|
|
|
return nxt_conf_vldt_js_module_element(vldt, value);
|
|
}
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt,
|
|
nxt_conf_value_t *value)
|
|
{
|
|
nxt_str_t name;
|
|
nxt_conf_value_t *module;
|
|
|
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
|
return nxt_conf_vldt_error(vldt, "The \"js_module\" array must "
|
|
"contain only string values.");
|
|
}
|
|
|
|
nxt_conf_get_string(value, &name);
|
|
|
|
module = nxt_script_info_get(&name);
|
|
if (module == NULL) {
|
|
return nxt_conf_vldt_error(vldt, "JS module \"%V\" is not found.",
|
|
&name);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
typedef struct {
|
|
nxt_str_t path;
|
|
nxt_str_t format;
|
|
} nxt_conf_vldt_access_log_conf_t;
|
|
|
|
|
|
static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = {
|
|
{
|
|
nxt_string("path"),
|
|
NXT_CONF_MAP_STR,
|
|
offsetof(nxt_conf_vldt_access_log_conf_t, path),
|
|
},
|
|
|
|
{
|
|
nxt_string("format"),
|
|
NXT_CONF_MAP_STR,
|
|
offsetof(nxt_conf_vldt_access_log_conf_t, format),
|
|
},
|
|
};
|
|
|
|
|
|
static nxt_int_t
|
|
nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
|
void *data)
|
|
{
|
|
nxt_int_t ret;
|
|
nxt_conf_vldt_access_log_conf_t conf;
|
|
|
|
static nxt_str_t format_str = nxt_string("format");
|
|
|
|
if (nxt_conf_type(value) == NXT_CONF_STRING) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_access_log_members);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
nxt_memzero(&conf, sizeof(nxt_conf_vldt_access_log_conf_t));
|
|
|
|
ret = nxt_conf_map_object(vldt->pool, value,
|
|
nxt_conf_vldt_access_log_map,
|
|
nxt_nitems(nxt_conf_vldt_access_log_map),
|
|
&conf);
|
|
if (ret != NXT_OK) {
|
|
return ret;
|
|
}
|
|
|
|
if (conf.path.length == 0) {
|
|
return nxt_conf_vldt_error(vldt,
|
|
"The \"path\" string must not be empty.");
|
|
}
|
|
|
|
if (nxt_is_tstr(&conf.format)) {
|
|
return nxt_conf_vldt_var(vldt, &format_str, &conf.format);
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|