Static: multiple paths in the "share" option.
This commit is contained in:
@@ -44,6 +44,12 @@ variables support in the "share" option.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para>
|
||||
multiple paths in the "share" option.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para>
|
||||
variables support in the "chroot" option.
|
||||
|
||||
@@ -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,
|
||||
@@ -1616,6 +1620,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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
var = nxt_var_compile(&str, mp, 1);
|
||||
if (nxt_slow_path(var == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (nxt_is_var(&acf->chroot)) {
|
||||
conf->is_const = 0;
|
||||
}
|
||||
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);
|
||||
|
||||
conf->fname = nxt_http_static_chroot_match(chr.start, shr.start);
|
||||
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->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;
|
||||
|
||||
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
|
||||
@@ -224,13 +287,6 @@ nxt_http_static(nxt_task_t *task, nxt_http_request_t *r,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,6 +372,9 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data)
|
||||
if (conf->resolve != 0 || ctx->chroot.length > 0) {
|
||||
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_http_static_next(task, r, ctx, NXT_HTTP_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
status = NXT_HTTP_NOT_FOUND;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
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 *
|
||||
|
||||
Reference in New Issue
Block a user