static ngx_int_t ngx_http_subs_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_log_t *log; ngx_chain_t *cl, *temp; ngx_http_subs_ctx_t *ctx; ngx_http_subs_loc_conf_t *slcf; log = r->connection->log; slcf = ngx_http_get_module_loc_conf(r, ngx_http_subs_filter_module); if (slcf == NULL) { return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_subs_filter_module); if (ctx == NULL) { return ngx_http_next_body_filter(r, in); } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http subs filter \"%V\"", &r->uri); if (in == NULL && ctx->busy == NULL) { return ngx_http_next_body_filter(r, in); } if (ngx_http_subs_body_filter_init_context(r, in) != NGX_OK){ goto failed; } for (cl = ctx->in; cl; cl = cl->next) { if (cl->buf->last_buf || cl->buf->last_in_chain){ ctx->last = 1; } /* TODO: check the flush flag */ rc = ngx_http_subs_body_filter_process_buffer(r, cl->buf); if (rc == NGX_DECLINED) { continue; } else if (rc == NGX_ERROR) { goto failed; } if (cl->next != NULL) { continue; } if (ctx->last) { /* copy line_in to ctx->out. */ if (ngx_buf_size(ctx->line_in) > 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "[subs_filter] Lost last linefeed, output anyway."); if (ngx_http_subs_out_chain_append(r, ctx, ctx->line_in) != NGX_OK) { goto failed; } } if (ctx->out_buf == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "[subs_filter] The last buffer is zero size."); /* * This is a zero buffer, it should not be set the temporary * or memory flag * */ ctx->out_buf = ngx_calloc_buf(r->pool); if (ctx->out_buf == NULL) { goto failed; } ctx->out_buf->sync = 1; temp = ngx_alloc_chain_link(r->pool); if (temp == NULL) { goto failed; } temp->buf = ctx->out_buf; temp->next = NULL; *ctx->last_out = temp; ctx->last_out = &temp->next; } ctx->out_buf->last_buf = (r == r->main) ? 1 : 0; ctx->out_buf->last_in_chain = cl->buf->last_in_chain; break; } } /* It doesn't output anything, return */ if ((ctx->out == NULL) && (ctx->busy == NULL)) { return NGX_OK; } return ngx_http_subs_output(r, ctx, in); failed: ngx_log_error(NGX_LOG_ERR, log, 0, "[subs_filter] ngx_http_subs_body_filter error."); return NGX_ERROR; }
/* * Do the substitutions from ctx->line_in * and output the chain buffers to ctx->out * */ static ngx_int_t ngx_http_subs_match(ngx_http_request_t *r, ngx_http_subs_ctx_t *ctx) { ngx_buf_t *src, *dst, *temp; ngx_log_t *log; ngx_int_t count, match_count; sub_pair_t *pairs, *pair; ngx_uint_t i; count = 0; match_count = 0; log = r->connection->log; src = ctx->line_in; dst = ctx->line_dst; pairs = (sub_pair_t *) ctx->sub_pairs->elts; for (i = 0; i < ctx->sub_pairs->nelts; i++) { pair = &pairs[i]; if (!pair->has_captured) { if (pair->sub.data == NULL) { if (ngx_http_script_run(r, &pair->sub, pair->sub_lengths->elts, 0, pair->sub_values->elts) == NULL) { goto failed; } } } else { pair->sub.data = NULL; pair->sub.len = 0; } /* exchange the src and dst buffer */ if (dst->pos != dst->last) { temp = src; src = dst; dst = temp; ngx_buffer_init(dst); } if ((!pair->regex) && ((ngx_uint_t)(src->last - src->pos) < pair->match.len)) { continue; } if (pair->once && pair->matched) { continue; } if (pair->sub.data == NULL && !pair->has_captured) { if (ngx_http_script_run(r, &pair->sub, pair->sub_lengths->elts, 0, pair->sub_values->elts) == NULL) { goto failed; } } /* regex substitution */ if (pair->regex || pair->insensitive) { count = ngx_http_subs_match_regex_substituion(r, pair, src, dst); if (count == NGX_ERROR) { goto failed; } } else { /* fixed string substituion */ count = ngx_http_subs_match_fix_substituion(r, pair, src, dst); if (count == NGX_ERROR) { goto failed; } } /* no match. */ if (count == 0){ continue; } if (src->pos < src->last) { if (buffer_append_string(dst, src->pos, src->last - src->pos, r->pool) == NULL) { goto failed; } src->pos = src->last; } /* match */ match_count += count; } /* no match last time */ if (dst->pos == dst->last){ dst = src; } if (ngx_http_subs_out_chain_append(r, ctx, dst) != NGX_OK) { goto failed; } ngx_buffer_init(ctx->line_in); ngx_buffer_init(ctx->line_dst); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "match counts: %i", match_count); return match_count; failed: ngx_log_error(NGX_LOG_ERR, log, 0, "[subs_filter] ngx_http_subs_match error."); return -1; }
static ngx_int_t ngx_http_subs_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_log_t *log; ngx_chain_t *cl, *ll; ngx_http_subs_ctx_t *ctx; ngx_http_subs_loc_conf_t *slcf; ll = NULL; log = r->connection->log; slcf = ngx_http_get_module_loc_conf(r, ngx_http_subs_filter_module); if (slcf == NULL) { return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_subs_filter_module); if (ctx == NULL) { return ngx_http_next_body_filter(r, in); } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http subs filter \"%V\"", &r->uri); if (in == NULL && ctx->busy == NULL) { return ngx_http_next_body_filter(r, in); } if (ngx_http_subs_body_filter_init_context(r, in) != NGX_OK){ goto failed; } for (cl = ctx->in; cl; cl = cl->next) { if (cl->buf->last_buf || cl->buf->last_in_chain){ ctx->last = 1; } /* TODO: check the flush tag */ rc = ngx_http_subs_body_filter_process_buffer(r, cl->buf); if (rc == NGX_DECLINED) { continue; } else if (rc == NGX_ERROR) { goto failed; } if (cl->next != NULL) { continue; } if (ctx->last) { /* copy line_in to ctx->out. */ if (ngx_buf_size(ctx->line_in) > 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "[subs_filter] Lost last linefeed, output anyway."); if (ngx_http_subs_out_chain_append(r, ctx, ctx->line_in) != NGX_OK) { goto failed; } } if (ctx->out_buf == NULL) { if (ngx_http_subs_get_chain_buf(r, ctx) != NGX_OK) { goto failed; } } ctx->out_buf->sync = 1; ctx->out_buf->last_buf = (r == r->main) ? 1 : 0; ctx->out_buf->last_in_chain = cl->buf->last_in_chain; break; } } /* It doesn't output anything, return */ if ((ctx->last_out == &ctx->out) && (ctx->busy == NULL)) { return NGX_OK; } ngx_http_subs_body_filter_clean_context(r, ctx); return ngx_http_subs_output(r, ctx, in); failed: ngx_http_subs_body_filter_clean_context(r, ctx); ngx_log_error(NGX_LOG_ERR, log, 0, "[subs_filter] ngx_http_subs_body_filter error."); return NGX_ERROR; }