~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/modules/ngx_http_chunked_filter_module.c

Version: ~ [ nginx-1.4.1 ] ~ [ nginx-1.5.0 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  * Copyright (C) Nginx, Inc.
  5  */
  6 
  7 
  8 #include <ngx_config.h>
  9 #include <ngx_core.h>
 10 #include <ngx_http.h>
 11 
 12 
 13 typedef struct {
 14     ngx_chain_t         *free;
 15     ngx_chain_t         *busy;
 16 } ngx_http_chunked_filter_ctx_t;
 17 
 18 
 19 static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf);
 20 
 21 
 22 static ngx_http_module_t  ngx_http_chunked_filter_module_ctx = {
 23     NULL,                                  /* preconfiguration */
 24     ngx_http_chunked_filter_init,          /* postconfiguration */
 25 
 26     NULL,                                  /* create main configuration */
 27     NULL,                                  /* init main configuration */
 28 
 29     NULL,                                  /* create server configuration */
 30     NULL,                                  /* merge server configuration */
 31 
 32     NULL,                                  /* create location configuration */
 33     NULL                                   /* merge location configuration */
 34 };
 35 
 36 
 37 ngx_module_t  ngx_http_chunked_filter_module = {
 38     NGX_MODULE_V1,
 39     &ngx_http_chunked_filter_module_ctx,   /* module context */
 40     NULL,                                  /* module directives */
 41     NGX_HTTP_MODULE,                       /* module type */
 42     NULL,                                  /* init master */
 43     NULL,                                  /* init module */
 44     NULL,                                  /* init process */
 45     NULL,                                  /* init thread */
 46     NULL,                                  /* exit thread */
 47     NULL,                                  /* exit process */
 48     NULL,                                  /* exit master */
 49     NGX_MODULE_V1_PADDING
 50 };
 51 
 52 
 53 static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
 54 static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
 55 
 56 
 57 static ngx_int_t
 58 ngx_http_chunked_header_filter(ngx_http_request_t *r)
 59 {
 60     ngx_http_core_loc_conf_t       *clcf;
 61     ngx_http_chunked_filter_ctx_t  *ctx;
 62 
 63     if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED
 64         || r->headers_out.status == NGX_HTTP_NO_CONTENT
 65         || r->headers_out.status < NGX_HTTP_OK
 66         || r != r->main
 67         || (r->method & NGX_HTTP_HEAD))
 68     {
 69         return ngx_http_next_header_filter(r);
 70     }
 71 
 72     if (r->headers_out.content_length_n == -1) {
 73         if (r->http_version < NGX_HTTP_VERSION_11) {
 74             r->keepalive = 0;
 75 
 76         } else {
 77             clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 78 
 79             if (clcf->chunked_transfer_encoding) {
 80                 r->chunked = 1;
 81 
 82                 ctx = ngx_pcalloc(r->pool,
 83                                   sizeof(ngx_http_chunked_filter_ctx_t));
 84                 if (ctx == NULL) {
 85                     return NGX_ERROR;
 86                 }
 87 
 88                 ngx_http_set_ctx(r, ctx, ngx_http_chunked_filter_module);
 89 
 90             } else {
 91                 r->keepalive = 0;
 92             }
 93         }
 94     }
 95 
 96     return ngx_http_next_header_filter(r);
 97 }
 98 
 99 
100 static ngx_int_t
101 ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
102 {
103     u_char                         *chunk;
104     off_t                           size;
105     ngx_int_t                       rc;
106     ngx_buf_t                      *b;
107     ngx_chain_t                    *out, *cl, *tl, **ll;
108     ngx_http_chunked_filter_ctx_t  *ctx;
109 
110     if (in == NULL || !r->chunked || r->header_only) {
111         return ngx_http_next_body_filter(r, in);
112     }
113 
114     ctx = ngx_http_get_module_ctx(r, ngx_http_chunked_filter_module);
115 
116     out = NULL;
117     ll = &out;
118 
119     size = 0;
120     cl = in;
121 
122     for ( ;; ) {
123         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
124                        "http chunk: %d", ngx_buf_size(cl->buf));
125 
126         size += ngx_buf_size(cl->buf);
127 
128         if (cl->buf->flush
129             || cl->buf->sync
130             || ngx_buf_in_memory(cl->buf)
131             || cl->buf->in_file)
132         {
133             tl = ngx_alloc_chain_link(r->pool);
134             if (tl == NULL) {
135                 return NGX_ERROR;
136             }
137 
138             tl->buf = cl->buf;
139             *ll = tl;
140             ll = &tl->next;
141         }
142 
143         if (cl->next == NULL) {
144             break;
145         }
146 
147         cl = cl->next;
148     }
149 
150     if (size) {
151         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
152         if (tl == NULL) {
153             return NGX_ERROR;
154         }
155 
156         b = tl->buf;
157         chunk = b->start;
158 
159         if (chunk == NULL) {
160             /* the "0000000000000000" is 64-bit hexadecimal string */
161 
162             chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
163             if (chunk == NULL) {
164                 return NGX_ERROR;
165             }
166 
167             b->start = chunk;
168             b->end = chunk + sizeof("0000000000000000" CRLF) - 1;
169         }
170 
171         b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
172         b->memory = 0;
173         b->temporary = 1;
174         b->pos = chunk;
175         b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
176 
177         tl->next = out;
178         out = tl;
179     }
180 
181     if (cl->buf->last_buf) {
182         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
183         if (tl == NULL) {
184             return NGX_ERROR;
185         }
186 
187         b = tl->buf;
188 
189         b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
190         b->temporary = 0;
191         b->memory = 1;
192         b->last_buf = 1;
193         b->pos = (u_char *) CRLF "" CRLF CRLF;
194         b->last = b->pos + 7;
195 
196         cl->buf->last_buf = 0;
197 
198         *ll = tl;
199 
200         if (size == 0) {
201             b->pos += 2;
202         }
203 
204     } else if (size > 0) {
205         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
206         if (tl == NULL) {
207             return NGX_ERROR;
208         }
209 
210         b = tl->buf;
211 
212         b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
213         b->temporary = 0;
214         b->memory = 1;
215         b->pos = (u_char *) CRLF;
216         b->last = b->pos + 2;
217 
218         *ll = tl;
219 
220     } else {
221         *ll = NULL;
222     }
223 
224     rc = ngx_http_next_body_filter(r, out);
225 
226     ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
227                             (ngx_buf_tag_t) &ngx_http_chunked_filter_module);
228 
229     return rc;
230 }
231 
232 
233 static ngx_int_t
234 ngx_http_chunked_filter_init(ngx_conf_t *cf)
235 {
236     ngx_http_next_header_filter = ngx_http_top_header_filter;
237     ngx_http_top_header_filter = ngx_http_chunked_header_filter;
238 
239     ngx_http_next_body_filter = ngx_http_top_body_filter;
240     ngx_http_top_body_filter = ngx_http_chunked_body_filter;
241 
242     return NGX_OK;
243 }
244 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.