blob: 04347c2ce9537455568cd098b90cd8498f183848 [file] [log] [blame]
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +00007#include <ngx_config.h>
8#include <ngx_core.h>
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00009#include <ngx_event.h>
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +000010#include <ngx_http.h>
Igor Sysoeva09f08d2003-04-25 14:43:13 +000011
12
Igor Sysoev899b44e2005-05-12 14:58:06 +000013static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
14static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +000015static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r,
16 ngx_chain_t *body);
17static void ngx_http_finalize_request_body(ngx_http_request_t *r, ngx_int_t rc);
18static void ngx_http_read_discarded_body_handler(ngx_http_request_t *r);
19static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r);
20
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000021
Igor Sysoev02025fd2005-01-18 13:03:58 +000022/*
23 * on completion ngx_http_read_client_request_body() adds to
24 * r->request_body->bufs one or two bufs:
25 * *) one memory buf that was preread in r->header_in;
26 * *) one memory or file buf that contains the rest of the body
27 */
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000028
Igor Sysoevc1571722005-03-19 12:38:37 +000029ngx_int_t
30ngx_http_read_client_request_body(ngx_http_request_t *r,
31 ngx_http_client_body_handler_pt post_handler)
Igor Sysoeva09f08d2003-04-25 14:43:13 +000032{
Igor Sysoev1765f472006-07-07 16:33:19 +000033 size_t preread;
34 ssize_t size;
Igor Sysoev369145c2004-05-28 15:49:23 +000035 ngx_buf_t *b;
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +000036 ngx_chain_t *cl, **next;
Igor Sysoev02025fd2005-01-18 13:03:58 +000037 ngx_http_request_body_t *rb;
Igor Sysoevdbb27762004-04-01 16:20:53 +000038 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev11dbe972004-03-29 17:43:58 +000039
Igor Sysoeve5035392005-08-30 10:55:07 +000040 if (r->request_body || r->discard_body) {
Igor Sysoev899b44e2005-05-12 14:58:06 +000041 post_handler(r);
42 return NGX_OK;
43 }
44
Igor Sysoevc1571722005-03-19 12:38:37 +000045 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
46 if (rb == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +000047 return NGX_HTTP_INTERNAL_SERVER_ERROR;
48 }
49
50 r->request_body = rb;
51
52 if (r->headers_in.content_length_n <= 0) {
53 post_handler(r);
54 return NGX_OK;
55 }
56
57 rb->post_handler = post_handler;
58
59 /*
60 * set by ngx_pcalloc():
61 *
62 * rb->bufs = NULL;
63 * rb->buf = NULL;
64 * rb->rest = 0;
65 */
66
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +000067 preread = r->header_in->last - r->header_in->pos;
Igor Sysoeva09f08d2003-04-25 14:43:13 +000068
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +000069 if (preread) {
Igor Sysoev14f02ed2004-03-26 16:13:01 +000070
71 /* there is the pre-read part of the request body */
72
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +000073 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
74 "http client request body preread %uz", preread);
75
Igor Sysoevc1571722005-03-19 12:38:37 +000076 b = ngx_calloc_buf(r->pool);
77 if (b == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +000078 return NGX_HTTP_INTERNAL_SERVER_ERROR;
79 }
Igor Sysoeva09f08d2003-04-25 14:43:13 +000080
Igor Sysoev369145c2004-05-28 15:49:23 +000081 b->temporary = 1;
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +000082 b->start = r->header_in->pos;
83 b->pos = r->header_in->pos;
84 b->last = r->header_in->last;
85 b->end = r->header_in->end;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000086
Igor Sysoevc1571722005-03-19 12:38:37 +000087 rb->bufs = ngx_alloc_chain_link(r->pool);
88 if (rb->bufs == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +000089 return NGX_HTTP_INTERNAL_SERVER_ERROR;
90 }
91
92 rb->bufs->buf = b;
93 rb->bufs->next = NULL;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000094
Igor Sysoev8f125582006-07-28 15:16:17 +000095 rb->buf = b;
96
Igor Sysoevbb28b6d2006-07-11 13:20:19 +000097 if ((off_t) preread >= r->headers_in.content_length_n) {
Igor Sysoev2b0c76c2003-10-27 21:01:00 +000098
Igor Sysoev14f02ed2004-03-26 16:13:01 +000099 /* the whole request body was pre-read */
100
Igor Sysoev1765f472006-07-07 16:33:19 +0000101 r->header_in->pos += (size_t) r->headers_in.content_length_n;
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000102 r->request_length += r->headers_in.content_length_n;
Igor Sysoev6707ba92004-03-30 15:59:50 +0000103
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000104 if (r->request_body_in_file_only) {
105 if (ngx_http_write_request_body(r, rb->bufs) != NGX_OK) {
106 return NGX_HTTP_INTERNAL_SERVER_ERROR;
107 }
108 }
109
Igor Sysoev02025fd2005-01-18 13:03:58 +0000110 post_handler(r);
Igor Sysoev6707ba92004-03-30 15:59:50 +0000111
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000112 return NGX_OK;
113 }
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000114
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000115 /*
116 * to not consider the body as pipelined request in
117 * ngx_http_set_keepalive()
118 */
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000119 r->header_in->pos = r->header_in->last;
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000120
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000121 r->request_length += preread;
122
123 rb->rest = r->headers_in.content_length_n - preread;
124
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000125 if (rb->rest <= (off_t) (b->end - b->last)) {
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000126
127 /* the whole request body may be placed in r->header_in */
128
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000129 r->read_event_handler = ngx_http_read_client_request_body_handler;
130
131 return ngx_http_do_read_client_request_body(r);
132 }
133
134 next = &rb->bufs->next;
135
136 } else {
137 b = NULL;
138 rb->rest = r->headers_in.content_length_n;
139 next = &rb->bufs;
140 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000141
Igor Sysoevdbb27762004-04-01 16:20:53 +0000142 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
143
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000144 size = clcf->client_body_buffer_size;
145 size += size >> 2;
Igor Sysoev14f02ed2004-03-26 16:13:01 +0000146
Igor Sysoev1765f472006-07-07 16:33:19 +0000147 if (rb->rest < size) {
148 size = (ssize_t) rb->rest;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000149
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000150 if (r->request_body_in_single_buf) {
151 size += preread;
152 }
153
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000154 } else {
Igor Sysoevdbb27762004-04-01 16:20:53 +0000155 size = clcf->client_body_buffer_size;
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000156
157 /* disable copying buffer for r->request_body_in_single_buf */
158 b = NULL;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000159 }
160
Igor Sysoevc1571722005-03-19 12:38:37 +0000161 rb->buf = ngx_create_temp_buf(r->pool, size);
162 if (rb->buf == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000163 return NGX_HTTP_INTERNAL_SERVER_ERROR;
164 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000165
Igor Sysoevc1571722005-03-19 12:38:37 +0000166 cl = ngx_alloc_chain_link(r->pool);
167 if (cl == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000168 return NGX_HTTP_INTERNAL_SERVER_ERROR;
169 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000170
Igor Sysoev02025fd2005-01-18 13:03:58 +0000171 cl->buf = rb->buf;
172 cl->next = NULL;
173
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000174 if (b && r->request_body_in_single_buf) {
175 size = b->last - b->pos;
176 ngx_memcpy(rb->buf->pos, b->pos, size);
177 rb->buf->last += size;
178
179 next = &rb->bufs;
180 }
181
182 *next = cl;
183
184 if (r->request_body_in_file_only || r->request_body_in_single_buf) {
185 rb->to_write = rb->bufs;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000186
187 } else {
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000188 rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000189 }
190
Igor Sysoev899b44e2005-05-12 14:58:06 +0000191 r->read_event_handler = ngx_http_read_client_request_body_handler;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000192
Igor Sysoev899b44e2005-05-12 14:58:06 +0000193 return ngx_http_do_read_client_request_body(r);
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000194}
195
196
Igor Sysoevc1571722005-03-19 12:38:37 +0000197static void
Igor Sysoev899b44e2005-05-12 14:58:06 +0000198ngx_http_read_client_request_body_handler(ngx_http_request_t *r)
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000199{
Igor Sysoev899b44e2005-05-12 14:58:06 +0000200 ngx_int_t rc;
Igor Sysoevae02c192004-03-19 05:25:53 +0000201
Igor Sysoev899b44e2005-05-12 14:58:06 +0000202 if (r->connection->read->timedout) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000203 r->connection->timedout = 1;
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000204 ngx_http_finalize_request_body(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6707ba92004-03-30 15:59:50 +0000205 return;
206 }
207
Igor Sysoev899b44e2005-05-12 14:58:06 +0000208 rc = ngx_http_do_read_client_request_body(r);
Igor Sysoevae02c192004-03-19 05:25:53 +0000209
210 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000211 ngx_http_finalize_request_body(r, rc);
Igor Sysoevae02c192004-03-19 05:25:53 +0000212 }
213}
214
215
Igor Sysoevc1571722005-03-19 12:38:37 +0000216static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +0000217ngx_http_do_read_client_request_body(ngx_http_request_t *r)
Igor Sysoevae02c192004-03-19 05:25:53 +0000218{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000219 size_t size;
220 ssize_t n;
Igor Sysoev369145c2004-05-28 15:49:23 +0000221 ngx_buf_t *b;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000222 ngx_connection_t *c;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000223 ngx_http_request_body_t *rb;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000224 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000225
Igor Sysoev899b44e2005-05-12 14:58:06 +0000226 c = r->connection;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000227 rb = r->request_body;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000228
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000229 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
230 "http read client request body");
231
232 for ( ;; ) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000233 if (rb->buf->last == rb->buf->end) {
234
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000235 if (ngx_http_write_request_body(r, rb->to_write) != NGX_OK) {
Igor Sysoevae02c192004-03-19 05:25:53 +0000236 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000237 }
238
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000239 rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000240 rb->buf->last = rb->buf->start;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000241 }
242
Igor Sysoev02025fd2005-01-18 13:03:58 +0000243 size = rb->buf->end - rb->buf->last;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000244
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000245 if ((off_t) size > rb->rest) {
Igor Sysoev1765f472006-07-07 16:33:19 +0000246 size = (size_t) rb->rest;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000247 }
248
Igor Sysoev02025fd2005-01-18 13:03:58 +0000249 n = c->recv(c, rb->buf->last, size);
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000250
Igor Sysoevae02c192004-03-19 05:25:53 +0000251 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000252 "http client request body recv %z", n);
Igor Sysoevae02c192004-03-19 05:25:53 +0000253
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000254 if (n == NGX_AGAIN) {
Igor Sysoev09c684b2005-11-09 17:25:55 +0000255 break;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000256 }
257
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000258 if (n == 0) {
259 ngx_log_error(NGX_LOG_INFO, c->log, 0,
260 "client closed prematurely connection");
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000261 }
262
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000263 if (n == 0 || n == NGX_ERROR) {
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000264 c->error = 1;
Igor Sysoevae02c192004-03-19 05:25:53 +0000265 return NGX_HTTP_BAD_REQUEST;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000266 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000267
Igor Sysoev02025fd2005-01-18 13:03:58 +0000268 rb->buf->last += n;
269 rb->rest -= n;
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000270 r->request_length += n;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000271
Igor Sysoev02025fd2005-01-18 13:03:58 +0000272 if (rb->rest == 0) {
Igor Sysoev89690bf2004-03-23 06:01:52 +0000273 break;
274 }
275
Igor Sysoev02025fd2005-01-18 13:03:58 +0000276 if (rb->buf->last < rb->buf->end) {
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000277 break;
278 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000279 }
280
Igor Sysoevae02c192004-03-19 05:25:53 +0000281 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev02025fd2005-01-18 13:03:58 +0000282 "http client request body rest %uz", rb->rest);
Igor Sysoevae02c192004-03-19 05:25:53 +0000283
Igor Sysoev02025fd2005-01-18 13:03:58 +0000284 if (rb->rest) {
Igor Sysoev09c684b2005-11-09 17:25:55 +0000285 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
286 ngx_add_timer(c->read, clcf->client_body_timeout);
287
288 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
289 return NGX_HTTP_INTERNAL_SERVER_ERROR;
290 }
291
Igor Sysoevae02c192004-03-19 05:25:53 +0000292 return NGX_AGAIN;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000293 }
294
Igor Sysoev09c684b2005-11-09 17:25:55 +0000295 if (c->read->timer_set) {
296 ngx_del_timer(c->read);
297 }
298
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000299 if (rb->temp_file || r->request_body_in_file_only) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000300
301 /* save the last part */
Igor Sysoev02025fd2005-01-18 13:03:58 +0000302
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000303 if (ngx_http_write_request_body(r, rb->to_write) != NGX_OK) {
Igor Sysoevae02c192004-03-19 05:25:53 +0000304 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000305 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000306
Igor Sysoevc1571722005-03-19 12:38:37 +0000307 b = ngx_calloc_buf(r->pool);
308 if (b == NULL) {
Igor Sysoevae02c192004-03-19 05:25:53 +0000309 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000310 }
311
Igor Sysoev369145c2004-05-28 15:49:23 +0000312 b->in_file = 1;
313 b->file_pos = 0;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000314 b->file_last = rb->temp_file->file.offset;
315 b->file = &rb->temp_file->file;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000316
Igor Sysoev02025fd2005-01-18 13:03:58 +0000317 if (rb->bufs->next) {
318 rb->bufs->next->buf = b;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000319
320 } else {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000321 rb->bufs->buf = b;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000322 }
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000323 }
324
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000325 if (r->request_body_in_file_only && rb->bufs->next) {
326 rb->bufs = rb->bufs->next;
327 }
328
Igor Sysoev02025fd2005-01-18 13:03:58 +0000329 rb->post_handler(r);
Igor Sysoevae02c192004-03-19 05:25:53 +0000330
331 return NGX_OK;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000332}
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000333
334
335static ngx_int_t
336ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body)
337{
338 ssize_t n;
339 ngx_temp_file_t *tf;
340 ngx_http_request_body_t *rb;
341 ngx_http_core_loc_conf_t *clcf;
342
343 rb = r->request_body;
344
345 if (rb->temp_file == NULL) {
346 tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
347 if (tf == NULL) {
348 return NGX_ERROR;
349 }
350
351 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
352
353 tf->file.fd = NGX_INVALID_FILE;
354 tf->file.log = r->connection->log;
355 tf->path = clcf->client_body_temp_path;
356 tf->pool = r->pool;
357 tf->warn = "a client request body is buffered to a temporary file";
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000358 tf->log_level = r->request_body_file_log_level;
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000359 tf->persistent = r->request_body_in_persistent_file;
360
361 if (r->request_body_file_group_access) {
362 tf->mode = 0660;
363 }
364
365 rb->temp_file = tf;
366 }
367
368 n = ngx_write_chain_to_temp_file(rb->temp_file, body);
369
370 /* TODO: n == 0 or not complete and level event */
371
372 if (n == NGX_ERROR) {
373 return NGX_ERROR;
374 }
375
376 rb->temp_file->offset += n;
377
378 return NGX_OK;
379}
380
381
382static void
383ngx_http_finalize_request_body(ngx_http_request_t *r, ngx_int_t rc)
384{
385 if (r->request_body->temp_file
386 && r->request_body_in_persistent_file
387 && r->request_body_delete_incomplete_file)
388 {
389 if (ngx_delete_file(r->request_body->temp_file->file.name.data)
390 == NGX_FILE_ERROR)
391 {
392 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
393 ngx_delete_file_n " \"%s\" failed",
394 r->request_body->temp_file->file.name.data);
395 }
396 }
397
398 ngx_http_finalize_request(r, rc);
399}
400
401
402ngx_int_t
403ngx_http_discard_body(ngx_http_request_t *r)
404{
405 ssize_t size;
406 ngx_event_t *rev;
407
Igor Sysoev08e63d42006-08-14 15:09:38 +0000408 if (r != r->main || r->discard_body) {
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000409 return NGX_OK;
410 }
411
412 rev = r->connection->read;
413
414 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
415
416 if (rev->timer_set) {
417 ngx_del_timer(rev);
418 }
419
Igor Sysoevda173ab2006-08-30 10:39:17 +0000420 r->discard_body = 1;
421
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000422 if (r->headers_in.content_length_n <= 0) {
423 return NGX_OK;
424 }
425
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000426 size = r->header_in->last - r->header_in->pos;
427
428 if (size) {
429 if (r->headers_in.content_length_n > size) {
430 r->headers_in.content_length_n -= size;
431
432 } else {
Igor Sysoev1765f472006-07-07 16:33:19 +0000433 r->header_in->pos += (size_t) r->headers_in.content_length_n;
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000434 r->headers_in.content_length_n = 0;
435 return NGX_OK;
436 }
437 }
438
439 r->read_event_handler = ngx_http_read_discarded_body_handler;
440
441 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
442 return NGX_HTTP_INTERNAL_SERVER_ERROR;
443 }
444
445 return ngx_http_read_discarded_body(r);
446}
447
448
449static void
450ngx_http_read_discarded_body_handler(ngx_http_request_t *r)
451{
452 ngx_int_t rc;
453
454 rc = ngx_http_read_discarded_body(r);
455
456 if (rc == NGX_AGAIN) {
457 if (ngx_handle_read_event(r->connection->read, 0) == NGX_ERROR) {
458 ngx_http_finalize_request(r, rc);
459 return;
460 }
461 }
462
463 if (rc != NGX_OK) {
464 ngx_http_finalize_request(r, rc);
465 }
466}
467
468
469static ngx_int_t
470ngx_http_read_discarded_body(ngx_http_request_t *r)
471{
Igor Sysoev1765f472006-07-07 16:33:19 +0000472 size_t size;
473 ssize_t n;
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000474 u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
475
476 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
477 "http read discarded body");
478
479 if (r->headers_in.content_length_n == 0) {
480 return NGX_OK;
481 }
482
Igor Sysoev1765f472006-07-07 16:33:19 +0000483 size = (r->headers_in.content_length_n > NGX_HTTP_DISCARD_BUFFER_SIZE) ?
484 NGX_HTTP_DISCARD_BUFFER_SIZE:
485 (size_t) r->headers_in.content_length_n;
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000486
487 n = r->connection->recv(r->connection, buffer, size);
488
489 if (n == NGX_ERROR) {
490
491 r->connection->error = 1;
492
493 /*
494 * if a client request body is discarded then we already set
495 * some HTTP response code for client and we can ignore the error
496 */
497
498 return NGX_OK;
499 }
500
501 if (n == NGX_AGAIN) {
502 return NGX_AGAIN;
503 }
504
505 r->headers_in.content_length_n -= n;
506
507 return NGX_OK;
508}