[PATCH v6 14/15] Static: multiple paths in the "index" option

Alejandro Colomar alx.manpages at gmail.com
Tue Feb 15 14:57:54 UTC 2022


This adds support for multiple paths in the "index" option.
An example:

{
	"share": "/srv/www/stat/static/$uri",
	"index": [
		"$method.html",
		"alt.html"
	]
}

When <example.com/foo/bar/> is requested,
</srv/www/data/static/foo/bar/GET.html> will be served if it
exists; otherwise, </srv/www/data/static/foo/bar/alt.html> will be
served.

===

I also tried this feature in my own computer, where I tried the
following:

- Setting "index" to ["idontexist", "$host.html"], and check that
  <localhost.html> is being served.
- Not setting "index", and check that <index.html> is being
  served.
- Setting "index" to [], and check that it reports an error when
  loading the configuration.

Signed-off-by: Alejandro Colomar <alx.manpages at gmail.com>
Cc: Nginx Unit <unit at nginx.org>
Cc: "Valentin V. Bartenev" <vbart at nginx.com>
Cc: Zhidao HONG <z.hong at f5.com>
Cc: Igor Sysoev <igor at sysoev.ru>
Cc: Oisin Canty <o.canty at f5.com>
Cc: Andrei Zeliankou <zelenkov at nginx.com>
Cc: Maxim Romanov <m.romanov at f5.com>
---
 docs/changes.xml          |  6 +++++
 src/nxt_conf_validation.c | 51 +++++++++++++++++++++++++++++++++++++--
 src/nxt_http_static.c     | 38 ++++++++++++++++++++---------
 test/test_static.py       |  2 +-
 4 files changed, 83 insertions(+), 14 deletions(-)

diff --git a/docs/changes.xml b/docs/changes.xml
index 7709fc8..18e180d 100644
--- a/docs/changes.xml
+++ b/docs/changes.xml
@@ -18,6 +18,12 @@
          date="" time=""
          packager="Andrei Belov <defan at nginx.com>">
 
+<change type="feature">
+<para>
+multiple paths in the "index" option.
+</para>
+</change>
+
 <change type="feature">
 <para>
 variables support in the "index" option.
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c
index 6236720..5b94116 100644
--- a/src/nxt_conf_validation.c
+++ b/src/nxt_conf_validation.c
@@ -117,6 +117,10 @@ 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_index(nxt_conf_validation_t *vldt,
+    nxt_conf_value_t *value, void *data);
+static nxt_int_t nxt_conf_vldt_index_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,
@@ -647,8 +651,8 @@ static nxt_conf_vldt_object_t  nxt_conf_vldt_share_action_members[] = {
         .validator  = nxt_conf_vldt_share,
     }, {
         .name       = nxt_string("index"),
-        .type       = NXT_CONF_VLDT_STRING,
-        .flags      = NXT_CONF_VLDT_VAR,
+        .type       = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
+        .validator  = nxt_conf_vldt_index,
     }, {
         .name       = nxt_string("types"),
         .type       = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
@@ -1694,6 +1698,49 @@ nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt,
 }
 
 
+static nxt_int_t
+nxt_conf_vldt_index(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 \"index\" array "
+                                       "must contain at least one element.");
+        }
+
+        return nxt_conf_vldt_array_iterator(vldt, value,
+                                            &nxt_conf_vldt_index_element);
+    }
+
+    /* NXT_CONF_STRING */
+
+    return nxt_conf_vldt_index_element(vldt, value);
+}
+
+
+static nxt_int_t
+nxt_conf_vldt_index_element(nxt_conf_validation_t *vldt,
+    nxt_conf_value_t *value)
+{
+    nxt_str_t  str;
+
+    static nxt_str_t  index = nxt_string("index");
+
+    if (nxt_conf_type(value) != NXT_CONF_STRING) {
+        return nxt_conf_vldt_error(vldt, "The \"index\" array must "
+                                   "contain only string values.");
+    }
+
+    nxt_conf_get_string(value, &str);
+
+    if (nxt_is_var(&str)) {
+        return nxt_conf_vldt_var(vldt, &index, &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 cbc8cbf..d6bb88d 100644
--- a/src/nxt_http_static.c
+++ b/src/nxt_http_static.c
@@ -18,8 +18,9 @@ typedef struct {
 
 typedef struct {
     nxt_uint_t                  nshares;
+    nxt_uint_t                  nindices;
     nxt_http_static_share_t     *shares;
-    nxt_var_t                   *index;
+    nxt_var_t                   **indices;
 #if (NXT_HAVE_OPENAT2)
     nxt_var_t                   *chroot;
     nxt_uint_t                  resolve;
@@ -36,6 +37,7 @@ typedef struct {
     nxt_str_t                   chroot;
 #endif
     uint32_t                    share_idx;
+    uint32_t                    index_idx;
     uint8_t                     need_body;  /* 1 bit */
 } nxt_http_static_ctx_t;
 
@@ -123,14 +125,23 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
         nxt_conf_set_string_dup(acf->index, mp, &default_index);
     }
 
-    nxt_conf_get_string(acf->index, &str);
-
-    var = nxt_var_compile(&str, mp, 1);
-    if (nxt_slow_path(var == NULL)) {
+    conf->nindices = nxt_conf_array_elements_count(acf->index);
+    conf->indices = nxt_mp_zget(mp, sizeof(*conf->indices) * conf->nindices);
+    if (nxt_slow_path(conf->indices == NULL)) {
         return NXT_ERROR;
     }
 
-    conf->index = var;
+    for (i = 0; i < conf->nindices; i++) {
+        cv = nxt_conf_get_array_element(acf->index, i);
+        nxt_conf_get_string(cv, &str);
+
+        var = nxt_var_compile(&str, mp, 1);
+        if (nxt_slow_path(var == NULL)) {
+            return NXT_ERROR;
+        }
+
+        conf->indices[i] = var;
+    }
 
 #if (NXT_HAVE_OPENAT2)
     if (acf->chroot.length > 0) {
@@ -235,6 +246,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
     nxt_http_static_ctx_t *ctx)
 {
     nxt_int_t                ret;
+    nxt_var_t                *index;
     nxt_http_static_conf_t   *conf;
     nxt_http_static_share_t  *share;
     nxt_bool_t               shr_is_const, idx_is_const;
@@ -242,13 +254,14 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
     conf = ctx->action->u.conf;
 
     share = &conf->shares[ctx->share_idx];
+    index = conf->indices[ctx->index_idx];
 
 #if (NXT_DEBUG)
     nxt_str_t  shr;
     nxt_str_t  idx;
 
     nxt_var_raw(share->var, &shr);
-    nxt_var_raw(conf->index, &idx);
+    nxt_var_raw(index, &idx);
 
 #if (NXT_HAVE_OPENAT2)
     nxt_str_t  chr;
@@ -268,7 +281,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
 #endif /* NXT_DEBUG */
 
     shr_is_const = share->is_const;
-    idx_is_const = nxt_var_is_const(conf->index);
+    idx_is_const = nxt_var_is_const(index);
 
     if (!shr_is_const || !idx_is_const) {
         ret = nxt_var_query_init(&r->var_query, r, r->mem_pool);
@@ -279,10 +292,10 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
     }
 
     if (idx_is_const) {
-        nxt_var_raw(conf->index, &ctx->index);
+        nxt_var_raw(index, &ctx->index);
 
     } else {
-        nxt_var_query(task, r->var_query, conf->index, &ctx->index);
+        nxt_var_query(task, r->var_query, index, &ctx->index);
     }
 
     if (shr_is_const) {
@@ -700,7 +713,10 @@ nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r,
     action = ctx->action;
     conf = action->u.conf;
 
-    ctx->share_idx++;
+    ctx->index_idx = (ctx->index_idx + 1) % conf->nindices;
+    if (ctx->index_idx == 0) {
+        ctx->share_idx++;
+    }
 
     if (ctx->share_idx < conf->nshares) {
         nxt_http_static_iterate(task, r, ctx);
diff --git a/test/test_static.py b/test/test_static.py
index 0368af6..e1909cd 100644
--- a/test/test_static.py
+++ b/test/test_static.py
@@ -35,7 +35,7 @@ class TestStatic(TestApplicationProto):
                     {
                         "action": {
                             "share": option.temp_dir + "/assets$uri",
-                            "index": "$host.html"
+                            "index": ["idontexist", "$host.html"]
                         }
                     }
                 ],
-- 
2.34.1



More information about the unit mailing list