Branch data Line data Source code
1 : : #define DDEBUG 0
2 : :
3 : : #include "ddebug.h"
4 : :
5 : : #include "ngx_http_echo_filter.h"
6 : : #include "ngx_http_echo_handler.h"
7 : : #include "ngx_http_echo_echo.h"
8 : : #include "ngx_http_echo_util.h"
9 : : #include "ngx_http_echo_sleep.h"
10 : : #include "ngx_http_echo_var.h"
11 : : #include "ngx_http_echo_timer.h"
12 : : #include "ngx_http_echo_location.h"
13 : : #include "ngx_http_echo_subrequest.h"
14 : : #include "ngx_http_echo_request_info.h"
15 : : #include "ngx_http_echo_foreach.h"
16 : :
17 : : #include <nginx.h>
18 : : #include <ngx_log.h>
19 : :
20 : : ngx_int_t
21 : 88 : ngx_http_echo_handler_init(ngx_conf_t *cf)
22 : : {
23 : : ngx_int_t rc;
24 : :
25 : : #if 1
26 : 88 : ngx_http_echo_filter_used = 0;
27 : : #endif
28 : :
29 : 88 : rc = ngx_http_echo_echo_init(cf);
30 [ - + ]: 88 : if (rc != NGX_OK) {
31 : 0 : return rc;
32 : : }
33 : :
34 : 88 : return ngx_http_echo_add_variables(cf);
35 : : }
36 : :
37 : :
38 : : void
39 : 2 : ngx_http_echo_wev_handler(ngx_http_request_t *r)
40 : : {
41 : : ngx_int_t rc;
42 : : ngx_http_echo_ctx_t *ctx;
43 : :
44 : : dd("wev handler");
45 : :
46 : 2 : ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
47 : :
48 [ - + ]: 2 : if (ctx == NULL) {
49 : 0 : ngx_http_finalize_request(r, NGX_ERROR);
50 : 0 : return;
51 : : }
52 : :
53 [ - + ][ # # ]: 2 : if (ctx->waiting && ! ctx->done) {
54 [ # # ][ # # ]: 0 : if (r == r->connection->data && r->postponed) {
55 [ # # ]: 0 : if (r->postponed->request) {
56 : 0 : r->connection->data = r->postponed->request;
57 : :
58 : : #if defined(nginx_version) && nginx_version >= 8012
59 : 0 : ngx_http_post_request(r->postponed->request, NULL);
60 : : #else
61 : : ngx_http_post_request(r->postponed->request);
62 : : #endif
63 : :
64 : : } else {
65 : 0 : ngx_http_echo_flush_postponed_outputs(r);
66 : : }
67 : : }
68 : :
69 : 0 : return;
70 : : }
71 : :
72 : 2 : ctx->done = 0;
73 : :
74 : 2 : ctx->next_handler_cmd++;
75 : :
76 : 2 : rc = ngx_http_echo_run_cmds(r);
77 : :
78 : : dd("rc: %d", (int) rc);
79 : :
80 [ - + ]: 2 : if (rc == NGX_DONE) {
81 : 0 : return;
82 : : }
83 : :
84 [ - + ]: 2 : if (rc == NGX_AGAIN) {
85 : : dd("mark busy %d for %.*s", (int) ctx->next_handler_cmd,
86 : : (int) r->uri.len,
87 : : r->uri.data);
88 : :
89 : 0 : ctx->waiting = 1;
90 : 0 : ctx->done = 0;
91 : :
92 : : } else {
93 : : dd("mark ready %d", (int) ctx->next_handler_cmd);
94 : 2 : ctx->waiting = 0;
95 : 2 : ctx->done = 1;
96 : :
97 : : dd("finalizing with rc %d", (int) rc);
98 : :
99 : : dd("finalize request %.*s with %d", (int) r->uri.len, r->uri.data,
100 : : (int) rc);
101 : :
102 : 2 : ngx_http_finalize_request(r, rc);
103 : : }
104 : : }
105 : :
106 : :
107 : : ngx_int_t
108 : 104 : ngx_http_echo_handler(ngx_http_request_t *r)
109 : : {
110 : : ngx_int_t rc;
111 : : ngx_http_echo_ctx_t *ctx;
112 : :
113 : 104 : rc = ngx_http_echo_run_cmds(r);
114 : :
115 [ - + ]: 104 : if (rc == NGX_ERROR) {
116 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
117 : : }
118 : :
119 [ - + ]: 104 : if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
120 : 0 : return rc;
121 : : }
122 : :
123 [ - + ]: 104 : if (rc == NGX_DONE) {
124 : 0 : return NGX_DONE;
125 : : }
126 : :
127 [ + + ]: 104 : if (rc == NGX_AGAIN) {
128 : : #if defined(nginx_version) && nginx_version >= 8011
129 : 2 : r->main->count++;
130 : : #endif
131 : :
132 : : /* XXX we need this for 0.7.x and 0.8.x < 0.8.11 */
133 : : dd("%d", r->connection->destroyed);
134 : : dd("%d", r->done);
135 : :
136 : 2 : ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
137 [ + - ]: 2 : if (ctx) {
138 : : dd("mark busy %d for %.*s", (int) ctx->next_handler_cmd,
139 : : (int) r->uri.len,
140 : : r->uri.data);
141 : :
142 : 2 : ctx->waiting = 1;
143 : 2 : ctx->done = 0;
144 : : }
145 : :
146 : 2 : return NGX_DONE;
147 : : }
148 : :
149 : 104 : return NGX_OK;
150 : : }
151 : :
152 : :
153 : : ngx_int_t
154 : 106 : ngx_http_echo_run_cmds(ngx_http_request_t *r)
155 : : {
156 : : ngx_http_echo_loc_conf_t *elcf;
157 : : ngx_http_echo_ctx_t *ctx;
158 : : ngx_int_t rc;
159 : : ngx_array_t *cmds;
160 : 106 : ngx_array_t *computed_args = NULL;
161 : : ngx_http_echo_cmd_t *cmd;
162 : : ngx_http_echo_cmd_t *cmd_elts;
163 : 106 : ngx_array_t *opts = NULL;
164 : :
165 : :
166 : 106 : elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
167 : 106 : cmds = elcf->handler_cmds;
168 [ - + ]: 106 : if (cmds == NULL) {
169 : 0 : return NGX_DECLINED;
170 : : }
171 : :
172 : 106 : ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
173 [ + + ]: 106 : if (ctx == NULL) {
174 : 104 : ctx = ngx_http_echo_create_ctx(r);
175 [ - + ]: 104 : if (ctx == NULL) {
176 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
177 : : }
178 : :
179 : 104 : ngx_http_set_ctx(r, ctx, ngx_http_echo_module);
180 : : }
181 : :
182 : : dd("exec handler: %.*s: %i", (int) r->uri.len, r->uri.data,
183 : : (int) ctx->next_handler_cmd);
184 : :
185 : 106 : cmd_elts = cmds->elts;
186 : :
187 [ + + ]: 224 : for (; ctx->next_handler_cmd < cmds->nelts; ctx->next_handler_cmd++) {
188 : :
189 : 120 : cmd = &cmd_elts[ctx->next_handler_cmd];
190 : :
191 : : /* evaluate arguments for the current cmd (if any) */
192 [ + - ]: 120 : if (cmd->args) {
193 : 120 : computed_args = ngx_array_create(r->pool, cmd->args->nelts,
194 : : sizeof(ngx_str_t));
195 : :
196 [ - + ]: 120 : if (computed_args == NULL) {
197 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
198 : : }
199 : :
200 : 120 : opts = ngx_array_create(r->pool, 1, sizeof(ngx_str_t));
201 : :
202 [ - + ]: 120 : if (opts == NULL) {
203 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
204 : : }
205 : :
206 : 120 : rc = ngx_http_echo_eval_cmd_args(r, cmd, computed_args, opts);
207 [ - + ]: 120 : if (rc != NGX_OK) {
208 [ # # ]: 0 : ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
209 : : "Failed to evaluate arguments for "
210 : : "the directive.");
211 : 0 : return rc;
212 : : }
213 : : }
214 : :
215 : : /* do command dispatch based on the opcode */
216 [ + + - + : 120 : switch (cmd->opcode) {
- - - - -
- - + - -
- - ]
217 : : case echo_opcode_echo:
218 : : /* XXX moved the following code to a separate
219 : : * function */
220 : : dd("found echo opcode");
221 : 110 : rc = ngx_http_echo_exec_echo(r, ctx, computed_args,
222 : : 0 /* in filter */, opts);
223 : 110 : break;
224 : :
225 : : case echo_opcode_echo_request_body:
226 : 4 : rc = ngx_http_echo_exec_echo_request_body(r, ctx);
227 : 4 : break;
228 : :
229 : : case echo_opcode_echo_location_async:
230 : : dd("found opcode echo location async...");
231 : 0 : rc = ngx_http_echo_exec_echo_location_async(r, ctx,
232 : : computed_args);
233 : 0 : break;
234 : :
235 : : case echo_opcode_echo_location:
236 : 2 : return ngx_http_echo_exec_echo_location(r, ctx, computed_args);
237 : : break;
238 : :
239 : : case echo_opcode_echo_subrequest_async:
240 : : dd("found opcode echo subrequest async...");
241 : 0 : rc = ngx_http_echo_exec_echo_subrequest_async(r, ctx,
242 : : computed_args);
243 : 0 : break;
244 : :
245 : : case echo_opcode_echo_subrequest:
246 : 0 : return ngx_http_echo_exec_echo_subrequest(r, ctx, computed_args);
247 : : break;
248 : :
249 : : case echo_opcode_echo_sleep:
250 : 0 : return ngx_http_echo_exec_echo_sleep(r, ctx, computed_args);
251 : : break;
252 : :
253 : : case echo_opcode_echo_flush:
254 : 0 : rc = ngx_http_echo_exec_echo_flush(r, ctx);
255 : 0 : break;
256 : :
257 : : case echo_opcode_echo_blocking_sleep:
258 : 0 : rc = ngx_http_echo_exec_echo_blocking_sleep(r, ctx,
259 : : computed_args);
260 : 0 : break;
261 : :
262 : : case echo_opcode_echo_reset_timer:
263 : 0 : rc = ngx_http_echo_exec_echo_reset_timer(r, ctx);
264 : 0 : break;
265 : :
266 : : case echo_opcode_echo_duplicate:
267 : 0 : rc = ngx_http_echo_exec_echo_duplicate(r, ctx, computed_args);
268 : 0 : break;
269 : :
270 : : case echo_opcode_echo_read_request_body:
271 : 4 : ctx->wait_read_request_body = 0;
272 : :
273 : 4 : rc = ngx_http_echo_exec_echo_read_request_body(r, ctx);
274 : :
275 : : #if defined(nginx_version) && nginx_version >= 8011
276 : : /* XXX read_client_request_body always increments the counter */
277 : 4 : r->main->count--;
278 : : #endif
279 : :
280 : : dd("read request body: %d", (int) rc);
281 : :
282 [ + - ]: 4 : if (rc == NGX_OK) {
283 : 4 : continue;
284 : : }
285 : :
286 : 0 : ctx->wait_read_request_body = 1;
287 : :
288 : : /* r->write_event_handler = ngx_http_request_empty_handler; */
289 : :
290 : 0 : return rc;
291 : : break;
292 : :
293 : : case echo_opcode_echo_foreach_split:
294 : 0 : rc = ngx_http_echo_exec_echo_foreach_split(r, ctx, computed_args);
295 : 0 : break;
296 : :
297 : : case echo_opcode_echo_end:
298 : 0 : rc = ngx_http_echo_exec_echo_end(r, ctx);
299 : 0 : break;
300 : :
301 : : case echo_opcode_echo_exec:
302 : : dd("echo_exec");
303 : 0 : return ngx_http_echo_exec_exec(r, ctx, computed_args);
304 : : break;
305 : :
306 : : default:
307 [ # # ]: 0 : ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
308 : : "Unknown opcode: %d", cmd->opcode);
309 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
310 : : break;
311 : : }
312 : :
313 [ + - ][ - + ]: 114 : if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
314 : 0 : return rc;
315 : : }
316 : : }
317 : :
318 : 104 : rc = ngx_http_echo_send_chain_link(r, ctx, NULL /* indicate LAST */);
319 : :
320 [ + - ][ - + ]: 104 : if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
321 : 0 : return rc;
322 : : }
323 : :
324 : 106 : return NGX_OK;
325 : : }
326 : :
327 : :
328 : : ngx_int_t
329 : 2 : ngx_http_echo_post_subrequest(ngx_http_request_t *r,
330 : : void *data, ngx_int_t rc)
331 : : {
332 : 2 : ngx_http_echo_ctx_t *ctx = data;
333 : : ngx_http_request_t *pr;
334 : : ngx_http_echo_ctx_t *pr_ctx;
335 : :
336 : : dd_enter();
337 : :
338 : : #if 0
339 : : if (ctx->run_post_subrequest) {
340 : : return rc;
341 : : }
342 : : #endif
343 : :
344 : 2 : ctx->run_post_subrequest = 1;
345 : :
346 : 2 : pr = r->parent;
347 : :
348 : 2 : pr_ctx = ngx_http_get_module_ctx(pr, ngx_http_echo_module);
349 [ - + ]: 2 : if (pr_ctx == NULL) {
350 : 0 : return NGX_ERROR;
351 : : }
352 : :
353 : : dd("mark ready %d", (int) pr_ctx->next_handler_cmd);
354 : :
355 : 2 : pr_ctx->waiting = 0;
356 : 2 : pr_ctx->done = 1;
357 : :
358 : 2 : pr->write_event_handler = ngx_http_echo_wev_handler;
359 : :
360 : : /* ensure that the parent request is (or will be)
361 : : * posted out the head of the r->posted_requests chain */
362 : :
363 [ - + ][ # # ]: 2 : if (r->main->posted_requests
364 : 2 : && r->main->posted_requests->request != pr)
365 : : {
366 : 0 : rc = ngx_http_echo_post_request_at_head(pr, NULL);
367 [ # # ]: 0 : if (rc != NGX_OK) {
368 : 0 : return NGX_ERROR;
369 : : }
370 : : }
371 : :
372 : 2 : return rc;
373 : : }
374 : :
|