HTTP: fixed variable caching.

When a variable is accessed in the Unit configuration, the value is cached.
This was useful prior to the URI rewrite feature, but now that the URI (more
precisely, the request target) can be rewritten, the contents of the variable
$uri (which contains the path part of the request target, and is decoded)
should not be cached anymore, or at least the cached value should be invalidated
after a URI rewrite.

Example:

{
	"rewrite": "/prefix$uri",
	"share": "$uri"
}

For a request line like GET /foo?bar=baz HTTP/1.1\r\n, the expected file
served in the response would be /prefix/foo, but due to the caching issue,
Unit currently serves /foo.
This commit is contained in:
Zhidao HONG 2023-05-25 00:27:55 +08:00
parent ce2405ec3d
commit a378f6aa31
4 changed files with 48 additions and 15 deletions

View file

@ -32,6 +32,12 @@ NGINX Unit updated to 1.31.0.
date="" time=""
packager="Nginx Packaging <nginx-packaging@f5.com>">
<change type="bugfix">
<para>
ensure that $uri variable is not cached.
</para>
</change>
<change type="bugfix">
<para>
deprecated options were unavailable.

View file

@ -47,54 +47,70 @@ static nxt_var_decl_t nxt_http_vars[] = {
{
.name = nxt_string("dollar"),
.handler = nxt_http_var_dollar,
.cacheable = 1,
}, {
.name = nxt_string("request_time"),
.handler = nxt_http_var_request_time,
.cacheable = 1,
}, {
.name = nxt_string("method"),
.handler = nxt_http_var_method,
.cacheable = 1,
}, {
.name = nxt_string("request_uri"),
.handler = nxt_http_var_request_uri,
.cacheable = 1,
}, {
.name = nxt_string("uri"),
.handler = nxt_http_var_uri,
.cacheable = 0,
}, {
.name = nxt_string("host"),
.handler = nxt_http_var_host,
.cacheable = 1,
}, {
.name = nxt_string("remote_addr"),
.handler = nxt_http_var_remote_addr,
.cacheable = 1,
}, {
.name = nxt_string("time_local"),
.handler = nxt_http_var_time_local,
.cacheable = 1,
}, {
.name = nxt_string("request_line"),
.handler = nxt_http_var_request_line,
.cacheable = 1,
}, {
.name = nxt_string("status"),
.handler = nxt_http_var_status,
.cacheable = 1,
}, {
.name = nxt_string("body_bytes_sent"),
.handler = nxt_http_var_body_bytes_sent,
.cacheable = 1,
}, {
.name = nxt_string("header_referer"),
.handler = nxt_http_var_referer,
.cacheable = 1,
}, {
.name = nxt_string("header_user_agent"),
.handler = nxt_http_var_user_agent,
.cacheable = 1,
}, {
.name = nxt_string("arg"),
.handler = nxt_http_var_arg,
.field_hash = nxt_http_argument_hash,
.cacheable = 1,
}, {
.name = nxt_string("header"),
.handler = nxt_http_var_header,
.field_hash = nxt_http_header_hash,
.cacheable = 1,
}, {
.name = nxt_string("cookie"),
.handler = nxt_http_var_cookie,
.field_hash = nxt_http_cookie_hash,
.cacheable = 1,
},
};

View file

@ -80,7 +80,7 @@ static const nxt_lvlhsh_proto_t nxt_var_cache_proto nxt_aligned(64) = {
static nxt_lvlhsh_t nxt_var_hash;
static uint32_t nxt_var_count;
static nxt_var_handler_t *nxt_var_index;
static nxt_var_decl_t **nxt_vars;
static nxt_int_t
@ -235,8 +235,11 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index,
{
nxt_int_t ret;
nxt_str_t *value;
nxt_var_decl_t *var;
nxt_lvlhsh_query_t lhq;
var = nxt_vars[index >> 16];
value = cache->spare;
if (value == NULL) {
@ -248,6 +251,10 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index,
cache->spare = value;
}
if (!var->cacheable) {
goto not_cached;
}
lhq.key_hash = nxt_murmur_hash2_uint32(&index);
lhq.replace = 0;
lhq.key.length = sizeof(uint32_t);
@ -261,16 +268,20 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index,
return NULL;
}
if (ret == NXT_OK) {
ret = nxt_var_index[index >> 16](task, value, ctx, index & 0xffff);
if (nxt_slow_path(ret != NXT_OK)) {
return NULL;
}
cache->spare = NULL;
if (ret == NXT_DECLINED) {
return lhq.value;
}
return lhq.value;
not_cached:
ret = var->handler(task, value, ctx, index & 0xffff);
if (nxt_slow_path(ret != NXT_OK)) {
return NULL;
}
cache->spare = NULL;
return value;
}
@ -303,12 +314,11 @@ nxt_int_t
nxt_var_index_init(void)
{
nxt_uint_t i;
nxt_var_decl_t *decl;
nxt_var_handler_t *index;
nxt_var_decl_t *decl, **vars;
nxt_lvlhsh_each_t lhe;
index = nxt_memalign(64, nxt_var_count * sizeof(nxt_var_handler_t));
if (index == NULL) {
vars = nxt_memalign(64, nxt_var_count * sizeof(nxt_var_decl_t *));
if (vars == NULL) {
return NXT_ERROR;
}
@ -317,10 +327,10 @@ nxt_var_index_init(void)
for (i = 0; i < nxt_var_count; i++) {
decl = nxt_lvlhsh_each(&nxt_var_hash, &lhe);
decl->index = i;
index[i] = decl->handler;
vars[i] = decl;
}
nxt_var_index = index;
nxt_vars = vars;
return NXT_OK;
}

View file

@ -22,6 +22,7 @@ typedef struct {
nxt_var_handler_t handler;
nxt_var_field_hash_t field_hash;
uint32_t index;
uint8_t cacheable; /* 1 bit */
} nxt_var_decl_t;