Mercurial > hg > nginx-site
comparison xml/en/docs/dev/development_guide.xml @ 1968:69908bd68481
The HTTP subrequests section of the development guide.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 19 Apr 2017 18:35:57 +0300 |
parents | ef27e3ef0c46 |
children | 275c928ab386 |
comparison
equal
deleted
inserted
replaced
1967:ef27e3ef0c46 | 1968:69908bd68481 |
---|---|
4731 | 4731 |
4732 <para> | 4732 <para> |
4733 Redirected and rewritten requests become internal and may access the | 4733 Redirected and rewritten requests become internal and may access the |
4734 <link doc="../http/ngx_http_core_module.xml" id="internal">internal</link> | 4734 <link doc="../http/ngx_http_core_module.xml" id="internal">internal</link> |
4735 locations. Internal requests have the <literal>internal</literal> flag set. | 4735 locations. Internal requests have the <literal>internal</literal> flag set. |
4736 </para> | |
4737 | |
4738 </section> | |
4739 | |
4740 | |
4741 <section name="Subrequests" id="http_subrequests"> | |
4742 | |
4743 <para> | |
4744 Subrequests are primarily used to include output of one request into another, | |
4745 possibly mixed with other data. | |
4746 A subrequest looks like a normal request, but shares some data with its parent. | |
4747 Particularly, all fields related to client input are shared since a subrequest | |
4748 does not receive any other input from client. | |
4749 The request field <literal>parent</literal> for a subrequest keeps a link to its | |
4750 parent request and is NULL for the main request. | |
4751 The field <literal>main</literal> keeps a link to the main request in a group of | |
4752 requests. | |
4753 </para> | |
4754 | |
4755 <para> | |
4756 A subrequest starts with <literal>NGX_HTTP_SERVER_REWRITE_PHASE</literal> phase. | |
4757 It passes through the same phases as a normal request and is assigned a location | |
4758 based on its own URI. | |
4759 </para> | |
4760 | |
4761 <para> | |
4762 Subrequest output header is always ignored. | |
4763 Subrequest output body is placed by the | |
4764 <literal>ngx_http_postpone_filter</literal> into the right position in relation | |
4765 to other data produced by the parent request. | |
4766 </para> | |
4767 | |
4768 <para> | |
4769 Subrequests are related to the concept of active requests. | |
4770 A request <literal>r</literal> is considered active if | |
4771 <literal>c->data == r</literal>, where <literal>c</literal> is the client | |
4772 connection object. | |
4773 At any point, only the active request in a request group is allowed to output | |
4774 its buffers to the client. | |
4775 A non-active request can still send its data to the filter chain, but they | |
4776 will not pass beyond the <literal>ngx_http_postpone_filter</literal> and will | |
4777 remain buffered by that filter until the request becomes active. | |
4778 Here are some rules of request activation: | |
4779 </para> | |
4780 | |
4781 <list type="bullet"> | |
4782 | |
4783 <listitem> | |
4784 Initially, the main request is active | |
4785 </listitem> | |
4786 | |
4787 <listitem> | |
4788 The first subrequest of an active request becomes active right after creation | |
4789 </listitem> | |
4790 | |
4791 <listitem> | |
4792 The <literal>ngx_http_postpone_filter</literal> activates the next request | |
4793 in active request's subrequest list, once all data prior to that request are | |
4794 sent | |
4795 </listitem> | |
4796 | |
4797 <listitem> | |
4798 When a request is finalized, its parent is activated | |
4799 </listitem> | |
4800 | |
4801 </list> | |
4802 | |
4803 <para> | |
4804 A subrequest is created by calling the function | |
4805 <literal>ngx_http_subrequest(r, uri, args, psr, ps, flags)</literal>, where | |
4806 <literal>r</literal> is the parent request, <literal>uri</literal> and | |
4807 <literal>args</literal> are URI and arguments of the | |
4808 subrequest, <literal>psr</literal> is the output parameter, receiving the | |
4809 newly created subrequest reference, <literal>ps</literal> is a callback object | |
4810 for notifying the parent request that the subrequest is being finalized, | |
4811 <literal>flags</literal> is subrequest creation flags bitmask. | |
4812 The following flags are available: | |
4813 </para> | |
4814 | |
4815 <list type="bullet"> | |
4816 | |
4817 <listitem> | |
4818 <literal>NGX_HTTP_SUBREQUEST_IN_MEMORY</literal> - subrequest output should not | |
4819 be sent to the client, but rather stored in memory. | |
4820 This only works for proxying subrequests. | |
4821 After subrequest finalization its output is available in | |
4822 <literal>r->upstream->buffer</literal> buffer of type | |
4823 <literal>ngx_buf_t</literal> | |
4824 </listitem> | |
4825 | |
4826 <listitem> | |
4827 <literal>NGX_HTTP_SUBREQUEST_WAITED</literal> - the subrequest | |
4828 <literal>done</literal> flag is set even if it is finalized being non-active. | |
4829 This subrequest flag is used by the SSI filter | |
4830 </listitem> | |
4831 | |
4832 <listitem> | |
4833 <literal>NGX_HTTP_SUBREQUEST_CLONE</literal> - the subrequest is created as a | |
4834 clone of its parent. | |
4835 It is started at the same location and proceeds from the same phase as the | |
4836 parent request | |
4837 </listitem> | |
4838 | |
4839 </list> | |
4840 | |
4841 <para> | |
4842 The following example creates a subrequest with the URI of "/foo". | |
4843 </para> | |
4844 | |
4845 <programlisting> | |
4846 ngx_int_t rc; | |
4847 ngx_str_t uri; | |
4848 ngx_http_request_t *sr; | |
4849 | |
4850 ... | |
4851 | |
4852 ngx_str_set(&uri, "/foo"); | |
4853 | |
4854 rc = ngx_http_subrequest(r, &uri, NULL, &sr, NULL, 0); | |
4855 if (rc == NGX_ERROR) { | |
4856 /* error */ | |
4857 } | |
4858 </programlisting> | |
4859 | |
4860 <para> | |
4861 This example clones the current request and sets a finalization callback for the | |
4862 subrequest. | |
4863 </para> | |
4864 | |
4865 <programlisting> | |
4866 ngx_int_t | |
4867 ngx_http_foo_clone(ngx_http_request_t *r) | |
4868 { | |
4869 ngx_http_request_t *sr; | |
4870 ngx_http_post_subrequest_t *ps; | |
4871 | |
4872 ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); | |
4873 if (ps == NULL) { | |
4874 return NGX_ERROR; | |
4875 } | |
4876 | |
4877 ps->handler = ngx_http_foo_subrequest_done; | |
4878 ps->data = "foo"; | |
4879 | |
4880 return ngx_http_subrequest(r, &r->uri, &r->args, &sr, ps, | |
4881 NGX_HTTP_SUBREQUEST_CLONE); | |
4882 } | |
4883 | |
4884 | |
4885 ngx_int_t | |
4886 ngx_http_foo_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc) | |
4887 { | |
4888 char *msg = (char *) data; | |
4889 | |
4890 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
4891 "done subrequest r:%p msg:%s rc:%i", r, msg, rc); | |
4892 | |
4893 return rc; | |
4894 } | |
4895 </programlisting> | |
4896 | |
4897 <para> | |
4898 Subrequests are normally created in a body filter. | |
4899 In this case subrequest output can be treated as any other explicit request | |
4900 output. | |
4901 This means that eventually the output of a subrequest is sent to the client | |
4902 after all explicit buffers passed prior to subrequest creation and before any | |
4903 buffers passed later. | |
4904 This ordering is preserved even for large hierarchies of subrequests. | |
4905 The following example inserts a subrequest output after all request data | |
4906 buffers, but before the final buffer with the <literal>last_buf</literal> flag. | |
4907 </para> | |
4908 | |
4909 <programlisting> | |
4910 ngx_int_t | |
4911 ngx_http_foo_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
4912 { | |
4913 ngx_int_t rc; | |
4914 ngx_buf_t *b; | |
4915 ngx_uint_t last; | |
4916 ngx_chain_t *cl, out; | |
4917 ngx_http_request_t *sr; | |
4918 ngx_http_foo_filter_ctx_t *ctx; | |
4919 | |
4920 ctx = ngx_http_get_module_ctx(r, ngx_http_foo_filter_module); | |
4921 if (ctx == NULL) { | |
4922 return ngx_http_next_body_filter(r, in); | |
4923 } | |
4924 | |
4925 last = 0; | |
4926 | |
4927 for (cl = in; cl; cl = cl->next) { | |
4928 if (cl->buf->last_buf) { | |
4929 cl->buf->last_buf = 0; | |
4930 cl->buf->last_in_chain = 1; | |
4931 cl->buf->sync = 1; | |
4932 last = 1; | |
4933 } | |
4934 } | |
4935 | |
4936 /* Output explicit output buffers */ | |
4937 | |
4938 rc = ngx_http_next_body_filter(r, in); | |
4939 | |
4940 if (rc == NGX_ERROR || !last) { | |
4941 return rc; | |
4942 } | |
4943 | |
4944 /* | |
4945 * Create the subrequest. The output of the subrequest | |
4946 * will automatically be sent after all preceding buffers, | |
4947 * but before the last_buf buffer passed later in this function. | |
4948 */ | |
4949 | |
4950 if (ngx_http_subrequest(r, ctx->uri, NULL, &sr, NULL, 0) != NGX_OK) { | |
4951 return NGX_ERROR; | |
4952 } | |
4953 | |
4954 ngx_http_set_ctx(r, NULL, ngx_http_foo_filter_module); | |
4955 | |
4956 | |
4957 /* Output the final buffer with the last_buf flag */ | |
4958 | |
4959 b = ngx_calloc_buf(r->pool); | |
4960 if (b == NULL) { | |
4961 return NGX_ERROR; | |
4962 } | |
4963 | |
4964 b->last_buf = 1; | |
4965 | |
4966 out.buf = b; | |
4967 out.next = NULL; | |
4968 | |
4969 return ngx_http_output_filter(r, &out); | |
4970 } | |
4971 </programlisting> | |
4972 | |
4973 <para> | |
4974 A subrequest may also be created for other purposes than data output. | |
4975 For example, the <link doc="../http/ngx_http_auth_request_module.xml"> | |
4976 ngx_http_auth_request_module</link> | |
4977 creates a subrequest at <literal>NGX_HTTP_ACCESS_PHASE</literal> phase. | |
4978 To disable any output at this point, the subrequest | |
4979 <literal>header_only</literal> flag is set. | |
4980 This prevents subrequest body from being sent to the client. | |
4981 Its header is ignored anyway. | |
4982 The result of the subrequest can be analyzed in the callback handler. | |
4736 </para> | 4983 </para> |
4737 | 4984 |
4738 </section> | 4985 </section> |
4739 | 4986 |
4740 | 4987 |