From a378f6aa3136ed7ef172b71add31ee62e560df00 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 25 May 2023 00:27:55 +0800 Subject: 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. --- src/nxt_var.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'src/nxt_var.c') diff --git a/src/nxt_var.c b/src/nxt_var.c index e113969f..e4299a09 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -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; - } + if (ret == NXT_DECLINED) { + return lhq.value; + } + +not_cached: - cache->spare = NULL; + ret = var->handler(task, value, ctx, index & 0xffff); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; } - return lhq.value; + 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; } -- cgit From c61ccec7b4926476b2188092e25990e433332688 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 19 Jun 2023 16:29:22 +0800 Subject: Variables refactoring. This commit is to reimplement the variables with an unknown field such as $header_{name} to make the parsing more generic, it's a preparation for supporting response header variables. --- src/nxt_var.c | 166 ++++++++++++++++++++++++---------------------------------- 1 file changed, 69 insertions(+), 97 deletions(-) (limited to 'src/nxt_var.c') diff --git a/src/nxt_var.c b/src/nxt_var.c index e4299a09..729de788 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -50,14 +50,11 @@ struct nxt_var_query_s { static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); -static nxt_var_decl_t *nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, - uint32_t *index); -static nxt_var_field_t *nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, - uint32_t hash); +static nxt_var_ref_t *nxt_var_ref_get(nxt_tstr_state_t *state, nxt_str_t *name); static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); -static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, - uint32_t index, void *ctx); +static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_tstr_state_t *state, + nxt_var_cache_t *cache, uint32_t index, void *ctx); static u_char *nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part); @@ -111,95 +108,70 @@ nxt_var_hash_find(nxt_str_t *name) } -static nxt_var_decl_t * -nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, uint32_t *index) +static nxt_var_ref_t * +nxt_var_ref_get(nxt_tstr_state_t *state, nxt_str_t *name) { - u_char *p, *end; - int64_t hash; - uint16_t field; - nxt_str_t str; - nxt_var_decl_t *decl; - nxt_var_field_t *f; - - f = NULL; - field = 0; - decl = nxt_var_hash_find(name); + nxt_int_t ret; + nxt_uint_t i; + nxt_var_ref_t *ref; + nxt_var_decl_t *decl; - if (decl == NULL) { - p = name->start; - end = p + name->length; + ref = state->var_refs->elts; - while (p < end) { - if (*p++ == '_') { - break; - } - } + for (i = 0; i < state->var_refs->nelts; i++) { - if (p == end) { - return NULL; + if (nxt_strstr_eq(ref[i].name, name)) { + return &ref[i]; } + } - str.start = name->start; - str.length = p - 1 - name->start; + ref = nxt_array_add(state->var_refs); + if (nxt_slow_path(ref == NULL)) { + return NULL; + } - decl = nxt_var_hash_find(&str); + ref->index = state->var_refs->nelts - 1; - if (decl != NULL) { - str.start = p; - str.length = end - p; + ref->name = nxt_str_dup(state->pool, NULL, name); + if (nxt_slow_path(ref->name == NULL)) { + return NULL; + } - hash = decl->field_hash(fields->mem_pool, &str); - if (nxt_slow_path(hash == -1)) { - return NULL; - } + decl = nxt_var_hash_find(name); - f = nxt_var_field_add(fields, &str, (uint32_t) hash); - if (nxt_slow_path(f == NULL)) { - return NULL; - } + if (decl != NULL) { + ref->handler = decl->handler; + ref->cacheable = decl->cacheable; - field = f->index; - } + return ref; } - if (decl != NULL) { - if (decl->field_hash != NULL && f == NULL) { - return NULL; - } - - if (index != NULL) { - *index = (decl->index << 16) | field; - } + ret = nxt_http_unknown_var_ref(state, ref, name); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; } - return decl; + return ref; } -static nxt_var_field_t * -nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, uint32_t hash) +nxt_var_field_t * +nxt_var_field_new(nxt_mp_t *mp, nxt_str_t *name, uint32_t hash) { - nxt_uint_t i; + nxt_str_t *str; nxt_var_field_t *field; - field = fields->elts; - - for (i = 0; i < fields->nelts; i++) { - if (field[i].hash == hash - && nxt_strstr_eq(&field[i].name, name)) - { - return field; - } + field = nxt_mp_alloc(mp, sizeof(nxt_var_field_t)); + if (nxt_slow_path(field == NULL)) { + return NULL; } - field = nxt_array_add(fields); - if (nxt_slow_path(field == NULL)) { + str = nxt_str_dup(mp, &field->name, name); + if (nxt_slow_path(str == NULL)) { return NULL; } - field->name = *name; field->hash = hash; - field->index = fields->nelts - 1; return field; } @@ -230,15 +202,16 @@ nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) static nxt_str_t * -nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index, - void *ctx) +nxt_var_cache_value(nxt_task_t *task, nxt_tstr_state_t *state, + nxt_var_cache_t *cache, uint32_t index, void *ctx) { nxt_int_t ret; nxt_str_t *value; - nxt_var_decl_t *var; + nxt_var_ref_t *ref; nxt_lvlhsh_query_t lhq; - var = nxt_vars[index >> 16]; + ref = state->var_refs->elts; + ref = &ref[index]; value = cache->spare; @@ -251,7 +224,7 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index, cache->spare = value; } - if (!var->cacheable) { + if (!ref->cacheable) { goto not_cached; } @@ -274,7 +247,7 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index, not_cached: - ret = var->handler(task, value, ctx, index & 0xffff); + ret = ref->handler(task, value, ctx, ref->data); if (nxt_slow_path(ret != NXT_OK)) { return NULL; } @@ -326,7 +299,6 @@ nxt_var_index_init(void) for (i = 0; i < nxt_var_count; i++) { decl = nxt_lvlhsh_each(&nxt_var_hash, &lhe); - decl->index = i; vars[i] = decl; } @@ -337,16 +309,15 @@ nxt_var_index_init(void) nxt_var_t * -nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields) +nxt_var_compile(nxt_tstr_state_t *state, nxt_str_t *str) { - u_char *p, *end, *next, *src; - size_t size; - uint32_t index; - nxt_var_t *var; - nxt_str_t part; - nxt_uint_t n; - nxt_var_sub_t *subs; - nxt_var_decl_t *decl; + u_char *p, *end, *next, *src; + size_t size; + nxt_var_t *var; + nxt_str_t part; + nxt_uint_t n; + nxt_var_sub_t *subs; + nxt_var_ref_t *ref; n = 0; @@ -366,7 +337,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields) size = sizeof(nxt_var_t) + n * sizeof(nxt_var_sub_t) + str->length; - var = nxt_mp_get(mp, size); + var = nxt_mp_get(state->pool, size); if (nxt_slow_path(var == NULL)) { return NULL; } @@ -386,12 +357,12 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields) next = nxt_var_next_part(p, end, &part); if (part.start != NULL) { - decl = nxt_var_decl_get(&part, fields, &index); - if (nxt_slow_path(decl == NULL)) { + ref = nxt_var_ref_get(state, &part); + if (nxt_slow_path(ref == NULL)) { return NULL; } - subs[n].index = index; + subs[n].index = ref->index; subs[n].length = next - p; subs[n].position = p - str->start; @@ -406,11 +377,11 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields) nxt_int_t -nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) +nxt_var_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error) { - u_char *p, *end, *next; - nxt_str_t part; - nxt_var_decl_t *decl; + u_char *p, *end, *next; + nxt_str_t part; + nxt_var_ref_t *ref; p = str->start; end = p + str->length; @@ -426,9 +397,9 @@ nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) } if (part.start != NULL) { - decl = nxt_var_decl_get(&part, fields, NULL); + ref = nxt_var_ref_get(state, &part); - if (decl == NULL) { + if (ref == NULL) { nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "Unknown variable \"%V\"%Z", &part); @@ -514,8 +485,9 @@ nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part) nxt_int_t -nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, nxt_var_t *var, - nxt_str_t *str, void *ctx, nxt_bool_t logging) +nxt_var_interpreter(nxt_task_t *task, nxt_tstr_state_t *state, + nxt_var_cache_t *cache, nxt_var_t *var, nxt_str_t *str, void *ctx, + nxt_bool_t logging) { u_char *p, *src; size_t length, last, next; @@ -532,7 +504,7 @@ nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, nxt_var_t *var, length = var->length; for (i = 0; i < var->vars; i++) { - value = nxt_var_cache_value(task, cache, subs[i].index, ctx); + value = nxt_var_cache_value(task, state, cache, subs[i].index, ctx); if (nxt_slow_path(value == NULL)) { return NXT_ERROR; } -- cgit