1
2 /*
3 * Copyright (C) Yichun Zhang (agentzh)
4 */
5
6
7 #ifndef DDEBUG
8 #define DDEBUG 0
9 #endif
10 #include "ddebug.h"
11
12
13 #include "ngx_http_echo_handler.h"
14 #include "ngx_http_echo_filter.h"
15 #include "ngx_http_echo_echo.h"
16 #include "ngx_http_echo_request_info.h"
17 #include "ngx_http_echo_var.h"
18 #include "ngx_http_echo_util.h"
19
20
21 #include <nginx.h>
22 #include <ngx_config.h>
23 #include <ngx_log.h>
24
25
26 /* config init handler */
27 static void *ngx_http_echo_create_loc_conf(ngx_conf_t *cf);
28 static char *ngx_http_echo_merge_loc_conf(ngx_conf_t *cf, void *parent,
29 void *child);
30 static void *ngx_http_echo_create_main_conf(ngx_conf_t *cf);
31 static ngx_int_t ngx_http_echo_post_config(ngx_conf_t *cf);
32
33 /* config directive handlers */
34 static char *ngx_http_echo_echo(ngx_conf_t *cf, ngx_command_t *cmd,
35 void *conf);
36 static char *ngx_http_echo_echo_request_body(ngx_conf_t *cf,
37 ngx_command_t *cmd, void *conf);
38 static char *ngx_http_echo_echo_sleep(ngx_conf_t *cf, ngx_command_t *cmd,
39 void *conf);
40 static char *ngx_http_echo_echo_flush(ngx_conf_t *cf, ngx_command_t *cmd,
41 void *conf);
42 static char *ngx_http_echo_echo_blocking_sleep(ngx_conf_t *cf,
43 ngx_command_t *cmd, void *conf);
44 static char *ngx_http_echo_echo_reset_timer(ngx_conf_t *cf,
45 ngx_command_t *cmd, void *conf);
46 static char *ngx_http_echo_echo_before_body(ngx_conf_t *cf,
47 ngx_command_t *cmd, void *conf);
48 static char *ngx_http_echo_echo_after_body(ngx_conf_t *cf,
49 ngx_command_t *cmd, void *conf);
50 static char *ngx_http_echo_echo_location_async(ngx_conf_t *cf,
51 ngx_command_t *cmd, void *conf);
52 static char *ngx_http_echo_echo_location(ngx_conf_t *cf,
53 ngx_command_t *cmd, void *conf);
54 static char *ngx_http_echo_echo_subrequest_async(ngx_conf_t *cf,
55 ngx_command_t *cmd, void *conf);
56 static char *ngx_http_echo_echo_subrequest(ngx_conf_t *cf,
57 ngx_command_t *cmd, void *conf);
58 static char *ngx_http_echo_echo_duplicate(ngx_conf_t *cf,
59 ngx_command_t *cmd, void *conf);
60 static char *ngx_http_echo_echo_read_request_body(ngx_conf_t *cf,
61 ngx_command_t *cmd, void *conf);
62 static char *ngx_http_echo_echo_foreach_split(ngx_conf_t *cf,
63 ngx_command_t *cmd, void *conf);
64 static char *ngx_http_echo_echo_end(ngx_conf_t *cf,
65 ngx_command_t *cmd, void *conf);
66 static char *ngx_http_echo_echo_abort_parent(ngx_conf_t *cf,
67 ngx_command_t *cmd, void *conf);
68 static char *ngx_http_echo_echo_exec(ngx_conf_t *cf,
69 ngx_command_t *cmd, void *conf);
70 static char *ngx_http_echo_helper(ngx_http_echo_opcode_t opcode,
71 ngx_http_echo_cmd_category_t cat,
72 ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
73
74
75 static ngx_http_module_t ngx_http_echo_module_ctx = {
76 NULL, /* preconfiguration */
77 ngx_http_echo_post_config, /* postconfiguration */
78
79 ngx_http_echo_create_main_conf, /* create main configuration */
80 NULL, /* init main configuration */
81
82 NULL, /* create server configuration */
83 NULL, /* merge server configuration */
84
85 ngx_http_echo_create_loc_conf, /* create location configuration */
86 ngx_http_echo_merge_loc_conf /* merge location configuration */
87 };
88
89
90 static ngx_command_t ngx_http_echo_commands[] = {
91
92 { ngx_string("echo"),
93 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY,
94 ngx_http_echo_echo,
95 NGX_HTTP_LOC_CONF_OFFSET,
96 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
97 NULL },
98
99 { ngx_string("echo_request_body"),
100 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
101 ngx_http_echo_echo_request_body,
102 NGX_HTTP_LOC_CONF_OFFSET,
103 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
104 NULL },
105
106 { ngx_string("echo_sleep"),
107 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
108 ngx_http_echo_echo_sleep,
109 NGX_HTTP_LOC_CONF_OFFSET,
110 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
111 NULL },
112
113 { ngx_string("echo_flush"),
114 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
115 ngx_http_echo_echo_flush,
116 NGX_HTTP_LOC_CONF_OFFSET,
117 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
118 NULL },
119
120 { ngx_string("echo_blocking_sleep"),
121 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
122 ngx_http_echo_echo_blocking_sleep,
123 NGX_HTTP_LOC_CONF_OFFSET,
124 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
125 NULL },
126
127 { ngx_string("echo_reset_timer"),
128 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
129 ngx_http_echo_echo_reset_timer,
130 NGX_HTTP_LOC_CONF_OFFSET,
131 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
132 NULL },
133
134 { ngx_string("echo_before_body"),
135 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY,
136 ngx_http_echo_echo_before_body,
137 NGX_HTTP_LOC_CONF_OFFSET,
138 offsetof(ngx_http_echo_loc_conf_t, before_body_cmds),
139 NULL },
140
141 { ngx_string("echo_after_body"),
142 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY,
143 ngx_http_echo_echo_after_body,
144 NGX_HTTP_LOC_CONF_OFFSET,
145 offsetof(ngx_http_echo_loc_conf_t, after_body_cmds),
146 NULL },
147
148 { ngx_string("echo_location_async"),
149 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12,
150 ngx_http_echo_echo_location_async,
151 NGX_HTTP_LOC_CONF_OFFSET,
152 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
153 NULL },
154
155 { ngx_string("echo_location"),
156 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12,
157 ngx_http_echo_echo_location,
158 NGX_HTTP_LOC_CONF_OFFSET,
159 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
160 NULL },
161
162 { ngx_string("echo_subrequest_async"),
163 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
164 ngx_http_echo_echo_subrequest_async,
165 NGX_HTTP_LOC_CONF_OFFSET,
166 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
167 NULL },
168
169 { ngx_string("echo_subrequest"),
170 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
171 ngx_http_echo_echo_subrequest,
172 NGX_HTTP_LOC_CONF_OFFSET,
173 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
174 NULL },
175
176 { ngx_string("echo_duplicate"),
177 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
178 ngx_http_echo_echo_duplicate,
179 NGX_HTTP_LOC_CONF_OFFSET,
180 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
181 NULL },
182
183 { ngx_string("echo_read_request_body"),
184 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
185 ngx_http_echo_echo_read_request_body,
186 NGX_HTTP_LOC_CONF_OFFSET,
187 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
188 NULL },
189
190 { ngx_string("echo_foreach_split"),
191 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
192 ngx_http_echo_echo_foreach_split,
193 NGX_HTTP_LOC_CONF_OFFSET,
194 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
195 NULL },
196
197 { ngx_string("echo_end"),
198 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
199 ngx_http_echo_echo_end,
200 NGX_HTTP_LOC_CONF_OFFSET,
201 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
202 NULL },
203
204 { ngx_string("echo_abort_parent"),
205 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
206 ngx_http_echo_echo_abort_parent,
207 NGX_HTTP_LOC_CONF_OFFSET,
208 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
209 NULL },
210
211 { ngx_string("echo_exec"),
212 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12,
213 ngx_http_echo_echo_exec,
214 NGX_HTTP_LOC_CONF_OFFSET,
215 offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
216 NULL },
217
218 { ngx_string("echo_status"),
219 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
220 ngx_conf_set_num_slot,
221 NGX_HTTP_LOC_CONF_OFFSET,
222 offsetof(ngx_http_echo_loc_conf_t, status),
223 NULL },
224
225 ngx_null_command
226 };
227
228
229 ngx_module_t ngx_http_echo_module = {
230 NGX_MODULE_V1,
231 &ngx_http_echo_module_ctx, /* module context */
232 ngx_http_echo_commands, /* module directives */
233 NGX_HTTP_MODULE, /* module type */
234 NULL, /* init master */
235 NULL, /* init module */
236 NULL, /* init process */
237 NULL, /* init thread */
238 NULL, /* exit thread */
239 NULL, /* exit process */
240 NULL, /* exit master */
241 NGX_MODULE_V1_PADDING
242 };
243
244
245 static void *
ngx_http_echo_create_loc_conf(ngx_conf_t * cf)246 ngx_http_echo_create_loc_conf(ngx_conf_t *cf)
247 {
248 ngx_http_echo_loc_conf_t *conf;
249
250 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_loc_conf_t));
251 if (conf == NULL) {
252 return NULL;
253 }
254
255 /* set by ngx_pcalloc
256 * conf->handler_cmds = NULL
257 * conf->before_body_cmds = NULL
258 * conf->after_body_cmds = NULL
259 * conf->seen_leading_output = 0
260 * conf->seen_trailing_output = 0
261 */
262
263 conf->status = NGX_CONF_UNSET;
264
265 return conf;
266 }
267
268
269 static char *
ngx_http_echo_merge_loc_conf(ngx_conf_t * cf,void * parent,void * child)270 ngx_http_echo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
271 {
272 ngx_http_echo_loc_conf_t *prev = parent;
273 ngx_http_echo_loc_conf_t *conf = child;
274
275 if (conf->handler_cmds == NULL) {
276 conf->handler_cmds = prev->handler_cmds;
277 conf->seen_leading_output = prev->seen_leading_output;
278 }
279
280 if (conf->before_body_cmds == NULL) {
281 conf->before_body_cmds = prev->before_body_cmds;
282 }
283
284 if (conf->after_body_cmds == NULL) {
285 conf->after_body_cmds = prev->after_body_cmds;
286 }
287
288 ngx_conf_merge_value(conf->status, prev->status, 200);
289
290 return NGX_CONF_OK;
291 }
292
293
294 static char *
ngx_http_echo_helper(ngx_http_echo_opcode_t opcode,ngx_http_echo_cmd_category_t cat,ngx_conf_t * cf,ngx_command_t * cmd,void * conf)295 ngx_http_echo_helper(ngx_http_echo_opcode_t opcode,
296 ngx_http_echo_cmd_category_t cat,
297 ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
298 {
299 ngx_str_t *raw_args;
300 ngx_uint_t i, n;
301 ngx_array_t **args_ptr;
302 ngx_array_t **cmds_ptr;
303 ngx_http_echo_cmd_t *echo_cmd;
304 ngx_http_core_loc_conf_t *clcf;
305 ngx_http_script_compile_t sc;
306 ngx_http_echo_main_conf_t *emcf;
307 ngx_http_echo_arg_template_t *arg;
308
309 emcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_echo_module);
310
311 /* cmds_ptr points to ngx_http_echo_loc_conf_t's
312 * handler_cmds, before_body_cmds, or after_body_cmds
313 * array, depending on the actual offset */
314 cmds_ptr = (ngx_array_t **) (((u_char *) conf) + cmd->offset);
315
316 if (*cmds_ptr == NULL) {
317 *cmds_ptr = ngx_array_create(cf->pool, 1,
318 sizeof(ngx_http_echo_cmd_t));
319
320 if (*cmds_ptr == NULL) {
321 return NGX_CONF_ERROR;
322 }
323
324 if (cat == echo_handler_cmd) {
325 dd("registering the content handler");
326 /* register the content handler */
327 clcf = ngx_http_conf_get_module_loc_conf(cf,
328 ngx_http_core_module);
329
330 dd("registering the content handler (2)");
331 clcf->handler = ngx_http_echo_handler;
332
333 } else {
334 dd("filter used = 1");
335 emcf->requires_filter = 1;
336 }
337 }
338
339 echo_cmd = ngx_array_push(*cmds_ptr);
340
341 if (echo_cmd == NULL) {
342 return NGX_CONF_ERROR;
343 }
344
345 echo_cmd->opcode = opcode;
346
347 args_ptr = &echo_cmd->args;
348 *args_ptr = ngx_array_create(cf->pool, 1,
349 sizeof(ngx_http_echo_arg_template_t));
350
351 if (*args_ptr == NULL) {
352 return NGX_CONF_ERROR;
353 }
354
355 raw_args = cf->args->elts;
356
357 /* we skip the first arg and start from the second */
358
359 for (i = 1 ; i < cf->args->nelts; i++) {
360 arg = ngx_array_push(*args_ptr);
361
362 if (arg == NULL) {
363 return NGX_CONF_ERROR;
364 }
365
366 arg->raw_value = raw_args[i];
367
368 dd("found raw arg %s", raw_args[i].data);
369
370 arg->lengths = NULL;
371 arg->values = NULL;
372
373 n = ngx_http_script_variables_count(&arg->raw_value);
374
375 if (n > 0) {
376 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
377
378 sc.cf = cf;
379 sc.source = &arg->raw_value;
380 sc.lengths = &arg->lengths;
381 sc.values = &arg->values;
382 sc.variables = n;
383 sc.complete_lengths = 1;
384 sc.complete_values = 1;
385
386 if (ngx_http_script_compile(&sc) != NGX_OK) {
387 return NGX_CONF_ERROR;
388 }
389 }
390 } /* end for */
391
392 return NGX_CONF_OK;
393 }
394
395
396 static char *
ngx_http_echo_echo(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)397 ngx_http_echo_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
398 {
399 ngx_http_echo_loc_conf_t *elcf = conf;
400
401 if (!elcf->seen_leading_output) {
402 elcf->seen_leading_output = 1;
403 }
404
405 dd("in echo_echo...");
406 return ngx_http_echo_helper(echo_opcode_echo, echo_handler_cmd,
407 cf, cmd, conf);
408 }
409
410
411 static char *
ngx_http_echo_echo_request_body(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)412 ngx_http_echo_echo_request_body(ngx_conf_t *cf, ngx_command_t *cmd,
413 void *conf)
414 {
415 ngx_http_echo_loc_conf_t *elcf = conf;
416
417 if (!elcf->seen_leading_output) {
418 elcf->seen_leading_output = 1;
419 }
420
421 dd("in echo_echo_request_body...");
422 return ngx_http_echo_helper(echo_opcode_echo_request_body, echo_handler_cmd,
423 cf, cmd, conf);
424 }
425
426
427 static char *
ngx_http_echo_echo_sleep(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)428 ngx_http_echo_echo_sleep(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
429 {
430 dd("in echo_sleep...");
431 return ngx_http_echo_helper(echo_opcode_echo_sleep, echo_handler_cmd,
432 cf, cmd, conf);
433 }
434
435
436 static char *
ngx_http_echo_echo_flush(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)437 ngx_http_echo_echo_flush(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
438 {
439 ngx_http_echo_loc_conf_t *elcf = conf;
440
441 if (!elcf->seen_leading_output) {
442 elcf->seen_leading_output = 1;
443 }
444
445 dd("in echo_flush...");
446 return ngx_http_echo_helper(echo_opcode_echo_flush, echo_handler_cmd,
447 cf, cmd, conf);
448 }
449
450
451 static char *
ngx_http_echo_echo_blocking_sleep(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)452 ngx_http_echo_echo_blocking_sleep(ngx_conf_t *cf, ngx_command_t *cmd,
453 void *conf)
454 {
455 dd("in echo_blocking_sleep...");
456 return ngx_http_echo_helper(echo_opcode_echo_blocking_sleep,
457 echo_handler_cmd, cf, cmd, conf);
458 }
459
460
461 static char *
ngx_http_echo_echo_reset_timer(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)462 ngx_http_echo_echo_reset_timer(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
463 {
464 return ngx_http_echo_helper(echo_opcode_echo_reset_timer, echo_handler_cmd,
465 cf, cmd, conf);
466 }
467
468
469 static char *
ngx_http_echo_echo_before_body(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)470 ngx_http_echo_echo_before_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
471 {
472 dd("processing echo_before_body directive...");
473 return ngx_http_echo_helper(echo_opcode_echo_before_body, echo_filter_cmd,
474 cf, cmd, conf);
475 }
476
477
478 static char *
ngx_http_echo_echo_after_body(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)479 ngx_http_echo_echo_after_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
480 {
481 return ngx_http_echo_helper(echo_opcode_echo_after_body, echo_filter_cmd,
482 cf, cmd, conf);
483 }
484
485
486 static char *
ngx_http_echo_echo_location_async(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)487 ngx_http_echo_echo_location_async(ngx_conf_t *cf, ngx_command_t *cmd,
488 void *conf)
489 {
490 ngx_http_echo_loc_conf_t *elcf = conf;
491 char *ret;
492
493 if (!elcf->seen_leading_output) {
494 elcf->seen_leading_output = 1;
495
496 ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd,
497 cf, cmd, conf);
498
499 if (ret != NGX_CONF_OK) {
500 return ret;
501 }
502 }
503
504 return ngx_http_echo_helper(echo_opcode_echo_location_async,
505 echo_handler_cmd, cf, cmd, conf);
506 }
507
508
509 static char *
ngx_http_echo_echo_location(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)510 ngx_http_echo_echo_location(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
511 {
512 ngx_http_echo_loc_conf_t *elcf = conf;
513 char *ret;
514
515 if (!elcf->seen_leading_output) {
516 elcf->seen_leading_output = 1;
517
518 ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd,
519 cf, cmd, conf);
520
521 if (ret != NGX_CONF_OK) {
522 return ret;
523 }
524 }
525
526 return ngx_http_echo_helper(echo_opcode_echo_location, echo_handler_cmd,
527 cf, cmd, conf);
528 }
529
530
531 static char *
ngx_http_echo_echo_subrequest_async(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)532 ngx_http_echo_echo_subrequest_async(ngx_conf_t *cf, ngx_command_t *cmd,
533 void *conf)
534 {
535 char *ret;
536 ngx_http_echo_loc_conf_t *elcf = conf;
537
538 if (!elcf->seen_leading_output) {
539 elcf->seen_leading_output = 1;
540
541 ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd,
542 cf, cmd, conf);
543
544 if (ret != NGX_CONF_OK) {
545 return ret;
546 }
547 }
548
549 return ngx_http_echo_helper(echo_opcode_echo_subrequest_async,
550 echo_handler_cmd, cf, cmd, conf);
551 }
552
553
554 static char *
ngx_http_echo_echo_subrequest(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)555 ngx_http_echo_echo_subrequest(ngx_conf_t *cf, ngx_command_t *cmd,
556 void *conf)
557 {
558 ngx_http_echo_loc_conf_t *elcf = conf;
559 char *ret;
560
561 if (!elcf->seen_leading_output) {
562 elcf->seen_leading_output = 1;
563
564 ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd,
565 cf, cmd, conf);
566
567 if (ret != NGX_CONF_OK) {
568 return ret;
569 }
570 }
571
572 return ngx_http_echo_helper(echo_opcode_echo_subrequest, echo_handler_cmd,
573 cf, cmd, conf);
574 }
575
576
577 static char *
ngx_http_echo_echo_duplicate(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)578 ngx_http_echo_echo_duplicate(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
579 {
580 ngx_http_echo_loc_conf_t *elcf = conf;
581
582 if (!elcf->seen_leading_output) {
583 elcf->seen_leading_output = 1;
584 }
585
586 return ngx_http_echo_helper(echo_opcode_echo_duplicate, echo_handler_cmd,
587 cf, cmd, conf);
588 }
589
590
591 static char *
ngx_http_echo_echo_read_request_body(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)592 ngx_http_echo_echo_read_request_body(ngx_conf_t *cf, ngx_command_t *cmd,
593 void *conf)
594 {
595 return ngx_http_echo_helper(echo_opcode_echo_read_request_body,
596 echo_handler_cmd, cf, cmd, conf);
597 }
598
599
600 static char *
ngx_http_echo_echo_foreach_split(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)601 ngx_http_echo_echo_foreach_split(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
602 {
603 return ngx_http_echo_helper(echo_opcode_echo_foreach_split,
604 echo_handler_cmd, cf, cmd, conf);
605 }
606
607
608 static char *
ngx_http_echo_echo_end(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)609 ngx_http_echo_echo_end(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
610 {
611 return ngx_http_echo_helper(echo_opcode_echo_end, echo_handler_cmd, cf,
612 cmd, conf);
613 }
614
615
616 static char *
ngx_http_echo_echo_abort_parent(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)617 ngx_http_echo_echo_abort_parent(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
618 {
619 return ngx_http_echo_helper(echo_opcode_echo_abort_parent, echo_handler_cmd,
620 cf, cmd, conf);
621 }
622
623
624 static char *
ngx_http_echo_echo_exec(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)625 ngx_http_echo_echo_exec(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
626 {
627 return ngx_http_echo_helper(echo_opcode_echo_exec, echo_handler_cmd,
628 cf, cmd, conf);
629 }
630
631
632 static void *
ngx_http_echo_create_main_conf(ngx_conf_t * cf)633 ngx_http_echo_create_main_conf(ngx_conf_t *cf)
634 {
635 #if nginx_version >= 1011011
636 ngx_pool_cleanup_t *cln;
637 #endif
638 ngx_http_echo_main_conf_t *emcf;
639
640 emcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_main_conf_t));
641 if (emcf == NULL) {
642 return NULL;
643 }
644
645 /* set by ngx_pcalloc:
646 * hmcf->requires_filter = 0;
647 */
648
649 #if nginx_version >= 1011011
650 cln = ngx_pool_cleanup_add(cf->pool, 0);
651 if (cln == NULL) {
652 return NULL;
653 }
654
655 cln->data = emcf;
656 cln->handler = ngx_http_echo_request_headers_cleanup;
657 #endif
658
659 return emcf;
660 }
661
662
663 static ngx_int_t
ngx_http_echo_post_config(ngx_conf_t * cf)664 ngx_http_echo_post_config(ngx_conf_t *cf)
665 {
666 ngx_int_t rc;
667
668 rc = ngx_http_echo_filter_init(cf);
669 if (rc != NGX_OK) {
670 return rc;
671 }
672
673 rc = ngx_http_echo_echo_init(cf);
674 if (rc != NGX_OK) {
675 return rc;
676 }
677
678 ngx_http_echo_content_length_hash =
679 ngx_http_echo_hash_literal("content-length");
680
681 return ngx_http_echo_add_variables(cf);
682 }
683