[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