<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>