Mercurial > hg > nginx-site
comparison xml/en/docs/dev/development_guide.xml @ 1960:9550ea66abdd
HTTP response section of the development guide.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 10 Apr 2017 15:09:06 +0300 |
parents | d0aebb2337ec |
children | ef27e3ef0c46 |
comparison
equal
deleted
inserted
replaced
1959:d0aebb2337ec | 1960:9550ea66abdd |
---|---|
4632 </para> | 4632 </para> |
4633 | 4633 |
4634 </section> | 4634 </section> |
4635 | 4635 |
4636 | 4636 |
4637 <section name="Response" id="http_response"> | |
4638 | |
4639 <para> | |
4640 An HTTP response in nginx is produced by sending the response header followed by | |
4641 the optional response body. | |
4642 Both header and body are passed through a chain of filters and eventually get | |
4643 written to the client socket. | |
4644 An nginx module can install its handler into the header or body filter chain | |
4645 and process the output coming from the previous handler. | |
4646 </para> | |
4647 | |
4648 | |
4649 <section name="Response header" id="http_response_header"> | |
4650 | |
4651 <para> | |
4652 Output header is sent by the function | |
4653 <literal>ngx_http_send_header(r)</literal>. | |
4654 Prior to calling this function, <literal>r->headers_out</literal> should contain | |
4655 all the data required to produce the HTTP response header. | |
4656 It's always required to set the <literal>status</literal> field of | |
4657 <literal>r->headers_out</literal>. | |
4658 If the response status suggests that a response body follows the header, | |
4659 <literal>content_length_n</literal> can be set as well. | |
4660 The default value for this field is -1, which means that the body size is | |
4661 unknown. | |
4662 In this case, chunked transfer encoding is used. | |
4663 To output an arbitrary header, <literal>headers</literal> list should be | |
4664 appended. | |
4665 </para> | |
4666 | |
4667 <programlisting> | |
4668 static ngx_int_t | |
4669 ngx_http_foo_content_handler(ngx_http_request_t *r) | |
4670 { | |
4671 ngx_int_t rc; | |
4672 ngx_table_elt_t *h; | |
4673 | |
4674 /* send header */ | |
4675 | |
4676 r->headers_out.status = NGX_HTTP_OK; | |
4677 r->headers_out.content_length_n = 3; | |
4678 | |
4679 /* X-Foo: foo */ | |
4680 | |
4681 h = ngx_list_push(&r->headers_out.headers); | |
4682 if (h == NULL) { | |
4683 return NGX_ERROR; | |
4684 } | |
4685 | |
4686 h->hash = 1; | |
4687 ngx_str_set(&h->key, "X-Foo"); | |
4688 ngx_str_set(&h->value, "foo"); | |
4689 | |
4690 rc = ngx_http_send_header(r); | |
4691 | |
4692 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
4693 return rc; | |
4694 } | |
4695 | |
4696 /* send body */ | |
4697 | |
4698 ... | |
4699 } | |
4700 </programlisting> | |
4701 | |
4702 </section> | |
4703 | |
4704 | |
4705 <section name="Header filters" id="http_header_filters"> | |
4706 | |
4707 <para> | |
4708 The <literal>ngx_http_send_header(r)</literal> function invokes the header | |
4709 filter chain by calling the top header filter handler | |
4710 <literal>ngx_http_top_header_filter</literal>. | |
4711 It's assumed that every header handler calls the next handler in chain until | |
4712 the final handler <literal>ngx_http_header_filter(r)</literal> is called. | |
4713 The final header handler constructs the HTTP response based on | |
4714 <literal>r->headers_out</literal> and passes it to the | |
4715 <literal>ngx_http_writer_filter</literal> for output. | |
4716 </para> | |
4717 | |
4718 <para> | |
4719 To add a handler to the header filter chain, one should store its address in | |
4720 <literal>ngx_http_top_header_filter</literal> global variable at configuration | |
4721 time. | |
4722 The previous handler address is normally stored in a module's static variable | |
4723 and is called by the newly added handler before exiting. | |
4724 </para> | |
4725 | |
4726 <para> | |
4727 The following is an example header filter module, adding the HTTP header | |
4728 "X-Foo: foo" to every output with the status 200. | |
4729 </para> | |
4730 | |
4731 <programlisting> | |
4732 #include <ngx_config.h> | |
4733 #include <ngx_core.h> | |
4734 #include <ngx_http.h> | |
4735 | |
4736 | |
4737 static ngx_int_t ngx_http_foo_header_filter(ngx_http_request_t *r); | |
4738 static ngx_int_t ngx_http_foo_header_filter_init(ngx_conf_t *cf); | |
4739 | |
4740 | |
4741 static ngx_http_module_t ngx_http_foo_header_filter_module_ctx = { | |
4742 NULL, /* preconfiguration */ | |
4743 ngx_http_foo_header_filter_init, /* postconfiguration */ | |
4744 | |
4745 NULL, /* create main configuration */ | |
4746 NULL, /* init main configuration */ | |
4747 | |
4748 NULL, /* create server configuration */ | |
4749 NULL, /* merge server configuration */ | |
4750 | |
4751 NULL, /* create location configuration */ | |
4752 NULL /* merge location configuration */ | |
4753 }; | |
4754 | |
4755 | |
4756 ngx_module_t ngx_http_foo_header_filter_module = { | |
4757 NGX_MODULE_V1, | |
4758 &ngx_http_foo_header_filter_module_ctx, /* module context */ | |
4759 NULL, /* module directives */ | |
4760 NGX_HTTP_MODULE, /* module type */ | |
4761 NULL, /* init master */ | |
4762 NULL, /* init module */ | |
4763 NULL, /* init process */ | |
4764 NULL, /* init thread */ | |
4765 NULL, /* exit thread */ | |
4766 NULL, /* exit process */ | |
4767 NULL, /* exit master */ | |
4768 NGX_MODULE_V1_PADDING | |
4769 }; | |
4770 | |
4771 | |
4772 static ngx_http_output_header_filter_pt ngx_http_next_header_filter; | |
4773 | |
4774 | |
4775 static ngx_int_t | |
4776 ngx_http_foo_header_filter(ngx_http_request_t *r) | |
4777 { | |
4778 ngx_table_elt_t *h; | |
4779 | |
4780 /* | |
4781 * The filter handler adds "X-Foo: foo" header | |
4782 * to every HTTP 200 response | |
4783 */ | |
4784 | |
4785 if (r->headers_out.status != NGX_HTTP_OK) { | |
4786 return ngx_http_next_header_filter(r); | |
4787 } | |
4788 | |
4789 h = ngx_list_push(&r->headers_out.headers); | |
4790 if (h == NULL) { | |
4791 return NGX_ERROR; | |
4792 } | |
4793 | |
4794 h->hash = 1; | |
4795 ngx_str_set(&h->key, "X-Foo"); | |
4796 ngx_str_set(&h->value, "foo"); | |
4797 | |
4798 return ngx_http_next_header_filter(r); | |
4799 } | |
4800 | |
4801 | |
4802 static ngx_int_t | |
4803 ngx_http_foo_header_filter_init(ngx_conf_t *cf) | |
4804 { | |
4805 ngx_http_next_header_filter = ngx_http_top_header_filter; | |
4806 ngx_http_top_header_filter = ngx_http_foo_header_filter; | |
4807 | |
4808 return NGX_OK; | |
4809 } | |
4810 </programlisting> | |
4811 | |
4812 </section> | |
4813 | |
4814 </section> | |
4815 | |
4816 | |
4817 <section name="Response body" id="http_response_body"> | |
4818 | |
4819 <para> | |
4820 Response body is sent by calling the function | |
4821 <literal>ngx_http_output_filter(r, cl)</literal>. | |
4822 The function can be called multiple times. | |
4823 Each time it sends a part of the response body passed as a buffer chain. | |
4824 The last body buffer should have the <literal>last_buf</literal> flag set. | |
4825 </para> | |
4826 | |
4827 <para> | |
4828 The following example produces a complete HTTP output with "foo" as its body. | |
4829 In order for the example to work not only as a main request but as a subrequest | |
4830 as well, the <literal>last_in_chain_flag</literal> is set in the last buffer | |
4831 of the output. | |
4832 The <literal>last_buf</literal> flag is set only for the main request since | |
4833 a subrequest's last buffers does not end the entire output. | |
4834 </para> | |
4835 | |
4836 <programlisting> | |
4837 static ngx_int_t | |
4838 ngx_http_bar_content_handler(ngx_http_request_t *r) | |
4839 { | |
4840 ngx_int_t rc; | |
4841 ngx_buf_t *b; | |
4842 ngx_chain_t out; | |
4843 | |
4844 /* send header */ | |
4845 | |
4846 r->headers_out.status = NGX_HTTP_OK; | |
4847 r->headers_out.content_length_n = 3; | |
4848 | |
4849 rc = ngx_http_send_header(r); | |
4850 | |
4851 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
4852 return rc; | |
4853 } | |
4854 | |
4855 /* send body */ | |
4856 | |
4857 b = ngx_calloc_buf(r->pool); | |
4858 if (b == NULL) { | |
4859 return NGX_ERROR; | |
4860 } | |
4861 | |
4862 b->last_buf = (r == r->main) ? 1: 0; | |
4863 b->last_in_chain = 1; | |
4864 | |
4865 b->memory = 1; | |
4866 | |
4867 b->pos = (u_char *) "foo"; | |
4868 b->last = b->pos + 3; | |
4869 | |
4870 out.buf = b; | |
4871 out.next = NULL; | |
4872 | |
4873 return ngx_http_output_filter(r, &out); | |
4874 } | |
4875 </programlisting> | |
4876 | |
4877 </section> | |
4878 | |
4879 | |
4880 <section name="Body filters" id="http_body_filters"> | |
4881 | |
4882 <para> | |
4883 The function <literal>ngx_http_output_filter(r, cl)</literal> invokes the | |
4884 body filter chain by calling the top body filter handler | |
4885 <literal>ngx_http_top_body_filter</literal>. | |
4886 It's assumed that every body handler calls the next handler in chain until | |
4887 the final handler <literal>ngx_http_write_filter(r, cl)</literal> is called. | |
4888 </para> | |
4889 | |
4890 <para> | |
4891 A body filter handler receives a chain of buffers. | |
4892 The handler is supposed to process the buffers and pass a possibly new chain to | |
4893 the next handler. | |
4894 It's worth noting that the chain links <literal>ngx_chain_t</literal> of the | |
4895 incoming chain belong to the caller. | |
4896 They should never be reused or changed. | |
4897 Right after the handler completes, the caller can use its output chain links | |
4898 to keep track of the buffers it has sent. | |
4899 To save the buffer chain or to substitute some buffers before sending further, | |
4900 a handler should allocate its own chain links. | |
4901 </para> | |
4902 | |
4903 <para> | |
4904 Following is the example of a simple body filter counting the number of | |
4905 body bytes. | |
4906 The result is available as the <literal>$counter</literal> variable which can be | |
4907 used in the access log. | |
4908 </para> | |
4909 | |
4910 <programlisting> | |
4911 #include <ngx_config.h> | |
4912 #include <ngx_core.h> | |
4913 #include <ngx_http.h> | |
4914 | |
4915 | |
4916 typedef struct { | |
4917 off_t count; | |
4918 } ngx_http_counter_filter_ctx_t; | |
4919 | |
4920 | |
4921 static ngx_int_t ngx_http_counter_body_filter(ngx_http_request_t *r, | |
4922 ngx_chain_t *in); | |
4923 static ngx_int_t ngx_http_counter_variable(ngx_http_request_t *r, | |
4924 ngx_http_variable_value_t *v, uintptr_t data); | |
4925 static ngx_int_t ngx_http_counter_add_variables(ngx_conf_t *cf); | |
4926 static ngx_int_t ngx_http_counter_filter_init(ngx_conf_t *cf); | |
4927 | |
4928 | |
4929 static ngx_http_module_t ngx_http_counter_filter_module_ctx = { | |
4930 ngx_http_counter_add_variables, /* preconfiguration */ | |
4931 ngx_http_counter_filter_init, /* postconfiguration */ | |
4932 | |
4933 NULL, /* create main configuration */ | |
4934 NULL, /* init main configuration */ | |
4935 | |
4936 NULL, /* create server configuration */ | |
4937 NULL, /* merge server configuration */ | |
4938 | |
4939 NULL, /* create location configuration */ | |
4940 NULL /* merge location configuration */ | |
4941 }; | |
4942 | |
4943 | |
4944 ngx_module_t ngx_http_counter_filter_module = { | |
4945 NGX_MODULE_V1, | |
4946 &ngx_http_counter_filter_module_ctx, /* module context */ | |
4947 NULL, /* module directives */ | |
4948 NGX_HTTP_MODULE, /* module type */ | |
4949 NULL, /* init master */ | |
4950 NULL, /* init module */ | |
4951 NULL, /* init process */ | |
4952 NULL, /* init thread */ | |
4953 NULL, /* exit thread */ | |
4954 NULL, /* exit process */ | |
4955 NULL, /* exit master */ | |
4956 NGX_MODULE_V1_PADDING | |
4957 }; | |
4958 | |
4959 | |
4960 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; | |
4961 | |
4962 static ngx_str_t ngx_http_counter_name = ngx_string("counter"); | |
4963 | |
4964 | |
4965 static ngx_int_t | |
4966 ngx_http_counter_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
4967 { | |
4968 ngx_chain_t *cl; | |
4969 ngx_http_counter_filter_ctx_t *ctx; | |
4970 | |
4971 ctx = ngx_http_get_module_ctx(r, ngx_http_counter_filter_module); | |
4972 if (ctx == NULL) { | |
4973 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_counter_filter_ctx_t)); | |
4974 if (ctx == NULL) { | |
4975 return NGX_ERROR; | |
4976 } | |
4977 | |
4978 ngx_http_set_ctx(r, ctx, ngx_http_counter_filter_module); | |
4979 } | |
4980 | |
4981 for (cl = in; cl; cl = cl->next) { | |
4982 ctx->count += ngx_buf_size(cl->buf); | |
4983 } | |
4984 | |
4985 return ngx_http_next_body_filter(r, in); | |
4986 } | |
4987 | |
4988 | |
4989 static ngx_int_t | |
4990 ngx_http_counter_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
4991 uintptr_t data) | |
4992 { | |
4993 u_char *p; | |
4994 ngx_http_counter_filter_ctx_t *ctx; | |
4995 | |
4996 ctx = ngx_http_get_module_ctx(r, ngx_http_counter_filter_module); | |
4997 if (ctx == NULL) { | |
4998 v->not_found = 1; | |
4999 return NGX_OK; | |
5000 } | |
5001 | |
5002 p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN); | |
5003 if (p == NULL) { | |
5004 return NGX_ERROR; | |
5005 } | |
5006 | |
5007 v->data = p; | |
5008 v->len = ngx_sprintf(p, "%O", ctx->count) - p; | |
5009 v->valid = 1; | |
5010 v->no_cacheable = 0; | |
5011 v->not_found = 0; | |
5012 | |
5013 return NGX_OK; | |
5014 } | |
5015 | |
5016 | |
5017 static ngx_int_t | |
5018 ngx_http_counter_add_variables(ngx_conf_t *cf) | |
5019 { | |
5020 ngx_http_variable_t *var; | |
5021 | |
5022 var = ngx_http_add_variable(cf, &ngx_http_counter_name, 0); | |
5023 if (var == NULL) { | |
5024 return NGX_ERROR; | |
5025 } | |
5026 | |
5027 var->get_handler = ngx_http_counter_variable; | |
5028 | |
5029 return NGX_OK; | |
5030 } | |
5031 | |
5032 | |
5033 static ngx_int_t | |
5034 ngx_http_counter_filter_init(ngx_conf_t *cf) | |
5035 { | |
5036 ngx_http_next_body_filter = ngx_http_top_body_filter; | |
5037 ngx_http_top_body_filter = ngx_http_counter_body_filter; | |
5038 | |
5039 return NGX_OK; | |
5040 } | |
5041 </programlisting> | |
5042 | |
5043 </section> | |
5044 | |
5045 | |
5046 <section name="Building filter modules" id="http_building_filter_modules"> | |
5047 | |
5048 <para> | |
5049 When writing a body or header filter, a special care should be taken of the | |
5050 filters order. | |
5051 There's a number of header and body filters registered by nginx standard | |
5052 modules. | |
5053 It's important to register a filter module in the right place in respect to | |
5054 other filters. | |
5055 Normally, filters are registered by modules in their postconfiguration handlers. | |
5056 The order in which filters are called is obviously the reverse of when they are | |
5057 registered. | |
5058 </para> | |
5059 | |
5060 <para> | |
5061 A special slot <literal>HTTP_AUX_FILTER_MODULES</literal> for third-party filter | |
5062 modules is provided by nginx. | |
5063 To register a filter module in this slot, the <literal>ngx_module_type</literal> | |
5064 variable should be set to the value of <literal>HTTP_AUX_FILTER</literal> in | |
5065 module's configuration. | |
5066 </para> | |
5067 | |
5068 <para> | |
5069 The following example shows a filter module config file assuming it only has | |
5070 one source file <literal>ngx_http_foo_filter_module.c</literal> | |
5071 </para> | |
5072 | |
5073 <programlisting> | |
5074 ngx_module_type=HTTP_AUX_FILTER | |
5075 ngx_module_name=ngx_http_foo_filter_module | |
5076 ngx_module_srcs="$ngx_addon_dir/ngx_http_foo_filter_module.c" | |
5077 | |
5078 . auto/module | |
5079 </programlisting> | |
5080 | |
5081 </section> | |
5082 | |
5083 | |
5084 <section name="Buffer reuse" id="http_body_buffers_reuse"> | |
5085 | |
5086 <para> | |
5087 When issuing or altering a stream of buffers, it's often desirable to reuse the | |
5088 allocated buffers. | |
5089 A standard approach widely adopted in nginx code is to keep two buffer chains | |
5090 for this purpose: <literal>free</literal> and <literal>busy</literal>. | |
5091 The <literal>free</literal> chain keeps all free buffers. | |
5092 These buffers can be reused. | |
5093 The <literal>busy</literal> chain keeps all buffers sent by the current | |
5094 module which are still in use by some other filter handler. | |
5095 A buffer is considered in use if its size is greater than zero. | |
5096 Normally, when a buffer is consumed by a filter, its <literal>pos</literal> | |
5097 (or <literal>file_pos</literal> for a file buffer) is moved towards | |
5098 <literal>last</literal> (<literal>file_last</literal> for a file buffer). | |
5099 Once a buffer is completely consumed, it's ready to be reused. | |
5100 To update the <literal>free</literal> chain with newly freed buffers, | |
5101 it's enough to iterate over the <literal>busy</literal> chain and move the zero | |
5102 size buffers at the head of it to <literal>free</literal>. | |
5103 This operation is so common that there is a special function | |
5104 <literal>ngx_chain_update_chains(free, busy, out, tag)</literal> which does | |
5105 this. | |
5106 The function appends the output chain <literal>out</literal> to | |
5107 <literal>busy</literal> and moves free buffers from the top of | |
5108 <literal>busy</literal> to <literal>free</literal>. | |
5109 Only the buffers with the given <literal>tag</literal> are reused. | |
5110 This lets a module reuse only the buffers allocated by itself. | |
5111 </para> | |
5112 | |
5113 <para> | |
5114 The following example is a body filter inserting the “foo” string before each | |
5115 incoming buffer. | |
5116 The new buffers allocated by the module are reused if possible. | |
5117 Note that for this example to work properly, it's also required to set up a | |
5118 header filter and reset <literal>content_length_n</literal> to -1, which is | |
5119 beyond the scope of this section. | |
5120 </para> | |
5121 | |
5122 <programlisting> | |
5123 typedef struct { | |
5124 ngx_chain_t *free; | |
5125 ngx_chain_t *busy; | |
5126 } ngx_http_foo_filter_ctx_t; | |
5127 | |
5128 | |
5129 ngx_int_t | |
5130 ngx_http_foo_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
5131 { | |
5132 ngx_int_t rc; | |
5133 ngx_buf_t *b; | |
5134 ngx_chain_t *cl, *tl, *out, **ll; | |
5135 ngx_http_foo_filter_ctx_t *ctx; | |
5136 | |
5137 ctx = ngx_http_get_module_ctx(r, ngx_http_foo_filter_module); | |
5138 if (ctx == NULL) { | |
5139 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_foo_filter_ctx_t)); | |
5140 if (ctx == NULL) { | |
5141 return NGX_ERROR; | |
5142 } | |
5143 | |
5144 ngx_http_set_ctx(r, ctx, ngx_http_foo_filter_module); | |
5145 } | |
5146 | |
5147 /* create a new chain "out" from "in" with all the changes */ | |
5148 | |
5149 ll = &out; | |
5150 | |
5151 for (cl = in; cl; cl = cl->next) { | |
5152 | |
5153 /* append "foo" in a reused buffer if possible */ | |
5154 | |
5155 tl = ngx_chain_get_free_buf(r->pool, &ctx->free); | |
5156 if (tl == NULL) { | |
5157 return NGX_ERROR; | |
5158 } | |
5159 | |
5160 b = tl->buf; | |
5161 b->tag = (ngx_buf_tag_t) &ngx_http_foo_filter_module; | |
5162 b->memory = 1; | |
5163 b->pos = (u_char *) "foo"; | |
5164 b->last = b->pos + 3; | |
5165 | |
5166 *ll = tl; | |
5167 ll = &tl->next; | |
5168 | |
5169 /* append the next incoming buffer */ | |
5170 | |
5171 tl = ngx_alloc_chain_link(r->pool); | |
5172 if (tl == NULL) { | |
5173 return NGX_ERROR; | |
5174 } | |
5175 | |
5176 tl->buf = cl->buf; | |
5177 *ll = tl; | |
5178 ll = &tl->next; | |
5179 } | |
5180 | |
5181 *ll = NULL; | |
5182 | |
5183 /* send the new chain */ | |
5184 | |
5185 rc = ngx_http_next_body_filter(r, out); | |
5186 | |
5187 /* update "busy" and "free" chains for reuse */ | |
5188 | |
5189 ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out, | |
5190 (ngx_buf_tag_t) &ngx_http_foo_filter_module); | |
5191 | |
5192 return rc; | |
5193 } | |
5194 </programlisting> | |
5195 | |
5196 </section> | |
5197 | |
5198 | |
4637 <section name="Load balancing" id="http_load_balancing"> | 5199 <section name="Load balancing" id="http_load_balancing"> |
4638 | 5200 |
4639 <para> | 5201 <para> |
4640 The | 5202 The |
4641 <link doc="../http/ngx_http_upstream_module.xml">ngx_http_upstream_module</link> | 5203 <link doc="../http/ngx_http_upstream_module.xml">ngx_http_upstream_module</link> |