4
#include "ngx_http_echo_filter.h"
5
#include "ngx_http_echo_util.h"
6
#include "ngx_http_echo_echo.h"
10
ngx_flag_t ngx_http_echo_filter_used = 0;
12
ngx_http_output_header_filter_pt ngx_http_echo_next_header_filter;
14
ngx_http_output_body_filter_pt ngx_http_echo_next_body_filter;
16
static ngx_int_t ngx_http_echo_header_filter(ngx_http_request_t *r);
18
static ngx_int_t ngx_http_echo_body_filter(ngx_http_request_t *r, ngx_chain_t *in);
21
static ngx_int_t ngx_http_echo_exec_filter_cmds(ngx_http_request_t *r,
22
ngx_http_echo_ctx_t *ctx, ngx_array_t *cmds, ngx_uint_t *iterator);
26
ngx_http_echo_filter_init (ngx_conf_t *cf)
28
if (ngx_http_echo_filter_used) {
29
dd("top header filter: %ld", (unsigned long) ngx_http_top_header_filter);
30
ngx_http_echo_next_header_filter = ngx_http_top_header_filter;
31
ngx_http_top_header_filter = ngx_http_echo_header_filter;
33
dd("top body filter: %ld", (unsigned long) ngx_http_top_body_filter);
34
ngx_http_echo_next_body_filter = ngx_http_top_body_filter;
35
ngx_http_top_body_filter = ngx_http_echo_body_filter;
43
ngx_http_echo_header_filter(ngx_http_request_t *r)
45
ngx_http_echo_loc_conf_t *conf;
46
ngx_http_echo_ctx_t *ctx;
49
dd("We're in the header filter...");
51
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
53
/* XXX we should add option to insert contents for responses
54
* of non-200 status code here... */
56
if (r->headers_out.status != NGX_HTTP_OK) {
60
return ngx_http_echo_next_header_filter(r);
64
conf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
65
if (conf->before_body_cmds == NULL && conf->after_body_cmds == NULL) {
69
return ngx_http_echo_next_header_filter(r);
73
rc = ngx_http_echo_init_ctx(r, &ctx);
77
ctx->headers_sent = 1;
78
ngx_http_set_ctx(r, ctx, ngx_http_echo_module);
81
/* enable streaming here (use chunked encoding) */
82
ngx_http_clear_content_length(r);
83
ngx_http_clear_accept_ranges(r);
85
return ngx_http_echo_next_header_filter(r);
90
ngx_http_echo_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
92
ngx_http_echo_ctx_t *ctx;
94
ngx_http_echo_loc_conf_t *conf;
99
if (in == NULL || r->header_only) {
100
return ngx_http_echo_next_body_filter(r, in);
103
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
105
if (ctx == NULL || ctx->skip_filter) {
106
return ngx_http_echo_next_body_filter(r, in);
109
conf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
111
if (!ctx->before_body_sent) {
112
ctx->before_body_sent = 1;
114
if (conf->before_body_cmds != NULL) {
115
rc = ngx_http_echo_exec_filter_cmds(r, ctx, conf->before_body_cmds,
116
&ctx->next_before_body_cmd);
123
if (conf->after_body_cmds == NULL) {
124
ctx->skip_filter = 1;
125
return ngx_http_echo_next_body_filter(r, in);
130
for (cl = in; cl; cl = cl->next) {
131
if (cl->buf->last_buf) {
132
cl->buf->last_buf = 0;
135
} else if (r != r->main && cl->buf->sync) {
136
dd("Found sync buf");
141
rc = ngx_http_echo_next_body_filter(r, in);
143
if (rc == NGX_ERROR || !last) {
147
dd("exec filter cmds for after body cmds");
148
rc = ngx_http_echo_exec_filter_cmds(r, ctx, conf->after_body_cmds, &ctx->next_after_body_cmd);
150
dd("FAILED: exec filter cmds for after body cmds");
154
ctx->skip_filter = 1;
156
dd("after body cmds executed...terminating...");
158
/* XXX we can NOT use
159
* ngx_http_send_special(r, NGX_HTTP_LAST) here
160
* because we should bypass the upstream filters. */
165
buf = ngx_calloc_buf(r->pool);
168
cl = ngx_alloc_chain_link(r->pool);
170
return NGX_HTTP_INTERNAL_SERVER_ERROR;
176
return ngx_http_echo_next_body_filter(r, cl);
181
ngx_http_echo_exec_filter_cmds(ngx_http_request_t *r,
182
ngx_http_echo_ctx_t *ctx, ngx_array_t *cmds,
183
ngx_uint_t *iterator)
186
ngx_array_t *computed_args = NULL;
187
ngx_http_echo_cmd_t *cmd;
188
ngx_http_echo_cmd_t *cmd_elts;
189
ngx_array_t *opts = NULL;
191
for (cmd_elts = cmds->elts; *iterator < cmds->nelts; (*iterator)++) {
192
cmd = &cmd_elts[*iterator];
194
/* evaluate arguments for the current cmd (if any) */
196
computed_args = ngx_array_create(r->pool, cmd->args->nelts,
199
if (computed_args == NULL) {
200
return NGX_HTTP_INTERNAL_SERVER_ERROR;
203
opts = ngx_array_create(r->pool, 1, sizeof(ngx_str_t));
206
return NGX_HTTP_INTERNAL_SERVER_ERROR;
209
rc = ngx_http_echo_eval_cmd_args(r, cmd, computed_args, opts);
212
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
213
"Failed to evaluate arguments for "
219
/* do command dispatch based on the opcode */
220
switch (cmd->opcode) {
221
case echo_opcode_echo_before_body:
222
case echo_opcode_echo_after_body:
223
dd("exec echo_before_body or echo_after_body...");
225
rc = ngx_http_echo_exec_echo(r, ctx, computed_args,
226
1 /* in filter */, opts);