# HG changeset patch # User Igor Sysoev # Date 1228746200 0 # Node ID 87b8c44906b52f2de52bd88bf62ffb051dd1299b # Parent 29d89920a749ef7ffcb94e168e3158598b89517b *) refactor subrequest handling, now they run as separate posted requests *) now $upstream_addr, $upstream_status, $upstream_response_time can be used with log_subrequest diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c --- a/src/http/modules/ngx_http_addition_filter_module.c +++ b/src/http/modules/ngx_http_addition_filter_module.c @@ -151,10 +151,10 @@ ngx_http_addition_body_filter(ngx_http_r ctx->before_body_sent = 1; if (conf->before_body.len) { - rc = ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0); - - if (rc == NGX_ERROR || rc == NGX_DONE) { - return rc; + if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0) + != NGX_OK) + { + return NGX_ERROR; } } } @@ -180,10 +180,10 @@ ngx_http_addition_body_filter(ngx_http_r return rc; } - rc = ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0); - - if (rc == NGX_ERROR || rc == NGX_DONE) { - return rc; + if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0) + != NGX_OK) + { + return NGX_ERROR; } ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module); diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -375,7 +375,6 @@ ngx_http_ssi_body_filter(ngx_http_reques ngx_uint_t i, index; ngx_chain_t *cl, **ll; ngx_table_elt_t *param; - ngx_http_request_t *pr; ngx_http_ssi_ctx_t *ctx, *mctx; ngx_http_ssi_block_t *bl; ngx_http_ssi_param_t *prm; @@ -403,44 +402,37 @@ ngx_http_ssi_body_filter(ngx_http_reques } } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter \"%V?%V\"", &r->uri, &r->args); + if (ctx->wait) { - if (r->connection->data != r) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\" wait", &r->uri); + + if (r != r->connection->data) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter wait \"%V?%V\" non-active", + &ctx->wait->uri, &ctx->wait->args); + return NGX_AGAIN; } - for (pr = ctx->wait->parent; pr; pr = pr->parent) { - if (pr == r) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\" flush", &r->uri); - - rc = ngx_http_next_body_filter(r, NULL); - - if (ctx->wait->done) { - ctx->wait = NULL; - } - - if (rc == NGX_ERROR || rc == NGX_AGAIN) { - return rc; - } - - break; - } - } - - if (ctx->wait == r) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\" continue", &r->uri); + if (ctx->wait->done) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter wait \"%V?%V\" done", + &ctx->wait->uri, &ctx->wait->args); + ctx->wait = NULL; + + } else { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter wait \"%V?%V\"", + &ctx->wait->uri, &ctx->wait->args); + + return ngx_http_next_body_filter(r, NULL); } } slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http ssi filter \"%V\"", &r->uri); - while (ctx->in || ctx->buf) { if (ctx->buf == NULL ){ @@ -788,16 +780,12 @@ ngx_http_ssi_body_filter(ngx_http_reques } } - if (cmd->flush) { - - if (ctx->out) { - rc = ngx_http_ssi_output(r, ctx); - - } else { - rc = ngx_http_next_body_filter(r, NULL); - } - - if (rc == NGX_ERROR) { + if (cmd->flush && ctx->out) { + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "ssi flush"); + + if (ngx_http_ssi_output(r, ctx) == NGX_ERROR) { return NGX_ERROR; } } @@ -2001,6 +1989,10 @@ ngx_http_ssi_include(ngx_http_request_t } } + if (wait) { + flags |= NGX_HTTP_SUBREQUEST_WAITED; + } + if (set) { key = ngx_hash_strlow(set->data, set->data, set->len); @@ -2033,16 +2025,10 @@ ngx_http_ssi_include(ngx_http_request_t psr->data = &var->value; } - flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY; + flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY|NGX_HTTP_SUBREQUEST_WAITED; } - rc = ngx_http_subrequest(r, uri, &args, &sr, psr, flags); - - if (rc == NGX_DONE) { - return NGX_DONE; - } - - if (rc == NGX_ERROR) { + if (ngx_http_subrequest(r, uri, &args, &sr, psr, flags) != NGX_OK) { return NGX_HTTP_SSI_ERROR; } @@ -2050,17 +2036,17 @@ ngx_http_ssi_include(ngx_http_request_t return NGX_OK; } - if (rc == NGX_AGAIN) { - if (ctx->wait == NULL) { - ctx->wait = sr; - - } else { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "only one subrequest may be waited at the same time"); - } + if (ctx->wait == NULL) { + ctx->wait = sr; + + return NGX_AGAIN; + + } else { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "only one subrequest may be waited at the same time"); } - return rc; + return NGX_OK; } diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -217,7 +217,7 @@ ngx_http_static_handler(ngx_http_request return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (r != r->main && of.size == 0) { + if (of.size == 0) { return ngx_http_send_header(r); } diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -80,11 +80,14 @@ ngx_int_t ngx_http_parse_multi_header_li ngx_int_t ngx_http_find_server_conf(ngx_http_request_t *r); void ngx_http_update_location_config(ngx_http_request_t *r); void ngx_http_handler(ngx_http_request_t *r); +void ngx_http_run_posted_requests(ngx_connection_t *c); +ngx_int_t ngx_http_post_request(ngx_http_request_t *r); void ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc); void ngx_http_empty_handler(ngx_event_t *wev); void ngx_http_request_empty_handler(ngx_http_request_t *r); + #define NGX_HTTP_LAST 1 #define NGX_HTTP_FLUSH 2 diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -117,10 +117,6 @@ ngx_http_copy_filter(ngx_http_request_t r->buffered |= NGX_HTTP_COPY_BUFFERED; } - if (r != r->main) { - r->out = ctx->in; - } - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args); } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1831,7 +1831,6 @@ ngx_http_subrequest(ngx_http_request_t * { ngx_connection_t *c; ngx_http_request_t *sr; - ngx_http_log_ctx_t *ctx; ngx_http_core_srv_conf_t *cscf; ngx_http_postponed_request_t *pr, *p; @@ -1896,6 +1895,7 @@ ngx_http_subrequest(ngx_http_request_t * sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0; sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0; + sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0; sr->unparsed_uri = r->unparsed_uri; sr->method_name = ngx_http_core_get_method; @@ -1909,7 +1909,7 @@ ngx_http_subrequest(ngx_http_request_t * sr->parent = r; sr->post_subrequest = ps; sr->read_event_handler = ngx_http_request_empty_handler; - sr->write_event_handler = ngx_http_request_empty_handler; + sr->write_event_handler = ngx_http_handler; if (c->data == r) { c->data = sr; @@ -1940,39 +1940,18 @@ ngx_http_subrequest(ngx_http_request_t * r->postponed = pr; } - ctx = c->log->data; - ctx->current_request = sr; - sr->internal = 1; - sr->fast_subrequest = 1; sr->discard_body = r->discard_body; sr->main_filter_need_in_memory = r->main_filter_need_in_memory; sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; - ngx_http_handler(sr); - - if (!c->destroyed) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http subrequest done \"%V?%V\"", uri, &sr->args); - - r->main->subrequests++; - - *psr = sr; - - if (sr->fast_subrequest) { - sr->fast_subrequest = 0; - - if (sr->done) { - return NGX_OK; - } - } - - return NGX_AGAIN; - } - - return NGX_DONE; + r->main->subrequests++; + + *psr = sr; + + return ngx_http_post_request(sr); } diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c --- a/src/http/ngx_http_postpone_filter_module.c +++ b/src/http/ngx_http_postpone_filter_module.c @@ -9,8 +9,8 @@ #include -static ngx_int_t - ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r); +static ngx_int_t ngx_http_postpone_filter_add(ngx_http_request_t *r, + ngx_chain_t *in); static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf); @@ -51,181 +51,119 @@ static ngx_http_output_body_filter_pt static ngx_int_t ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) { - ngx_int_t rc; - ngx_chain_t *out; - ngx_http_postponed_request_t *pr, **ppr; + ngx_connection_t *c; + ngx_http_postponed_request_t *pr; - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + c = r->connection; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in); - if (r != r->connection->data || (r->postponed && in)) { - - if (r->postponed) { - for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ } - - ppr = pr->request ? &pr->next : NULL; - - } else { - ppr = &r->postponed; -#if (NGX_SUPPRESS_WARN) - pr = NULL; -#endif - } + if (r != c->data) { - if (ppr) { - pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t)); - if (pr == NULL) { - return NGX_ERROR; - } - - *ppr = pr; - - pr->request = NULL; - pr->out = NULL; - pr->next = NULL; - } - - if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_ERROR) { - return NGX_ERROR; + if (in) { + ngx_http_postpone_filter_add(r, in); + return NGX_OK; } -#if 1 - { - ngx_chain_t *cl; - ngx_buf_t *b = NULL; - for (cl = pr->out; cl; cl = cl->next) { - if (cl->buf == b) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - "the same buf was used in postponed %p %p", - b, b->pos); - ngx_debug_point(); - return NGX_ERROR; - } - b = cl->buf; - } - } +#if 0 + /* TODO: SSI may pass NULL */ + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "http postpone filter NULL inactive request", + &r->uri, &r->args); #endif - if (r != r->connection->data || r->postponed->request) { - return NGX_AGAIN; - } - } - - if (r->postponed) { - out = r->postponed->out; - if (out) { - r->postponed = r->postponed->next; - } - - } else { - out = in; - } - - rc = NGX_OK; - - if (out - || (r->connection->buffered - & (NGX_HTTP_LOWLEVEL_BUFFERED|NGX_LOWLEVEL_BUFFERED))) - { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter out \"%V?%V\"", &r->uri, &r->args); - - if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) { - - rc = ngx_http_next_filter(r->main, out); - - if (rc == NGX_ERROR) { - /* NGX_ERROR may be returned by any filter */ - r->connection->error = 1; - } - } + return NGX_OK; } if (r->postponed == NULL) { - return rc; + + if (in || c->buffered) { + return ngx_http_next_filter(r->main, in); + } + + return NGX_OK; + } + + if (in) { + ngx_http_postpone_filter_add(r, in); } - rc = ngx_http_postpone_filter_output_postponed_request(r); + do { + pr = r->postponed; + + if (pr->request) { + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http postpone filter wake \"%V?%V\"", + &pr->request->uri, &pr->request->args); + + r->postponed = pr->next; + + c->data = pr->request; + + return ngx_http_post_request(pr->request); + } - if (rc == NGX_ERROR) { - /* NGX_ERROR may be returned by any filter */ - r->connection->error = 1; - } + if (pr->out == NULL) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "http postpone filter NULL output", + &r->uri, &r->args); + + } else { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http postpone filter output \"%V?%V\"", + &r->uri, &r->args); - return rc; + if (ngx_http_next_filter(r->main, pr->out) == NGX_ERROR) { + return NGX_ERROR; + } + } + + r->postponed = pr->next; + + } while (r->postponed); + + return NGX_OK; } static ngx_int_t -ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r) +ngx_http_postpone_filter_add(ngx_http_request_t *r, ngx_chain_t *in) { - ngx_int_t rc; - ngx_chain_t *out; - ngx_http_log_ctx_t *ctx; - ngx_http_postponed_request_t *pr; + ngx_http_postponed_request_t *pr, **ppr; - for ( ;; ) { - pr = r->postponed; + if (r->postponed) { + for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ } - if (pr == NULL) { - break; + if (pr->request == NULL) { + goto found; } - if (pr->request) { - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter handle \"%V?%V\"", - &pr->request->uri, &pr->request->args); - - ctx = r->connection->log->data; - ctx->current_request = pr->request; - - if (!pr->request->done) { - r->connection->data = pr->request; - return NGX_AGAIN; - } - - rc = ngx_http_postpone_filter_output_postponed_request(pr->request); - - if (rc == NGX_AGAIN || rc == NGX_ERROR) { - return rc; - } + ppr = &pr->next; - r->postponed = r->postponed->next; - pr = r->postponed; - } - - if (pr == NULL) { - break; - } - - out = pr->out; + } else { + ppr = &r->postponed; + } - if (out) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter out postponed \"%V?%V\"", - &r->uri, &r->args); - - if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) { - if (ngx_http_next_filter(r->main, out) == NGX_ERROR) { - return NGX_ERROR; - } - } - } - - r->postponed = r->postponed->next; + pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t)); + if (pr == NULL) { + return NGX_ERROR; } - if (r != r->main && r->out) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter out again \"%V?%V\"", - &r->uri, &r->args); + *ppr = pr; - r->connection->data = r; - return NGX_AGAIN; + pr->request = NULL; + pr->out = NULL; + pr->next = NULL; + +found: + + if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_OK) { + return NGX_OK; } - return NGX_OK; + return NGX_ERROR; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -38,6 +38,7 @@ static ngx_int_t ngx_http_find_virtual_s static void ngx_http_request_handler(ngx_event_t *ev); static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r); static void ngx_http_writer(ngx_http_request_t *r); +static void ngx_http_request_finalizer(ngx_http_request_t *r); static void ngx_http_set_keepalive(ngx_http_request_t *r); static void ngx_http_keepalive_handler(ngx_event_t *ev); @@ -1522,7 +1523,7 @@ ngx_http_process_request(ngx_http_reques ngx_http_handler(r); - return; + ngx_http_run_posted_requests(c); } @@ -1675,12 +1676,73 @@ ngx_http_request_handler(ngx_event_t *ev ctx = c->log->data; ctx->current_request = r; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http run request: \"%V?%V\"", &r->uri, &r->args); + if (ev->write) { r->write_event_handler(r); } else { r->read_event_handler(r); } + + ngx_http_run_posted_requests(c); +} + + +void +ngx_http_run_posted_requests(ngx_connection_t *c) +{ + ngx_http_request_t *r; + ngx_http_log_ctx_t *ctx; + ngx_http_posted_request_t *pr; + + for ( ;; ) { + + if (c->destroyed) { + return; + } + + r = c->data; + pr = r->main->posted_requests; + + if (pr == NULL) { + return; + } + + r->main->posted_requests = pr->next; + + r = pr->request; + + ctx = c->log->data; + ctx->current_request = r; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http posted request: \"%V?%V\"", &r->uri, &r->args); + + r->write_event_handler(r); + } +} + + +ngx_int_t +ngx_http_post_request(ngx_http_request_t *r) +{ + ngx_http_posted_request_t *pr, **p; + + pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t)); + if (pr == NULL) { + return NGX_ERROR; + } + + pr->request = r; + pr->next = NULL; + + for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ } + + *p = pr; + + return NGX_OK; } @@ -1689,7 +1751,6 @@ ngx_http_finalize_request(ngx_http_reque { ngx_connection_t *c; ngx_http_request_t *pr; - ngx_http_log_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; if (rc == NGX_DONE) { @@ -1699,9 +1760,9 @@ ngx_http_finalize_request(ngx_http_reque c = r->connection; - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http finalize request: %d, \"%V?%V\"", - rc, &r->uri, &r->args); + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http finalize request: %d, \"%V?%V\" %d", + rc, &r->uri, &r->args, r == c->data); if (rc == NGX_DECLINED) { r->content_handler = NULL; @@ -1757,88 +1818,93 @@ ngx_http_finalize_request(ngx_http_reque return; } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (r != r->main && !r->logged) { - - if (clcf->log_subrequest) { - ngx_http_log_request(r); - } - - r->logged = 1; - } - - if (r != r->main || rc == NGX_AGAIN) { - if (ngx_http_set_write_handler(r) != NGX_OK) { + if (r != r->main) { + + if (r->buffered || r->postponed) { + + if (ngx_http_set_write_handler(r) != NGX_OK) { + ngx_http_close_request(r->main, 0); + } + return; } - } - - r->done = 1; - - if (r != c->data) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http finalize non-active request: \"%V?%V\"", - &r->uri, &r->args); - return; - } - - if (r != r->main) { + +#if (NGX_DEBUG) + if (r != c->data) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http finalize non-active request: \"%V?%V\"", + &r->uri, &r->args); + } +#endif pr = r->parent; + if (r == c->data) { + + if (!r->logged) { + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->log_subrequest) { + ngx_http_log_request(r); + } + + r->logged = 1; + + } else { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "subrequest: \"%V?%V\" logged again", + &r->uri, &r->args); + } + + r->done = 1; + + if (pr->postponed && pr->postponed->request == r) { + pr->postponed = pr->postponed->next; + } + + c->data = pr; + + } else { + + r->write_event_handler = ngx_http_request_finalizer; + + if (r->waited) { + r->done = 1; + } + } + + if (ngx_http_post_request(pr) != NGX_OK) { + ngx_http_close_request(r->main, 0); + return; + } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http parent request: \"%V?%V\"", &pr->uri, &pr->args); - - if (rc != NGX_AGAIN) { - c->data = pr; - } - - ctx = c->log->data; - ctx->current_request = pr; - - if (pr->postponed) { - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http request: \"%V?%V\" has postponed", - &pr->uri, &pr->args); - - if (rc != NGX_AGAIN && pr->postponed->request == r) { - pr->postponed = pr->postponed->next; - } - - if (r->fast_subrequest) { - - if (rc == NGX_AGAIN) { - r->fast_subrequest = 0; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http fast subrequest: \"%V?%V\" done", - &r->uri, &r->args); - return; - } - - if (rc != NGX_AGAIN) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http wake parent request: \"%V?%V\"", - &pr->uri, &pr->args); - - pr->write_event_handler(pr); - } + "http wake parent request: \"%V?%V\"", + &pr->uri, &pr->args); + + ngx_http_run_posted_requests(c); + + return; + } + + if (r->buffered || c->buffered || r->postponed) { + + if (ngx_http_set_write_handler(r) != NGX_OK) { + ngx_http_close_request(r, 0); } return; } - if (rc == NGX_AGAIN) { + if (r != c->data) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "http finalize non-active request: \"%V?%V\"", + &r->uri, &r->args); return; } - if (c->buffered) { - (void) ngx_http_set_write_handler(r); - return; - } + r->done = 1; if (!r->post_action) { r->request_complete = 1; @@ -1866,6 +1932,8 @@ ngx_http_finalize_request(ngx_http_reque return; } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (!ngx_terminate && !ngx_exiting && r->keepalive @@ -1928,6 +1996,8 @@ ngx_http_writer(ngx_http_request_t *r) ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer handler: \"%V?%V\"", &r->uri, &r->args); + clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); + if (wev->timedout) { if (!wev->delayed) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, @@ -1942,7 +2012,6 @@ ngx_http_writer(ngx_http_request_t *r) wev->delayed = 0; if (!wev->ready) { - clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); ngx_add_timer(wev, clcf->send_timeout); if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { @@ -1957,8 +2026,6 @@ ngx_http_writer(ngx_http_request_t *r) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer delayed"); - clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); - if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { ngx_http_close_request(r, 0); } @@ -1977,8 +2044,8 @@ ngx_http_writer(ngx_http_request_t *r) "http writer output filter: %d, \"%V?%V\"", rc, &r->uri, &r->args); - if (rc == NGX_AGAIN) { - clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); + if (r->buffered || r->postponed || (r == r->main && c->buffered)) { + if (!wev->ready && !wev->delayed) { ngx_add_timer(wev, clcf->send_timeout); } @@ -1987,11 +2054,7 @@ ngx_http_writer(ngx_http_request_t *r) ngx_http_close_request(r, 0); } - if (r == r->main || r->buffered) { - return; - } - - rc = NGX_OK; + return; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0, @@ -2001,6 +2064,16 @@ ngx_http_writer(ngx_http_request_t *r) } +static void +ngx_http_request_finalizer(ngx_http_request_t *r) +{ + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http finalizer done: \"%V?%V\"", &r->uri, &r->args); + + ngx_http_finalize_request(r, 0); +} + + void ngx_http_block_reading(ngx_http_request_t *r) { diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -58,6 +58,7 @@ #define NGX_HTTP_ZERO_IN_URI 1 #define NGX_HTTP_SUBREQUEST_IN_MEMORY 2 +#define NGX_HTTP_SUBREQUEST_WAITED 4 #define NGX_HTTP_OK 200 @@ -321,6 +322,14 @@ struct ngx_http_postponed_request_s { }; +typedef struct ngx_http_posted_request_s ngx_http_posted_request_t; + +struct ngx_http_posted_request_s { + ngx_http_request_t *request; + ngx_http_posted_request_t *next; +}; + + typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r); typedef void (*ngx_http_event_handler_pt)(ngx_http_request_t *r); @@ -373,6 +382,7 @@ struct ngx_http_request_s { ngx_http_request_t *parent; ngx_http_postponed_request_t *postponed; ngx_http_post_subrequest_t *post_subrequest; + ngx_http_posted_request_t *posted_requests; uint32_t in_addr; ngx_uint_t port; @@ -428,8 +438,8 @@ struct ngx_http_request_s { unsigned request_body_file_group_access:1; unsigned request_body_file_log_level:3; - unsigned fast_subrequest:1; unsigned subrequest_in_memory:1; + unsigned waited:1; unsigned gzip:2; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -274,13 +274,16 @@ ngx_module_t ngx_http_upstream_module = static ngx_http_variable_t ngx_http_upstream_vars[] = { { ngx_string("upstream_addr"), NULL, - ngx_http_upstream_addr_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, + ngx_http_upstream_addr_variable, 0, + NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("upstream_status"), NULL, - ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, + ngx_http_upstream_status_variable, 0, + NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("upstream_response_time"), NULL, - ngx_http_upstream_response_time_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, + ngx_http_upstream_response_time_variable, 0, + NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -511,6 +514,37 @@ ngx_http_upstream_resolve_handler(ngx_re static void +ngx_http_upstream_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_log_ctx_t *ctx; + ngx_http_upstream_t *u; + + c = ev->data; + r = c->data; + + u = r->upstream; + c = r->connection; + + ctx = c->log->data; + ctx->current_request = r; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream request: \"%V?%V\"", &r->uri, &r->args); + + if (ev->write) { + u->write_event_handler(ev); + + } else { + u->read_event_handler(ev); + } + + ngx_http_run_posted_requests(c); +} + + +static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r) { ngx_http_upstream_check_broken_connection(r, r->connection->read); @@ -712,8 +746,11 @@ ngx_http_upstream_connect(ngx_http_reque c->data = r; - c->write->handler = ngx_http_upstream_send_request_handler; - c->read->handler = ngx_http_upstream_process_header; + c->write->handler = ngx_http_upstream_handler; + c->read->handler = ngx_http_upstream_handler; + + u->write_event_handler = ngx_http_upstream_send_request_handler; + u->read_event_handler = ngx_http_upstream_process_header; c->sendfile &= r->connection->sendfile; u->output.sendfile = c->sendfile; @@ -838,8 +875,8 @@ ngx_http_upstream_ssl_handshake(ngx_conn u->peer.save_session(&u->peer, u->peer.data); } - c->write->handler = ngx_http_upstream_send_request_handler; - c->read->handler = ngx_http_upstream_process_header; + c->write->handler = ngx_http_upstream_handler; + c->read->handler = ngx_http_upstream_handler; ngx_http_upstream_send_request(r, u); @@ -998,7 +1035,7 @@ ngx_http_upstream_send_request(ngx_http_ } #endif - c->write->handler = ngx_http_upstream_dummy_handler; + u->write_event_handler = ngx_http_upstream_dummy_handler; if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, @@ -1037,7 +1074,7 @@ ngx_http_upstream_send_request_handler(n #endif if (u->header_sent) { - wev->handler = ngx_http_upstream_dummy_handler; + u->write_event_handler = ngx_http_upstream_dummy_handler; (void) ngx_handle_write_event(wev, 0); @@ -1350,7 +1387,7 @@ ngx_http_upstream_process_header(ngx_eve } } - rev->handler = ngx_http_upstream_process_body_in_memory; + u->read_event_handler = ngx_http_upstream_process_body_in_memory; ngx_http_upstream_process_body_in_memory(rev); } @@ -1614,8 +1651,7 @@ ngx_http_upstream_send_response(ngx_http u->input_filter_ctx = r; } - u->peer.connection->read->handler = - ngx_http_upstream_process_non_buffered_body; + u->read_event_handler = ngx_http_upstream_process_non_buffered_body; r->write_event_handler = ngx_http_upstream_process_non_buffered_downstream; @@ -1796,7 +1832,7 @@ ngx_http_upstream_send_response(ngx_http p->send_timeout = clcf->send_timeout; p->send_lowat = clcf->send_lowat; - u->peer.connection->read->handler = ngx_http_upstream_process_body; + u->read_event_handler = ngx_http_upstream_process_body; r->write_event_handler = ngx_http_upstream_process_downstream; ngx_http_upstream_process_body(u->peer.connection->read); @@ -1926,7 +1962,7 @@ ngx_http_upstream_process_non_buffered_b if (downstream->data == r) { if (ngx_handle_write_event(downstream->write, clcf->send_lowat) - == NGX_ERROR) + != NGX_OK) { ngx_http_upstream_finalize_request(r, u, 0); return; @@ -1940,7 +1976,7 @@ ngx_http_upstream_process_non_buffered_b ngx_del_timer(downstream->write); } - if (ngx_handle_read_event(upstream->read, 0) == NGX_ERROR) { + if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, 0); return; } @@ -2016,7 +2052,6 @@ ngx_http_upstream_process_body(ngx_event ngx_temp_file_t *tf; ngx_event_pipe_t *p; ngx_connection_t *c, *downstream; - ngx_http_log_ctx_t *ctx; ngx_http_request_t *r; ngx_http_upstream_t *u; @@ -2034,9 +2069,6 @@ ngx_http_upstream_process_body(ngx_event ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http upstream process upstream"); c->log->action = "reading upstream"; - - ctx = c->log->data; - ctx->current_request = r; } p = u->pipe; @@ -2051,8 +2083,7 @@ ngx_http_upstream_process_body(ngx_event if (!ev->ready) { ngx_add_timer(ev, p->send_timeout); - if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR) - { + if (ngx_handle_write_event(ev, p->send_lowat) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, 0); return; } @@ -2086,7 +2117,8 @@ ngx_http_upstream_process_body(ngx_event ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http downstream delayed"); - if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR) { + if (ngx_handle_write_event(ev, p->send_lowat) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, 0); return; } @@ -2464,17 +2496,8 @@ ngx_http_upstream_finalize_request(ngx_h r->connection->log->action = "sending to client"; - if (rc == 0) { - if (r == r->main) { - if (!r->post_action) { - rc = ngx_http_send_special(r, NGX_HTTP_LAST); - } - - } else { - if (r->out) { - rc = NGX_AGAIN; - } - } + if (rc == 0 && r == r->main && !r->post_action) { + rc = ngx_http_send_special(r, NGX_HTTP_LAST); } ngx_http_finalize_request(r, rc); diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -217,6 +217,9 @@ typedef struct { struct ngx_http_upstream_s { + ngx_event_handler_pt read_event_handler; + ngx_event_handler_pt write_event_handler; + ngx_peer_connection_t peer; ngx_event_pipe_t *pipe;