<html><head></head><body><div class="yahoo-style-wrap" style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:13px;"><div><div><div>diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c</div><div>index 3f068bb..5c0e74b 100644</div><div>--- a/src/nxt_conf_validation.c</div><div>+++ b/src/nxt_conf_validation.c</div><div>@@ -117,6 +117,10 @@ static nxt_int_t nxt_conf_vldt_share(nxt_conf_validation_t *vldt,</div><div> nxt_conf_value_t *value, void *data);</div><div> static nxt_int_t nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt,</div><div> nxt_conf_value_t *value);</div><div>+static nxt_int_t nxt_conf_vldt_action_index(nxt_conf_validation_t *vldt,</div><div>+ nxt_conf_value_t *value, void *data);</div><div>+static nxt_int_t nxt_conf_vldt_action_index_element(nxt_conf_validation_t *vldt,</div><div>+ nxt_conf_value_t *value);</div><div> static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt,</div><div> nxt_conf_value_t *value, void *data);</div><div> static nxt_int_t nxt_conf_vldt_python(nxt_conf_validation_t *vldt,</div><div>@@ -675,6 +679,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = {</div><div> .validator = nxt_conf_vldt_unsupported,</div><div> .u.string = "traverse_mounts",</div><div> #endif</div><div>+ }, {</div><div>+ .name = nxt_string("index"),</div><div>+ .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,</div><div>+ .validator = nxt_conf_vldt_action_index,</div><div> },</div><div> </div><div> NXT_CONF_VLDT_END</div><div>@@ -1690,6 +1698,52 @@ nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt,</div><div> }</div><div> </div><div> </div><div>+static nxt_int_t</div><div>+nxt_conf_vldt_action_index(nxt_conf_validation_t *vldt,</div><div>+ nxt_conf_value_t *value, void *data)</div><div>+{</div><div>+ nxt_str_t name;</div><div>+</div><div>+ if (nxt_conf_type(value) == NXT_CONF_ARRAY) {</div><div>+ if (nxt_conf_array_elements_count(value) == 0) {</div><div>+ return nxt_conf_vldt_error(vldt, "The \"index\" array "</div><div>+ "must contain at least one element.");</div><div>+ }</div><div>+</div><div>+ return nxt_conf_vldt_array_iterator(vldt, value,</div><div>+ &nxt_conf_vldt_action_index_element);</div><div>+ }</div><div>+</div><div>+ /* NXT_CONF_STRING */</div><div>+ nxt_conf_get_string(value, &name);</div><div>+</div><div>+ return nxt_conf_vldt_share_element(vldt, value);</div><div>+}</div><div>+</div><div>+</div><div>+static nxt_int_t</div><div>+nxt_conf_vldt_action_index_element(nxt_conf_validation_t *vldt,</div><div>+ nxt_conf_value_t *value)</div><div>+{</div><div>+ nxt_str_t str;</div><div>+</div><div>+ static nxt_str_t index = nxt_string("index");</div><div>+</div><div>+ if (nxt_conf_type(value) != NXT_CONF_STRING) {</div><div>+ return nxt_conf_vldt_error(vldt, "The \"index\" array must "</div><div>+ "contain only string values.");</div><div>+ }</div><div>+</div><div>+ nxt_conf_get_string(value, &str);</div><div>+</div><div>+ if (nxt_is_var(&str)) {</div><div>+ return nxt_conf_vldt_var(vldt, &index, &str);</div><div>+ }</div><div>+</div><div>+ return NXT_OK;</div><div>+}</div><div>+</div><div>+</div><div> static nxt_int_t</div><div> nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,</div><div> void *data)</div><div>diff --git a/src/nxt_http.h b/src/nxt_http.h</div><div>index 02d66f5..bc97f83 100644</div><div>--- a/src/nxt_http.h</div><div>+++ b/src/nxt_http.h</div><div>@@ -214,6 +214,7 @@ typedef struct {</div><div> nxt_conf_value_t *traverse_mounts;</div><div> nxt_conf_value_t *types;</div><div> nxt_conf_value_t *fallback;</div><div>+ nxt_conf_value_t *index;</div><div> } nxt_http_action_conf_t;</div><div> </div><div> </div><div>diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c</div><div>index 36c1ebc..6860e2b 100644</div><div>--- a/src/nxt_http_static.c</div><div>+++ b/src/nxt_http_static.c</div><div>@@ -15,15 +15,22 @@ typedef struct {</div><div> uint8_t is_const; /* 1 bit */</div><div> } nxt_http_static_share_t;</div><div> </div><div>+typedef struct {</div><div>+ nxt_var_t *var;</div><div>+ uint8_t is_const; /* 1 bit */</div><div>+} nxt_http_static_share_index_t;</div><div>+</div><div> </div><div> typedef struct {</div><div>- nxt_uint_t nshares;</div><div>- nxt_http_static_share_t *shares;</div><div>+ nxt_uint_t nshares;</div><div>+ nxt_http_static_share_t *shares;</div><div> #if (NXT_HAVE_OPENAT2)</div><div>- nxt_var_t *chroot;</div><div>- nxt_uint_t resolve;</div><div>+ nxt_var_t *chroot;</div><div>+ nxt_uint_t resolve;</div><div> #endif</div><div>- nxt_http_route_rule_t *types;</div><div>+ nxt_http_route_rule_t *types;</div><div>+ nxt_uint_t nindex;</div><div>+ nxt_http_static_share_index_t *index;</div><div> } nxt_http_static_conf_t;</div><div> </div><div> </div><div>@@ -34,6 +41,10 @@ typedef struct {</div><div> nxt_str_t chroot;</div><div> #endif</div><div> uint32_t index;</div><div>+</div><div>+ nxt_str_t *share_index;</div><div>+ uint32_t share_index_read;</div><div>+ uint32_t share_index_write;</div><div> uint8_t need_body; /* 1 bit */</div><div> } nxt_http_static_ctx_t;</div><div> </div><div>@@ -181,6 +192,38 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,</div><div> action->fallback);</div><div> }</div><div> </div><div>+ if (acf->index != NULL) {</div><div>+ array = (nxt_conf_type(acf->index) == NXT_CONF_ARRAY);</div><div>+ conf->nindex = array ? nxt_conf_array_elements_count(acf->index) : 1;</div><div>+</div><div>+ conf->index = nxt_mp_zget(mp, sizeof(nxt_str_t) * conf->nindex);</div><div>+ if (nxt_slow_path(conf->index == NULL)) {</div><div>+ return NXT_ERROR;</div><div>+ }</div><div>+</div><div>+ if (array) {</div><div>+ for (i = 0; i < conf->nindex; i++) {</div><div>+ cv = nxt_conf_get_array_element(acf->index, i);</div><div>+ nxt_conf_get_string(cv, &str);</div><div>+ var = nxt_var_compile(&str, mp, 1);</div><div>+ if (nxt_slow_path(var == NULL)) {</div><div>+ return NXT_ERROR;</div><div>+ }</div><div>+</div><div>+ conf->index[i].var = var;</div><div>+ conf->index[i].is_const = nxt_var_is_const(var);</div><div>+ }</div><div>+ } else {</div><div>+ nxt_conf_get_string(acf->share, &str);</div><div>+ var = nxt_var_compile(&str, mp, 1);</div><div>+ if (nxt_slow_path(var == NULL)) {</div><div>+ return NXT_ERROR;</div><div>+ }</div><div>+ conf->index[0].var = var;</div><div>+ conf->index[0].is_const = nxt_var_is_const(var);</div><div>+ }</div><div>+ }</div><div>+</div><div> return NXT_OK;</div><div> }</div><div> </div><div>@@ -219,10 +262,49 @@ nxt_http_static(nxt_task_t *task, nxt_http_request_t *r,</div><div> ctx->need_body = need_body;</div><div> </div><div> nxt_http_static_iterate(task, r, ctx);</div><div>+ nxt_mp_free(r->mem_pool, ctx->share_index);</div><div> </div><div> return NULL;</div><div> }</div><div> </div><div>+static void</div><div>+nxt_http_static_share_index_resolv(nxt_task_t *task, void *obj, void *data) {</div><div>+ nxt_int_t ret;</div><div>+ nxt_http_static_share_index_t* index;</div><div>+ nxt_http_request_t *r;</div><div>+ nxt_http_static_ctx_t *ctx;</div><div>+ nxt_http_static_conf_t *conf;</div><div>+ nxt_str_t *share_index;</div><div>+</div><div>+ r = obj;</div><div>+ ctx = data;</div><div>+ conf = ctx->action->u.conf;</div><div>+</div><div>+ if (ctx->share_index_write >= conf->nindex) {</div><div>+ return;</div><div>+ }</div><div>+</div><div>+ index = &conf->index[ctx->share_index_write];</div><div>+ share_index = &ctx->share_index[ctx->share_index_write++];</div><div>+</div><div>+ if (index->is_const) {</div><div>+ nxt_var_raw(index->var, share_index);</div><div>+ nxt_http_static_share_index_resolv(task, r, ctx);</div><div>+ }</div><div>+ else {</div><div>+ ret = nxt_var_query_init(&r->var_query, r, r->mem_pool);</div><div>+ if (nxt_slow_path(ret != NXT_OK)) {</div><div>+ nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);</div><div>+ return;</div><div>+ }</div><div>+</div><div>+ nxt_var_query(task, r->var_query, index->var, share_index);</div><div>+ nxt_var_query_resolve(task, r->var_query, ctx,</div><div>+ nxt_http_static_share_index_resolv,</div><div>+ nxt_http_static_var_error);</div><div>+ }</div><div>+}</div><div>+</div><div> </div><div> static void</div><div> nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,</div><div>@@ -234,6 +316,12 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,</div><div> </div><div> conf = ctx->action->u.conf;</div><div> </div><div>+ if (ctx->index == 0 && ctx->share_index_read == 0) {</div><div>+ ctx->share_index = nxt_mp_zalloc(r->mem_pool,</div><div>+ sizeof(nxt_str_t) * conf->nindex);</div><div>+ nxt_http_static_share_index_resolv(task, r, ctx);</div><div>+ }</div><div>+</div><div> share = &conf->shares[ctx->index];</div><div> </div><div> #if (NXT_DEBUG)</div><div>@@ -265,9 +353,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,</div><div> nxt_var_raw(conf->chroot, &ctx->chroot);</div><div> }</div><div> #endif</div><div>-</div><div> nxt_http_static_send_ready(task, r, ctx);</div><div>-</div><div> } else {</div><div> ret = nxt_var_query_init(&r->var_query, r, r->mem_pool);</div><div> if (nxt_slow_path(ret != NXT_OK)) {</div><div>@@ -299,6 +385,7 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data)</div><div> nxt_buf_t *fb;</div><div> nxt_int_t ret;</div><div> nxt_str_t *shr, exten, *mtype;</div><div>+ nxt_str_t *index;</div><div> nxt_uint_t level;</div><div> nxt_file_t *f, file;</div><div> nxt_file_info_t fi;</div><div>@@ -311,8 +398,6 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data)</div><div> nxt_http_static_ctx_t *ctx;</div><div> nxt_http_static_conf_t *conf;</div><div> </div><div>- static const nxt_str_t index = nxt_string("index.html");</div><div>-</div><div> r = obj;</div><div> ctx = data;</div><div> action = ctx->action;</div><div>@@ -323,12 +408,13 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data)</div><div> mtype = NULL;</div><div> </div><div> shr = &ctx->share;</div><div>+ index = &ctx->share_index[ctx->share_index_read];</div><div> </div><div> if (shr->start[shr->length - 1] == '/') {</div><div> /* TODO: dynamic index setting. */</div><div> nxt_str_set(&exten, ".html");</div><div> </div><div>- length = shr->length + index.length;</div><div>+ length = shr->length + index->length;</div><div> </div><div> fname = nxt_mp_nget(r->mem_pool, length + 1);</div><div> if (nxt_slow_path(fname == NULL)) {</div><div>@@ -337,7 +423,7 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data)</div><div> </div><div> p = fname;</div><div> p = nxt_cpymem(p, shr->start, shr->length);</div><div>- p = nxt_cpymem(p, index.start, index.length);</div><div>+ p = nxt_cpymem(p, index->start, index->length);</div><div> *p = '\0';</div><div> </div><div> } else {</div><div>@@ -387,7 +473,7 @@ nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data)</div><div> </div><div> if (fname != NULL) {</div><div> file.name = chr->start;</div><div>- ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN,</div><div>+ ret = (task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN,</div><div> 0);</div><div> </div><div> } else {</div><div>@@ -675,7 +761,11 @@ nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r,</div><div> action = ctx->action;</div><div> conf = action->u.conf;</div><div> </div><div>- ctx->index++;</div><div>+ ctx->share_index_read++;</div><div>+ if (ctx->share_index_read >= conf->nindex) {</div><div>+ ctx->share_index_read = 0;</div><div>+ ctx->index++;</div><div>+ }</div><div> </div><div> if (ctx->index < conf->nshares) {</div><div> nxt_http_static_iterate(task, r, ctx);</div><div><br></div></div><br></div></div></body></html>