diff options
author | Zhidao HONG <z.hong@f5.com> | 2021-10-01 10:03:55 +0800 |
---|---|---|
committer | Zhidao HONG <z.hong@f5.com> | 2021-10-01 10:03:55 +0800 |
commit | 95e653590927bfdb6919a8652ef62824cc6c9538 (patch) | |
tree | 5d721627f4156752299f06fecafedd6d6e0b0d4e | |
parent | c5220944d2acdb912c129fc82ac8a83d24e9845d (diff) | |
download | unit-95e653590927bfdb6919a8652ef62824cc6c9538.tar.gz unit-95e653590927bfdb6919a8652ef62824cc6c9538.tar.bz2 |
Static: multiple paths in the "share" option.
-rw-r--r-- | docs/changes.xml | 6 | ||||
-rw-r--r-- | src/nxt_conf_validation.c | 51 | ||||
-rw-r--r-- | src/nxt_http_static.c | 217 |
3 files changed, 202 insertions, 72 deletions
diff --git a/docs/changes.xml b/docs/changes.xml index 1e1bff0a..12f5264f 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -46,6 +46,12 @@ variables support in the "share" option. <change type="feature"> <para> +multiple paths in the "share" option. +</para> +</change> + +<change type="feature"> +<para> variables support in the "chroot" option. </para> </change> diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 23e6d823..55107cd6 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -113,6 +113,10 @@ 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, @@ -633,8 +637,8 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = { static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { { .name = nxt_string("share"), - .type = NXT_CONF_VLDT_STRING, - .flags = NXT_CONF_VLDT_VAR, + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_share, }, { .name = nxt_string("types"), .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, @@ -1617,6 +1621,49 @@ nxt_conf_vldt_return(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 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_var(&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) { diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index c610bbf7..06e0cab2 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -8,14 +8,22 @@ typedef struct { - nxt_var_t *share; + nxt_var_t *var; +#if (NXT_HAVE_OPENAT2) + u_char *fname; +#endif + uint8_t is_const; /* 1 bit */ +} nxt_http_static_share_t; + + +typedef struct { + nxt_uint_t nshares; + nxt_http_static_share_t *shares; #if (NXT_HAVE_OPENAT2) nxt_var_t *chroot; nxt_uint_t resolve; - u_char *fname; #endif nxt_http_route_rule_t *types; - uint8_t is_const; /* 1 bit */ } nxt_http_static_conf_t; @@ -25,6 +33,7 @@ typedef struct { #if (NXT_HAVE_OPENAT2) nxt_str_t chroot; #endif + uint32_t index; uint8_t need_body; /* 1 bit */ } nxt_http_static_ctx_t; @@ -35,8 +44,12 @@ typedef struct { static nxt_http_action_t *nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action); +static void nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_static_ctx_t *ctx); static void nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data); static void nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data); +static void nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_static_ctx_t *ctx, nxt_http_status_t status); #if (NXT_HAVE_OPENAT2) static u_char *nxt_http_static_chroot_match(u_char *chr, u_char *shr); #endif @@ -60,8 +73,12 @@ nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action, nxt_http_action_conf_t *acf) { + uint32_t i; nxt_mp_t *mp; nxt_str_t str; + nxt_var_t *var; + nxt_bool_t array; + nxt_conf_value_t *cv; nxt_http_static_conf_t *conf; mp = tmcf->router_conf->mem_pool; @@ -74,33 +91,63 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, action->handler = nxt_http_static; action->u.conf = conf; - nxt_conf_get_string(acf->share, &str); + array = (nxt_conf_type(acf->share) == NXT_CONF_ARRAY); + conf->nshares = array ? nxt_conf_array_elements_count(acf->share) : 1; - conf->share = nxt_var_compile(&str, mp, 1); - if (nxt_slow_path(conf->share == NULL)) { + conf->shares = nxt_mp_zget(mp, sizeof(nxt_http_static_share_t) + * conf->nshares); + if (nxt_slow_path(conf->shares == NULL)) { return NXT_ERROR; } - conf->is_const = nxt_var_is_const(conf->share); + if (array) { + for (i = 0; i < conf->nshares; i++) { + cv = nxt_conf_get_array_element(acf->share, i); + nxt_conf_get_string(cv, &str); -#if (NXT_HAVE_OPENAT2) - if (acf->chroot.length > 0) { - nxt_str_t chr, shr; + var = nxt_var_compile(&str, mp, 1); + if (nxt_slow_path(var == NULL)) { + return NXT_ERROR; + } - if (nxt_is_var(&acf->chroot)) { - conf->is_const = 0; + conf->shares[i].var = var; + conf->shares[i].is_const = nxt_var_is_const(var); } + } else { + nxt_conf_get_string(acf->share, &str); + + var = nxt_var_compile(&str, mp, 1); + if (nxt_slow_path(var == NULL)) { + return NXT_ERROR; + } + + conf->shares[0].var = var; + conf->shares[0].is_const = nxt_var_is_const(var); + } + +#if (NXT_HAVE_OPENAT2) + if (acf->chroot.length > 0) { + nxt_str_t chr, shr; + nxt_bool_t is_const; + conf->chroot = nxt_var_compile(&acf->chroot, mp, 1); if (nxt_slow_path(conf->chroot == NULL)) { return NXT_ERROR; } - if (conf->is_const) { - nxt_var_raw(conf->chroot, &chr); - nxt_var_raw(conf->share, &shr); + is_const = nxt_var_is_const(conf->chroot); + + for (i = 0; i < conf->nshares; i++) { + conf->shares[i].is_const &= is_const; + + if (conf->shares[i].is_const) { + nxt_var_raw(conf->chroot, &chr); + nxt_var_raw(conf->shares[i].var, &shr); - conf->fname = nxt_http_static_chroot_match(chr.start, shr.start); + conf->shares[i].fname = nxt_http_static_chroot_match(chr.start, + shr.start); + } } } @@ -142,10 +189,8 @@ static nxt_http_action_t * nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { - nxt_int_t ret; - nxt_bool_t need_body; - nxt_http_static_ctx_t *ctx; - nxt_http_static_conf_t *conf; + nxt_bool_t need_body; + nxt_http_static_ctx_t *ctx; if (nxt_slow_path(!nxt_str_eq(r->method, "GET", 3))) { @@ -164,12 +209,37 @@ nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, need_body = 1; } - conf = action->u.conf; + ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_static_ctx_t)); + if (nxt_slow_path(ctx == NULL)) { + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return NULL; + } + + ctx->action = action; + ctx->need_body = need_body; + + nxt_http_static_iterate(task, r, ctx); + + return NULL; +} + + +static void +nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_static_ctx_t *ctx) +{ + nxt_int_t ret; + nxt_http_static_conf_t *conf; + nxt_http_static_share_t *share; + + conf = ctx->action->u.conf; + + share = &conf->shares[ctx->index]; #if (NXT_DEBUG) nxt_str_t shr; - nxt_var_raw(conf->share, &shr); + nxt_var_raw(share->var, &shr); #if (NXT_HAVE_OPENAT2) nxt_str_t chr; @@ -187,19 +257,11 @@ nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, #endif #endif /* NXT_DEBUG */ - ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_static_ctx_t)); - if (nxt_slow_path(ctx == NULL)) { - goto fail; - } - - ctx->action = action; - ctx->need_body = need_body; - - if (conf->is_const) { - nxt_var_raw(conf->share, &ctx->share); + if (share->is_const) { + nxt_var_raw(share->var, &ctx->share); #if (NXT_HAVE_OPENAT2) - if (conf->chroot != NULL) { + if (conf->chroot != NULL && ctx->index == 0) { nxt_var_raw(conf->chroot, &ctx->chroot); } #endif @@ -209,13 +271,14 @@ nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, } else { ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { - goto fail; + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + return; } - nxt_var_query(task, r->var_query, conf->share, &ctx->share); + nxt_var_query(task, r->var_query, share->var, &ctx->share); #if (NXT_HAVE_OPENAT2) - if (conf->chroot != NULL) { + if (conf->chroot != NULL && ctx->index == 0) { nxt_var_query(task, r->var_query, conf->chroot, &ctx->chroot); } #endif @@ -223,14 +286,7 @@ nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, nxt_var_query_resolve(task, r->var_query, ctx, nxt_http_static_send_ready, nxt_http_static_var_error); - } - - return NULL; - -fail: - - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); - return NULL; + } } @@ -255,7 +311,7 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) nxt_http_static_ctx_t *ctx; nxt_http_static_conf_t *conf; - static nxt_str_t index = nxt_string("index.html"); + static const nxt_str_t index = nxt_string("index.html"); r = obj; ctx = data; @@ -300,8 +356,8 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) } if (ret == 0) { - status = NXT_HTTP_FORBIDDEN; - goto fail; + nxt_http_static_next(task, r, ctx, NXT_HTTP_FORBIDDEN); + return; } } @@ -314,8 +370,11 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) #if (NXT_HAVE_OPENAT2) if (conf->resolve != 0 || ctx->chroot.length > 0) { - nxt_str_t *chr; - nxt_uint_t resolve; + nxt_str_t *chr; + nxt_uint_t resolve; + nxt_http_static_share_t *share; + + share = &conf->shares[ctx->index]; resolve = conf->resolve; chr = &ctx->chroot; @@ -323,8 +382,8 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) if (chr->length > 0) { resolve |= RESOLVE_IN_ROOT; - fname = conf->is_const - ? conf->fname + fname = share->is_const + ? share->fname : nxt_http_static_chroot_match(chr->start, file.name); if (fname != NULL) { @@ -407,10 +466,6 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) break; } - if (level == NXT_LOG_ERR && action->fallback != NULL) { - goto fail; - } - if (status != NXT_HTTP_NOT_FOUND) { #if (NXT_HAVE_OPENAT2) nxt_str_t *chr = &ctx->chroot; @@ -429,6 +484,11 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) #endif } + if (level == NXT_LOG_ERR) { + nxt_http_static_next(task, r, ctx, status); + return; + } + goto fail; } @@ -525,18 +585,16 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) } else { /* Not a file. */ + nxt_file_close(task, f); if (nxt_slow_path(!nxt_is_dir(&fi))) { - if (action->fallback == NULL) { - nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file", - f->name); - } + nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file", + f->name); - status = NXT_HTTP_NOT_FOUND; - goto fail; + nxt_http_static_next(task, r, ctx, NXT_HTTP_NOT_FOUND); + return; } - nxt_file_close(task, f); f = NULL; r->status = NXT_HTTP_MOVED_PERMANENTLY; @@ -592,14 +650,7 @@ fail: nxt_file_close(task, f); } - if (status != NXT_HTTP_INTERNAL_SERVER_ERROR - && action->fallback != NULL) - { - nxt_http_request_action(task, r, action->fallback); - return; - } - - nxt_http_request_error(task, r, status); + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } @@ -614,6 +665,32 @@ nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data) } +static void +nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_static_ctx_t *ctx, nxt_http_status_t status) +{ + nxt_http_action_t *action; + nxt_http_static_conf_t *conf; + + action = ctx->action; + conf = action->u.conf; + + ctx->index++; + + if (ctx->index < conf->nshares) { + nxt_http_static_iterate(task, r, ctx); + return; + } + + if (action->fallback != NULL) { + nxt_http_request_action(task, r, action->fallback); + return; + } + + nxt_http_request_error(task, r, status); +} + + #if (NXT_HAVE_OPENAT2) static u_char * |