static ngx_int_t ngx_http_echo_header_filter(ngx_http_request_t *r) { ngx_http_echo_loc_conf_t *conf; ngx_http_echo_ctx_t *ctx; dd("We're in the header filter..."); ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); /* XXX we should add option to insert contents for responses * of non-200 status code here... */ /* if (r->headers_out.status != NGX_HTTP_OK) { if (ctx != NULL) { ctx->skip_filter = 1; } return ngx_http_echo_next_header_filter(r); } */ conf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); if (conf->before_body_cmds == NULL && conf->after_body_cmds == NULL) { if (ctx != NULL) { ctx->skip_filter = 1; } return ngx_http_echo_next_header_filter(r); } if (ctx == NULL) { ctx = ngx_http_echo_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } ctx->headers_sent = 1; ngx_http_set_ctx(r, ctx, ngx_http_echo_module); } /* enable streaming here (use chunked encoding) */ ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); return ngx_http_echo_next_header_filter(r); }
static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r) { r->request_body_no_buffering = 1; r->buffered = 0; ngx_http_echo_ctx_t *ctx; ctx = ngx_http_echo_create_ctx(r); ctx->wev.handler = echo_reading_callback; ctx->wev.data = ctx; ctx->wev.log = r->connection->log; create_ev(&ctx->wev, (ngx_msec_t)1000); r->main->count++; return NGX_AGAIN; } /* ngx_http_hello_world_handler */
static ngx_int_t ngx_http_echo_header_filter(ngx_http_request_t *r) { ngx_http_echo_loc_conf_t *conf; ngx_http_echo_ctx_t *ctx; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo header filter, uri \"%V?%V\"", &r->uri, &r->args); ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); /* XXX we should add option to insert contents for responses * of non-200 status code here... */ /* if (r->headers_out.status != NGX_HTTP_OK) { if (ctx != NULL) { ctx->skip_filter = 1; } return ngx_http_echo_next_header_filter(r); } */ conf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); if (conf->before_body_cmds == NULL && conf->after_body_cmds == NULL) { if (ctx != NULL) { ctx->skip_filter = 1; } return ngx_http_echo_next_header_filter(r); } if (ctx == NULL) { ctx = ngx_http_echo_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_echo_module); } /* enable streaming here (use chunked encoding) */ ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); return ngx_http_echo_next_header_filter(r); }
ngx_int_t ngx_http_echo_run_cmds(ngx_http_request_t *r) { ngx_http_echo_loc_conf_t *elcf; ngx_http_echo_ctx_t *ctx; ngx_int_t rc; ngx_array_t *cmds; ngx_array_t *computed_args = NULL; ngx_http_echo_cmd_t *cmd; ngx_http_echo_cmd_t *cmd_elts; ngx_array_t *opts = NULL; elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); cmds = elcf->handler_cmds; if (cmds == NULL) { return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL) { ctx = ngx_http_echo_create_ctx(r); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_echo_module); } dd("exec handler: %.*s: %i", (int) r->uri.len, r->uri.data, (int) ctx->next_handler_cmd); cmd_elts = cmds->elts; for (; ctx->next_handler_cmd < cmds->nelts; ctx->next_handler_cmd++) { cmd = &cmd_elts[ctx->next_handler_cmd]; /* evaluate arguments for the current cmd (if any) */ if (cmd->args) { computed_args = ngx_array_create(r->pool, cmd->args->nelts, sizeof(ngx_str_t)); if (computed_args == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } opts = ngx_array_create(r->pool, 1, sizeof(ngx_str_t)); if (opts == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } rc = ngx_http_echo_eval_cmd_args(r, cmd, computed_args, opts); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to evaluate arguments for " "the directive."); return rc; } } /* do command dispatch based on the opcode */ switch (cmd->opcode) { case echo_opcode_echo: /* XXX moved the following code to a separate * function */ dd("found echo opcode"); rc = ngx_http_echo_exec_echo(r, ctx, computed_args, 0 /* in filter */, opts); break; case echo_opcode_echo_request_body: rc = ngx_http_echo_exec_echo_request_body(r, ctx); break; case echo_opcode_echo_location_async: dd("found opcode echo location async..."); rc = ngx_http_echo_exec_echo_location_async(r, ctx, computed_args); break; case echo_opcode_echo_location: return ngx_http_echo_exec_echo_location(r, ctx, computed_args); break; case echo_opcode_echo_subrequest_async: dd("found opcode echo subrequest async..."); rc = ngx_http_echo_exec_echo_subrequest_async(r, ctx, computed_args); break; case echo_opcode_echo_subrequest: return ngx_http_echo_exec_echo_subrequest(r, ctx, computed_args); break; case echo_opcode_echo_sleep: return ngx_http_echo_exec_echo_sleep(r, ctx, computed_args); break; case echo_opcode_echo_flush: rc = ngx_http_echo_exec_echo_flush(r, ctx); break; case echo_opcode_echo_blocking_sleep: rc = ngx_http_echo_exec_echo_blocking_sleep(r, ctx, computed_args); break; case echo_opcode_echo_reset_timer: rc = ngx_http_echo_exec_echo_reset_timer(r, ctx); break; case echo_opcode_echo_duplicate: rc = ngx_http_echo_exec_echo_duplicate(r, ctx, computed_args); break; case echo_opcode_echo_read_request_body: ctx->wait_read_request_body = 0; rc = ngx_http_echo_exec_echo_read_request_body(r, ctx); #if defined(nginx_version) && nginx_version >= 8011 /* XXX read_client_request_body always increments the counter */ r->main->count--; #endif dd("read request body: %d", (int) rc); if (rc == NGX_OK) { continue; } ctx->wait_read_request_body = 1; /* r->write_event_handler = ngx_http_request_empty_handler; */ return rc; break; case echo_opcode_echo_foreach_split: rc = ngx_http_echo_exec_echo_foreach_split(r, ctx, computed_args); break; case echo_opcode_echo_end: rc = ngx_http_echo_exec_echo_end(r, ctx); break; case echo_opcode_echo_exec: dd("echo_exec"); return ngx_http_echo_exec_exec(r, ctx, computed_args); break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Unknown opcode: %d", cmd->opcode); return NGX_HTTP_INTERNAL_SERVER_ERROR; break; } if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } } rc = ngx_http_echo_send_chain_link(r, ctx, NULL /* indicate LAST */); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_OK; }
ngx_int_t ngx_http_echo_exec_echo_location(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_int_t rc; ngx_http_request_t *sr; /* subrequest object */ ngx_str_t *computed_arg_elts; ngx_str_t location; ngx_str_t *url_args; ngx_http_post_subrequest_t *psr; ngx_str_t args; ngx_uint_t flags = 0; ngx_http_echo_ctx_t *sr_ctx; computed_arg_elts = computed_args->elts; location = computed_arg_elts[0]; if (location.len == 0) { return NGX_ERROR; } if (computed_args->nelts > 1) { url_args = &computed_arg_elts[1]; } else { url_args = NULL; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, &location, &args, &flags) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo_location sees unsafe uri: \"%V\"", &location); return NGX_ERROR; } if (args.len > 0 && url_args == NULL) { url_args = &args; } rc = ngx_http_echo_send_header_if_needed(r, ctx); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } sr_ctx = ngx_http_echo_create_ctx(r); psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { return NGX_ERROR; } psr->handler = ngx_http_echo_post_subrequest; psr->data = sr_ctx; rc = ngx_http_subrequest(r, &location, url_args, &sr, psr, 0); if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_http_echo_adjust_subrequest(sr); if (rc != NGX_OK) { return NGX_ERROR; } return NGX_AGAIN; }
ngx_int_t ngx_http_echo_timer_elapsed_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_echo_ctx_t *ctx; ngx_msec_int_t ms; u_char *p; ngx_time_t *tp; size_t size; ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL) { ctx = ngx_http_echo_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_echo_module); } if (ctx->timer_begin.sec == 0) { ctx->timer_begin.sec = r->start_sec; ctx->timer_begin.msec = (ngx_msec_t) r->start_msec; } /* force the ngx timer to update */ #if (nginx_version >= 8035) || (nginx_version < 8000 && nginx_version >= 7066) ngx_time_update(); #else ngx_time_update(0, 0); #endif tp = ngx_timeofday(); dd("old sec msec: %ld %d\n", (long) ctx->timer_begin.sec, (int) ctx->timer_begin.msec); dd("new sec msec: %ld %d\n", (long) tp->sec, (int) tp->msec); ms = (ngx_msec_int_t) ((tp->sec - ctx->timer_begin.sec) * 1000 + (tp->msec - ctx->timer_begin.msec)); ms = (ms >= 0) ? ms : 0; size = sizeof("-9223372036854775808.000") - 1; p = ngx_palloc(r->pool, size); if (p == NULL) { return NGX_ERROR; } v->len = ngx_snprintf(p, size, "%T.%03M", ms / 1000, ms % 1000) - p; v->data = p; v->valid = 1; v->no_cacheable = 1; v->not_found = 0; return NGX_OK; }