[PATCH v4 09/12] Static: variables in the "index" option

Alejandro Colomar alx.manpages at gmail.com
Thu Dec 23 19:25:06 UTC 2021


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

{
	"share": "/srv/www/data/static/$uri",
	"index": "$method.html"
}

When <example.com/foo/bar/> is requested,
</srv/www/data/static/foo/bar/GET.html> will be served.

===

test_static.py:

Rename <index_.html> to <localhost.html>, to be able to test this
feature, and set "index": "$host.html>".

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

- Setting "index" to "$method.html", and check that <GET.html> is
  being served.
- Not setting index, and check that <index.html> is being served.
- Setting "index" to "$asdf", and check that the configuration
  fails:

{
	"error": "Invalid configuration.",
	"detail": "Unknown variable \"asdf\" in the \"index\" value."
}

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>
---
 docs/changes.xml          |  6 ++++++
 src/nxt_conf_validation.c |  1 +
 src/nxt_http_static.c     | 29 +++++++++++++++++++++--------
 test/test_static.py       | 13 +++++++------
 4 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/docs/changes.xml b/docs/changes.xml
index 07f3c83..8931165 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>
+variables support in the "index" option.
+</para>
+</change>
+
 <change type="feature">
 <para>
 new "index" option to specify a custom index file name.
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c
index bdc38b0..6236720 100644
--- a/src/nxt_conf_validation.c
+++ b/src/nxt_conf_validation.c
@@ -648,6 +648,7 @@ static nxt_conf_vldt_object_t  nxt_conf_vldt_share_action_members[] = {
     }, {
         .name       = nxt_string("index"),
         .type       = NXT_CONF_VLDT_STRING,
+        .flags      = NXT_CONF_VLDT_VAR,
     }, {
         .name       = nxt_string("types"),
         .type       = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c
index 2a176d0..57d8ca8 100644
--- a/src/nxt_http_static.c
+++ b/src/nxt_http_static.c
@@ -19,7 +19,7 @@ typedef struct {
 typedef struct {
     nxt_uint_t                  nshares;
     nxt_http_static_share_t     *shares;
-    nxt_str_t                   index;
+    nxt_var_t                   *index;
 #if (NXT_HAVE_OPENAT2)
     nxt_var_t                   *chroot;
     nxt_uint_t                  resolve;
@@ -115,12 +115,19 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
     }
 
     if (acf->index == NULL) {
-        conf->index = default_index;
+        str = default_index;
 
     } else {
-        nxt_conf_get_string(acf->index, &conf->index);
+        nxt_conf_get_string(acf->index, &str);
     }
 
+    var = nxt_var_compile(&str, mp, 1);
+    if (nxt_slow_path(var == NULL)) {
+        return NXT_ERROR;
+    }
+
+    conf->index = var;
+
 #if (NXT_HAVE_OPENAT2)
     if (acf->chroot.length > 0) {
         nxt_str_t   chr, shr;
@@ -226,7 +233,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
     nxt_int_t                ret;
     nxt_http_static_conf_t   *conf;
     nxt_http_static_share_t  *share;
-    nxt_bool_t               shr_is_const;
+    nxt_bool_t               shr_is_const, idx_is_const;
 
     conf = ctx->action->u.conf;
 
@@ -237,7 +244,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
     nxt_str_t  idx;
 
     nxt_var_raw(share->var, &shr);
-    idx = conf->index;
+    nxt_var_raw(conf->index, &idx);
 
 #if (NXT_HAVE_OPENAT2)
     nxt_str_t  chr;
@@ -257,8 +264,9 @@ 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);
 
-    if (!shr_is_const) {
+    if (!shr_is_const || !idx_is_const) {
         ret = nxt_var_query_init(&r->var_query, r, r->mem_pool);
         if (nxt_slow_path(ret != NXT_OK)) {
             nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
@@ -266,7 +274,12 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
         }
     }
 
-    ctx->index = conf->index;
+    if (idx_is_const) {
+        nxt_var_raw(conf->index, &ctx->index);
+
+    } else {
+        nxt_var_query(task, r->var_query, conf->index, &ctx->index);
+    }
 
     if (shr_is_const) {
         nxt_var_raw(share->var, &ctx->share);
@@ -287,7 +300,7 @@ nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r,
 #endif
     }
 
-    if (shr_is_const) {
+    if (shr_is_const && idx_is_const) {
         nxt_http_static_send_ready(task, r, ctx);
 
     } else {
diff --git a/test/test_static.py b/test/test_static.py
index 70ae676..2190901 100644
--- a/test/test_static.py
+++ b/test/test_static.py
@@ -14,7 +14,8 @@ class TestStatic(TestApplicationProto):
 
     def setup_method(self):
         os.makedirs(option.temp_dir + '/assets/dir')
-        with open(option.temp_dir + '/assets/index_.html', 'w') as index, open(
+        with open(option.temp_dir + '/assets/localhost.html', 'w'
+        ) as index, open(
             option.temp_dir + '/assets/README', 'w'
         ) as readme, open(
             option.temp_dir + '/assets/log.log', 'w'
@@ -33,7 +34,7 @@ class TestStatic(TestApplicationProto):
                     {
                         "action": {
                             "share": option.temp_dir + "/assets$uri",
-                            "index": "index_.html"
+                            "index": "$host.html"
                         }
                     }
                 ],
@@ -91,7 +92,7 @@ class TestStatic(TestApplicationProto):
         assert self.get(url='/')['body'] == '0123456789', 'before 1.26.0 2'
 
     def test_static_index(self):
-        assert self.get(url='/index_.html')['body'] == '0123456789', 'index'
+        assert self.get(url='/localhost.html')['body'] == '0123456789', 'index'
         assert self.get(url='/')['body'] == '0123456789', 'index 2'
         assert self.get(url='//')['body'] == '0123456789', 'index 3'
         assert self.get(url='/.')['body'] == '0123456789', 'index 4'
@@ -100,7 +101,7 @@ class TestStatic(TestApplicationProto):
         assert self.get(url='/#blah')['body'] == '0123456789', 'index anchor'
         assert self.get(url='/dir/')['status'] == 404, 'index not found'
 
-        resp = self.get(url='/index_.html/')
+        resp = self.get(url='/localhost.html/')
         assert resp['status'] == 404, 'index not found 2 status'
         assert (
             resp['headers']['Content-Type'] == 'text/html'
@@ -124,7 +125,7 @@ class TestStatic(TestApplicationProto):
         assert etag != etag_2, 'different ETag'
         assert etag == self.get(url='/')['headers']['ETag'], 'same ETag'
 
-        with open(temp_dir + '/assets/index_.html', 'w') as f:
+        with open(temp_dir + '/assets/localhost.html', 'w') as f:
             f.write('blah')
 
         assert etag != self.get(url='/')['headers']['ETag'], 'new ETag'
@@ -263,7 +264,7 @@ class TestStatic(TestApplicationProto):
             == 'text/x-code/x-blah/x-blah'
         ), 'mime_types string case insensitive'
         assert (
-            self.get(url='/index_.html')['headers']['Content-Type']
+            self.get(url='/localhost.html')['headers']['Content-Type']
             == 'text/plain'
         ), 'mime_types html'
         assert (
-- 
2.34.1



More information about the unit mailing list