[nginx] Sub filter: support of variables in the strings to replace.
Dmitry Volyntsev
xeioex at nginx.com
Mon Aug 17 14:44:23 UTC 2015
details: http://hg.nginx.org/nginx/rev/2c045e5b8291
branches:
changeset: 6229:2c045e5b8291
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Mon Aug 17 17:42:02 2015 +0300
description:
Sub filter: support of variables in the strings to replace.
diffstat:
src/http/modules/ngx_http_sub_filter_module.c | 174 +++++++++++++++++++++----
1 files changed, 146 insertions(+), 28 deletions(-)
diffs (truncated from 318 to 300 lines):
diff -r b9447fc457b4 -r 2c045e5b8291 src/http/modules/ngx_http_sub_filter_module.c
--- a/src/http/modules/ngx_http_sub_filter_module.c Mon Aug 17 17:42:02 2015 +0300
+++ b/src/http/modules/ngx_http_sub_filter_module.c Mon Aug 17 17:42:02 2015 +0300
@@ -11,8 +11,14 @@
typedef struct {
+ ngx_http_complex_value_t match;
+ ngx_http_complex_value_t value;
+} ngx_http_sub_pair_t;
+
+
+typedef struct {
ngx_str_t match;
- ngx_http_complex_value_t value;
+ ngx_http_complex_value_t *value;
} ngx_http_sub_match_t;
@@ -26,6 +32,10 @@ typedef struct {
typedef struct {
+ ngx_uint_t dynamic; /* unsigned dynamic:1; */
+
+ ngx_array_t *pairs;
+
ngx_http_sub_tables_t *tables;
ngx_hash_t types;
@@ -61,6 +71,9 @@ typedef struct {
ngx_int_t offset;
ngx_uint_t index;
+
+ ngx_http_sub_tables_t *tables;
+ ngx_array_t *matches;
} ngx_http_sub_ctx_t;
@@ -155,12 +168,16 @@ static ngx_http_output_body_filter_pt
static ngx_int_t
ngx_http_sub_header_filter(ngx_http_request_t *r)
{
- ngx_http_sub_ctx_t *ctx;
+ ngx_str_t *m;
+ ngx_uint_t i, j, n;
+ ngx_http_sub_ctx_t *ctx;
+ ngx_http_sub_pair_t *pairs;
+ ngx_http_sub_match_t *matches;
ngx_http_sub_loc_conf_t *slcf;
slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
- if (slcf->matches == NULL
+ if (slcf->pairs == NULL
|| r->headers_out.content_length_n == 0
|| ngx_http_test_content_type(r, &slcf->types) == NULL)
{
@@ -172,19 +189,76 @@ ngx_http_sub_header_filter(ngx_http_requ
return NGX_ERROR;
}
- ctx->saved.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1);
+ if (slcf->dynamic == 0) {
+ ctx->tables = slcf->tables;
+ ctx->matches = slcf->matches;
+
+ } else {
+ pairs = slcf->pairs->elts;
+ n = slcf->pairs->nelts;
+
+ matches = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_match_t) * n);
+ if (matches == NULL) {
+ return NGX_ERROR;
+ }
+
+ j = 0;
+ for (i = 0; i < n; i++) {
+ matches[j].value = &pairs[i].value;
+
+ if (pairs[i].match.lengths == NULL) {
+ matches[j].match = pairs[i].match.value;
+ j++;
+ continue;
+ }
+
+ m = &matches[j].match;
+ if (ngx_http_complex_value(r, &pairs[i].match, m) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (m->len == 0) {
+ continue;
+ }
+
+ ngx_strlow(m->data, m->data, m->len);
+ j++;
+ }
+
+ if (j == 0) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ ctx->matches = ngx_pnalloc(r->pool, sizeof(ngx_array_t));
+ if (ctx->matches == NULL) {
+ return NGX_ERROR;
+ }
+
+ ctx->matches->elts = matches;
+ ctx->matches->nelts = j;
+
+ ctx->tables = ngx_pnalloc(r->pool, sizeof(ngx_http_sub_tables_t));
+ if (ctx->tables == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_sub_init_tables(ctx->tables, ctx->matches->elts,
+ ctx->matches->nelts);
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module);
+
+ ctx->saved.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1);
if (ctx->saved.data == NULL) {
return NGX_ERROR;
}
- ctx->looked.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1);
+ ctx->looked.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1);
if (ctx->looked.data == NULL) {
return NGX_ERROR;
}
- ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module);
-
- ctx->offset = slcf->tables->min_match_len - 1;
+ ctx->offset = ctx->tables->min_match_len - 1;
ctx->last_out = &ctx->out;
r->filter_need_in_memory = 1;
@@ -350,7 +424,7 @@ ngx_http_sub_body_filter(ngx_http_reques
if (ctx->sub == NULL) {
ctx->sub = ngx_pcalloc(r->pool, sizeof(ngx_str_t)
- * slcf->matches->nelts);
+ * ctx->matches->nelts);
if (ctx->sub == NULL) {
return NGX_ERROR;
}
@@ -359,9 +433,9 @@ ngx_http_sub_body_filter(ngx_http_reques
sub = &ctx->sub[ctx->index];
if (sub->data == NULL) {
- match = slcf->matches->elts;
+ match = ctx->matches->elts;
- if (ngx_http_complex_value(r, &match[ctx->index].value, sub)
+ if (ngx_http_complex_value(r, match[ctx->index].value, sub)
!= NGX_OK)
{
return NGX_ERROR;
@@ -381,7 +455,7 @@ ngx_http_sub_body_filter(ngx_http_reques
ctx->last_out = &cl->next;
ctx->index = 0;
- ctx->once = slcf->once && (++ctx->applied == slcf->matches->nelts);
+ ctx->once = slcf->once && (++ctx->applied == ctx->matches->nelts);
continue;
}
@@ -527,7 +601,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
ngx_http_sub_loc_conf_t *slcf;
slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
- tables = slcf->tables;
+ tables = ctx->tables;
offset = ctx->offset;
end = ctx->buf->last - ctx->pos;
@@ -554,7 +628,7 @@ ngx_http_sub_parse(ngx_http_request_t *r
/* a potential match */
start = offset - (ngx_int_t) tables->min_match_len + 1;
- match = slcf->matches->elts;
+ match = ctx->matches->elts;
i = ngx_max(tables->index[c], ctx->index);
j = tables->index[c + 1];
@@ -663,7 +737,7 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_
ngx_http_sub_loc_conf_t *slcf = conf;
ngx_str_t *value;
- ngx_http_sub_match_t *match;
+ ngx_http_sub_pair_t *pair;
ngx_http_compile_complex_value_t ccv;
value = cf->args->elts;
@@ -673,15 +747,15 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_
return NGX_CONF_ERROR;
}
- if (slcf->matches == NULL) {
- slcf->matches = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_sub_match_t));
- if (slcf->matches == NULL) {
+ if (slcf->pairs == NULL) {
+ slcf->pairs = ngx_array_create(cf->pool, 1,
+ sizeof(ngx_http_sub_pair_t));
+ if (slcf->pairs == NULL) {
return NGX_CONF_ERROR;
}
}
- if (slcf->matches->nelts == 255) {
+ if (slcf->pairs->nelts == 255) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"number of search patterns exceeds 255");
return NGX_CONF_ERROR;
@@ -689,18 +763,34 @@ ngx_http_sub_filter(ngx_conf_t *cf, ngx_
ngx_strlow(value[1].data, value[1].data, value[1].len);
- match = ngx_array_push(slcf->matches);
- if (match == NULL) {
+ pair = ngx_array_push(slcf->pairs);
+ if (pair == NULL) {
return NGX_CONF_ERROR;
}
- match->match = value[1];
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[1];
+ ccv.complex_value = &pair->match;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (ccv.complex_value->lengths != NULL) {
+ slcf->dynamic = 1;
+
+ } else {
+ ngx_strlow(pair->match.value.data, pair->match.value.data,
+ pair->match.value.len);
+ }
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
ccv.cf = cf;
ccv.value = &value[2];
- ccv.complex_value = &match->value;
+ ccv.complex_value = &pair->value;
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR;
@@ -723,6 +813,8 @@ ngx_http_sub_create_conf(ngx_conf_t *cf)
/*
* set by ngx_pcalloc():
*
+ * conf->dynamic = 0;
+ * conf->pairs = NULL;
* conf->tables = NULL;
* conf->types = { NULL };
* conf->types_keys = NULL;
@@ -739,8 +831,11 @@ ngx_http_sub_create_conf(ngx_conf_t *cf)
static char *
ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
- ngx_http_sub_loc_conf_t *prev = parent;
- ngx_http_sub_loc_conf_t *conf = child;
+ ngx_uint_t i, n;
+ ngx_http_sub_pair_t *pairs;
+ ngx_http_sub_match_t *matches;
+ ngx_http_sub_loc_conf_t *prev = parent;
+ ngx_http_sub_loc_conf_t *conf = child;
ngx_conf_merge_value(conf->once, prev->once, 1);
ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0);
@@ -753,11 +848,34 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf,
return NGX_CONF_ERROR;
}
- if (conf->matches == NULL) {
+ if (conf->pairs == NULL) {
+ conf->dynamic = prev->dynamic;
+ conf->pairs = prev->pairs;
conf->matches = prev->matches;
conf->tables = prev->tables;
- } else {
+ } else if (conf->dynamic == 0){
+ pairs = conf->pairs->elts;
+ n = conf->pairs->nelts;
+
+ matches = ngx_pnalloc(cf->pool, sizeof(ngx_http_sub_match_t) * n);
+ if (matches == NULL) {
+ return NGX_CONF_ERROR;
More information about the nginx-devel
mailing list