details: http://hg.nginx.org/nginx/rev/b9447fc457b4 branches: changeset: 6228:b9447fc457b4 user: Dmitry Volyntsev <xei...@nginx.com> date: Mon Aug 17 17:42:02 2015 +0300 description: Sub filter: support of multiple strings to replace.
diffstat: src/http/modules/ngx_http_sub_filter_module.c | 433 +++++++++++++++---------- 1 files changed, 257 insertions(+), 176 deletions(-) diffs (truncated from 638 to 300 lines): diff -r bd55d75a1410 -r b9447fc457b4 src/http/modules/ngx_http_sub_filter_module.c --- a/src/http/modules/ngx_http_sub_filter_module.c Sun Aug 16 10:51:34 2015 +0300 +++ b/src/http/modules/ngx_http_sub_filter_module.c Mon Aug 17 17:42:02 2015 +0300 @@ -13,6 +13,20 @@ typedef struct { ngx_str_t match; ngx_http_complex_value_t value; +} ngx_http_sub_match_t; + + +typedef struct { + ngx_uint_t min_match_len; + ngx_uint_t max_match_len; + + u_char index[257]; + u_char shift[256]; +} ngx_http_sub_tables_t; + + +typedef struct { + ngx_http_sub_tables_t *tables; ngx_hash_t types; @@ -20,17 +34,11 @@ typedef struct { ngx_flag_t last_modified; ngx_array_t *types_keys; + ngx_array_t *matches; } ngx_http_sub_loc_conf_t; -typedef enum { - sub_start_state = 0, - sub_match_state, -} ngx_http_sub_state_e; - - typedef struct { - ngx_str_t match; ngx_str_t saved; ngx_str_t looked; @@ -48,12 +56,17 @@ typedef struct { ngx_chain_t *busy; ngx_chain_t *free; - ngx_str_t sub; + ngx_str_t *sub; + ngx_uint_t applied; - ngx_uint_t state; + ngx_int_t offset; + ngx_uint_t index; } ngx_http_sub_ctx_t; +static ngx_uint_t ngx_http_sub_cmp_index; + + static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx); static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, @@ -64,6 +77,9 @@ static char * ngx_http_sub_filter(ngx_co static void *ngx_http_sub_create_conf(ngx_conf_t *cf); static char *ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child); +static void ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables, + ngx_http_sub_match_t *match, ngx_uint_t n); +static ngx_int_t ngx_http_sub_cmp_matches(const void *one, const void *two); static ngx_int_t ngx_http_sub_filter_init(ngx_conf_t *cf); @@ -144,7 +160,7 @@ ngx_http_sub_header_filter(ngx_http_requ slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - if (slcf->match.len == 0 + if (slcf->matches == NULL || r->headers_out.content_length_n == 0 || ngx_http_test_content_type(r, &slcf->types) == NULL) { @@ -156,19 +172,19 @@ ngx_http_sub_header_filter(ngx_http_requ return NGX_ERROR; } - ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len); + ctx->saved.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1); if (ctx->saved.data == NULL) { return NGX_ERROR; } - ctx->looked.data = ngx_pnalloc(r->pool, slcf->match.len); + ctx->looked.data = ngx_pnalloc(r->pool, slcf->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->match = slcf->match; + ctx->offset = slcf->tables->min_match_len - 1; ctx->last_out = &ctx->out; r->filter_need_in_memory = 1; @@ -194,8 +210,10 @@ ngx_http_sub_body_filter(ngx_http_reques { ngx_int_t rc; ngx_buf_t *b; + ngx_str_t *sub; ngx_chain_t *cl; ngx_http_sub_ctx_t *ctx; + ngx_http_sub_match_t *match; ngx_http_sub_loc_conf_t *slcf; ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module); @@ -242,18 +260,10 @@ ngx_http_sub_body_filter(ngx_http_reques ctx->pos = ctx->buf->pos; } - if (ctx->state == sub_start_state) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->pos; - } - b = NULL; while (ctx->pos < ctx->buf->last) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "saved: \"%V\" state: %d", &ctx->saved, ctx->state); - rc = ngx_http_sub_parse(r, ctx); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -320,20 +330,6 @@ ngx_http_sub_body_filter(ngx_http_reques ctx->last_out = &cl->next; } - if (ctx->state == sub_start_state) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->pos; - - } else { - ctx->copy_start = NULL; - ctx->copy_end = NULL; - } - - if (ctx->looked.len > (size_t) (ctx->pos - ctx->buf->pos)) { - ctx->saved.len = ctx->looked.len - (ctx->pos - ctx->buf->pos); - ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len); - } - if (rc == NGX_AGAIN) { continue; } @@ -352,19 +348,30 @@ ngx_http_sub_body_filter(ngx_http_reques slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - if (ctx->sub.data == NULL) { + if (ctx->sub == NULL) { + ctx->sub = ngx_pcalloc(r->pool, sizeof(ngx_str_t) + * slcf->matches->nelts); + if (ctx->sub == NULL) { + return NGX_ERROR; + } + } - if (ngx_http_complex_value(r, &slcf->value, &ctx->sub) + sub = &ctx->sub[ctx->index]; + + if (sub->data == NULL) { + match = slcf->matches->elts; + + if (ngx_http_complex_value(r, &match[ctx->index].value, sub) != NGX_OK) { return NGX_ERROR; } } - if (ctx->sub.len) { + if (sub->len) { b->memory = 1; - b->pos = ctx->sub.data; - b->last = ctx->sub.data + ctx->sub.len; + b->pos = sub->data; + b->last = sub->data + sub->len; } else { b->sync = 1; @@ -373,7 +380,8 @@ ngx_http_sub_body_filter(ngx_http_reques *ctx->last_out = cl; ctx->last_out = &cl->next; - ctx->once = slcf->once; + ctx->index = 0; + ctx->once = slcf->once && (++ctx->applied == slcf->matches->nelts); continue; } @@ -428,9 +436,6 @@ ngx_http_sub_body_filter(ngx_http_reques } ctx->buf = NULL; - - ctx->saved.len = ctx->looked.len; - ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len); } if (ctx->out == NULL && ctx->busy == NULL) { @@ -513,158 +518,142 @@ ngx_http_sub_output(ngx_http_request_t * static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) { - u_char *p, *last, *copy_end, ch, match; - size_t looked, i; - ngx_http_sub_state_e state; + u_char *p, *last, *pat, *pat_end, c; + ngx_str_t *m; + ngx_int_t offset, start, next, end, len, rc; + ngx_uint_t shift, i, j; + ngx_http_sub_match_t *match; + ngx_http_sub_tables_t *tables; + ngx_http_sub_loc_conf_t *slcf; + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); + tables = slcf->tables; + + offset = ctx->offset; + end = ctx->buf->last - ctx->pos; if (ctx->once) { - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->buf->last; - ctx->pos = ctx->buf->last; - ctx->looked.len = 0; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once"); - - return NGX_AGAIN; + /* sets start and next to end */ + offset = end + (ngx_int_t) tables->min_match_len - 1; + goto again; } - state = ctx->state; - looked = ctx->looked.len; - last = ctx->buf->last; - copy_end = ctx->copy_end; + while (offset < end) { - for (p = ctx->pos; p < last; p++) { + c = offset < 0 ? ctx->looked.data[ctx->looked.len + offset] + : ctx->pos[offset]; - ch = *p; - ch = ngx_tolower(ch); + c = ngx_tolower(c); - if (state == sub_start_state) { - - /* the tight loop */ - - match = ctx->match.data[0]; - - for ( ;; ) { - if (ch == match) { - - if (ctx->match.len == 1) { - ctx->pos = p + 1; - ctx->copy_end = p; - - return NGX_OK; - } - - copy_end = p; - ctx->looked.data[0] = *p; - looked = 1; - state = sub_match_state; - - goto match_started; - } - - if (++p == last) { - break; - } - - ch = *p; - ch = ngx_tolower(ch); - } - - ctx->state = state; - ctx->pos = p; - ctx->looked.len = looked; - ctx->copy_end = p; - - if (ctx->copy_start == NULL) { - ctx->copy_start = ctx->buf->pos; _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel