# HG changeset patch # User Roman Arutyunyan # Date 1492616157 -10800 # Node ID 69908bd684811392f875e027a75047681c6db87b # Parent ef27e3ef0c46e055d7efd4759ea496aaaa9092ae The HTTP subrequests section of the development guide. diff -r ef27e3ef0c46 -r 69908bd68481 xml/en/docs/dev/development_guide.xml --- a/xml/en/docs/dev/development_guide.xml Wed Apr 19 18:35:05 2017 +0300 +++ b/xml/en/docs/dev/development_guide.xml Wed Apr 19 18:35:57 2017 +0300 @@ -4738,6 +4738,253 @@ +
+ + +Subrequests are primarily used to include output of one request into another, +possibly mixed with other data. +A subrequest looks like a normal request, but shares some data with its parent. +Particularly, all fields related to client input are shared since a subrequest +does not receive any other input from client. +The request field parent for a subrequest keeps a link to its +parent request and is NULL for the main request. +The field main keeps a link to the main request in a group of +requests. + + + +A subrequest starts with NGX_HTTP_SERVER_REWRITE_PHASE phase. +It passes through the same phases as a normal request and is assigned a location +based on its own URI. + + + +Subrequest output header is always ignored. +Subrequest output body is placed by the +ngx_http_postpone_filter into the right position in relation +to other data produced by the parent request. + + + +Subrequests are related to the concept of active requests. +A request r is considered active if +c->data == r, where c is the client +connection object. +At any point, only the active request in a request group is allowed to output +its buffers to the client. +A non-active request can still send its data to the filter chain, but they +will not pass beyond the ngx_http_postpone_filter and will +remain buffered by that filter until the request becomes active. +Here are some rules of request activation: + + + + + +Initially, the main request is active + + + +The first subrequest of an active request becomes active right after creation + + + +The ngx_http_postpone_filter activates the next request +in active request's subrequest list, once all data prior to that request are +sent + + + +When a request is finalized, its parent is activated + + + + + +A subrequest is created by calling the function +ngx_http_subrequest(r, uri, args, psr, ps, flags), where +r is the parent request, uri and +args are URI and arguments of the +subrequest, psr is the output parameter, receiving the +newly created subrequest reference, ps is a callback object +for notifying the parent request that the subrequest is being finalized, +flags is subrequest creation flags bitmask. +The following flags are available: + + + + + +NGX_HTTP_SUBREQUEST_IN_MEMORY - subrequest output should not +be sent to the client, but rather stored in memory. +This only works for proxying subrequests. +After subrequest finalization its output is available in +r->upstream->buffer buffer of type +ngx_buf_t + + + +NGX_HTTP_SUBREQUEST_WAITED - the subrequest +done flag is set even if it is finalized being non-active. +This subrequest flag is used by the SSI filter + + + +NGX_HTTP_SUBREQUEST_CLONE - the subrequest is created as a +clone of its parent. +It is started at the same location and proceeds from the same phase as the +parent request + + + + + +The following example creates a subrequest with the URI of "/foo". + + + +ngx_int_t rc; +ngx_str_t uri; +ngx_http_request_t *sr; + +... + +ngx_str_set(&uri, "/foo"); + +rc = ngx_http_subrequest(r, &uri, NULL, &sr, NULL, 0); +if (rc == NGX_ERROR) { + /* error */ +} + + + +This example clones the current request and sets a finalization callback for the +subrequest. + + + +ngx_int_t +ngx_http_foo_clone(ngx_http_request_t *r) +{ + ngx_http_request_t *sr; + ngx_http_post_subrequest_t *ps; + + ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); + if (ps == NULL) { + return NGX_ERROR; + } + + ps->handler = ngx_http_foo_subrequest_done; + ps->data = "foo"; + + return ngx_http_subrequest(r, &r->uri, &r->args, &sr, ps, + NGX_HTTP_SUBREQUEST_CLONE); +} + + +ngx_int_t +ngx_http_foo_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc) +{ + char *msg = (char *) data; + + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "done subrequest r:%p msg:%s rc:%i", r, msg, rc); + + return rc; +} + + + +Subrequests are normally created in a body filter. +In this case subrequest output can be treated as any other explicit request +output. +This means that eventually the output of a subrequest is sent to the client +after all explicit buffers passed prior to subrequest creation and before any +buffers passed later. +This ordering is preserved even for large hierarchies of subrequests. +The following example inserts a subrequest output after all request data +buffers, but before the final buffer with the last_buf flag. + + + +ngx_int_t +ngx_http_foo_body_filter(ngx_http_request_t *r, ngx_chain_t *in) +{ + ngx_int_t rc; + ngx_buf_t *b; + ngx_uint_t last; + ngx_chain_t *cl, out; + ngx_http_request_t *sr; + ngx_http_foo_filter_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_foo_filter_module); + if (ctx == NULL) { + return ngx_http_next_body_filter(r, in); + } + + last = 0; + + for (cl = in; cl; cl = cl->next) { + if (cl->buf->last_buf) { + cl->buf->last_buf = 0; + cl->buf->last_in_chain = 1; + cl->buf->sync = 1; + last = 1; + } + } + + /* Output explicit output buffers */ + + rc = ngx_http_next_body_filter(r, in); + + if (rc == NGX_ERROR || !last) { + return rc; + } + + /* + * Create the subrequest. The output of the subrequest + * will automatically be sent after all preceding buffers, + * but before the last_buf buffer passed later in this function. + */ + + if (ngx_http_subrequest(r, ctx->uri, NULL, &sr, NULL, 0) != NGX_OK) { + return NGX_ERROR; + } + + ngx_http_set_ctx(r, NULL, ngx_http_foo_filter_module); + + + /* Output the final buffer with the last_buf flag */ + + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + b->last_buf = 1; + + out.buf = b; + out.next = NULL; + + return ngx_http_output_filter(r, &out); +} + + + +A subrequest may also be created for other purposes than data output. +For example, the +ngx_http_auth_request_module +creates a subrequest at NGX_HTTP_ACCESS_PHASE phase. +To disable any output at this point, the subrequest +header_only flag is set. +This prevents subrequest body from being sent to the client. +Its header is ignored anyway. +The result of the subrequest can be analyzed in the callback handler. + + +
+ +