blob: c4aada505e92396b69dd48355a4afa6456470821 [file] [log] [blame]
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +00002#include <ngx_config.h>
3#include <ngx_core.h>
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00004#include <ngx_event.h>
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +00005#include <ngx_http.h>
Igor Sysoeva09f08d2003-04-25 14:43:13 +00006
7
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00008static void ngx_http_read_client_request_body_handler(ngx_event_t *rev);
Igor Sysoevae02c192004-03-19 05:25:53 +00009static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000010
11
Igor Sysoev11dbe972004-03-29 17:43:58 +000012ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r)
Igor Sysoeva09f08d2003-04-25 14:43:13 +000013{
Igor Sysoevdbb27762004-04-01 16:20:53 +000014 ssize_t size;
15 ngx_hunk_t *h;
16 ngx_chain_t *cl;
17 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev11dbe972004-03-29 17:43:58 +000018
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000019 size = r->header_in->last - r->header_in->pos;
Igor Sysoeva09f08d2003-04-25 14:43:13 +000020
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000021 if (size) {
Igor Sysoev14f02ed2004-03-26 16:13:01 +000022
23 /* there is the pre-read part of the request body */
24
Igor Sysoev11dbe972004-03-29 17:43:58 +000025 ngx_test_null(h, ngx_calloc_hunk(r->pool),
26 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoeva09f08d2003-04-25 14:43:13 +000027
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000028 h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
29 h->start = h->pos = r->header_in->pos;
30 h->end = h->last = r->header_in->last;
31
Igor Sysoev11dbe972004-03-29 17:43:58 +000032 ngx_alloc_link_and_set_hunk(r->request_body->bufs, h, r->pool,
33 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000034
35 if (size >= r->headers_in.content_length_n) {
Igor Sysoev2b0c76c2003-10-27 21:01:00 +000036
Igor Sysoev14f02ed2004-03-26 16:13:01 +000037 /* the whole request body was pre-read */
38
39 r->header_in->pos += r->headers_in.content_length_n;
Igor Sysoev6707ba92004-03-30 15:59:50 +000040
41 r->request_body->handler(r->request_body->data);
42
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000043 return NGX_OK;
44 }
Igor Sysoev2b0c76c2003-10-27 21:01:00 +000045
46 r->header_in->pos = r->header_in->last;
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +000047 }
48
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000049
Igor Sysoevdbb27762004-04-01 16:20:53 +000050 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
51
Igor Sysoev11dbe972004-03-29 17:43:58 +000052 r->request_body->rest = r->headers_in.content_length_n - size;
Igor Sysoev14f02ed2004-03-26 16:13:01 +000053
Igor Sysoev11dbe972004-03-29 17:43:58 +000054 if (r->request_body->rest
Igor Sysoevdbb27762004-04-01 16:20:53 +000055 < clcf->client_body_buffer_size
56 + (clcf->client_body_buffer_size >> 2))
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000057 {
Igor Sysoev11dbe972004-03-29 17:43:58 +000058 size = r->request_body->rest;
Igor Sysoeva09f08d2003-04-25 14:43:13 +000059
60 } else {
Igor Sysoevdbb27762004-04-01 16:20:53 +000061 size = clcf->client_body_buffer_size;
Igor Sysoeva09f08d2003-04-25 14:43:13 +000062 }
63
Igor Sysoev11dbe972004-03-29 17:43:58 +000064 ngx_test_null(r->request_body->buf, ngx_create_temp_hunk(r->pool, size),
65 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000066
Igor Sysoev11dbe972004-03-29 17:43:58 +000067 ngx_alloc_link_and_set_hunk(cl, r->request_body->buf, r->pool,
68 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000069
Igor Sysoev11dbe972004-03-29 17:43:58 +000070 if (r->request_body->bufs) {
71 r->request_body->bufs->next = cl;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000072
73 } else {
Igor Sysoev11dbe972004-03-29 17:43:58 +000074 r->request_body->bufs = cl;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000075 }
76
Igor Sysoevae02c192004-03-19 05:25:53 +000077 r->connection->read->event_handler =
78 ngx_http_read_client_request_body_handler;
Igor Sysoeva09f08d2003-04-25 14:43:13 +000079
Igor Sysoevae02c192004-03-19 05:25:53 +000080 return ngx_http_do_read_client_request_body(r);
Igor Sysoeva09f08d2003-04-25 14:43:13 +000081}
82
83
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000084static void ngx_http_read_client_request_body_handler(ngx_event_t *rev)
Igor Sysoeva09f08d2003-04-25 14:43:13 +000085{
Igor Sysoevae02c192004-03-19 05:25:53 +000086 ngx_int_t rc;
87 ngx_connection_t *c;
88 ngx_http_request_t *r;
89
90 c = rev->data;
91 r = c->data;
92
Igor Sysoev6707ba92004-03-30 15:59:50 +000093 if (rev->timedout) {
94 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
95 return;
96 }
97
Igor Sysoevae02c192004-03-19 05:25:53 +000098 rc = ngx_http_do_read_client_request_body(r);
99
100 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
101 ngx_http_finalize_request(r, rc);
102 }
103}
104
105
106static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r)
107{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000108 size_t size;
109 ssize_t n;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000110 ngx_hunk_t *h;
111 ngx_connection_t *c;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000112 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1d8d9ee2003-04-28 15:06:39 +0000113
Igor Sysoevae02c192004-03-19 05:25:53 +0000114 c = r->connection;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000115
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000116 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
117 "http read client request body");
118
119 for ( ;; ) {
Igor Sysoev11dbe972004-03-29 17:43:58 +0000120 if (r->request_body->buf->last == r->request_body->buf->end) {
121 n = ngx_write_chain_to_temp_file(r->request_body->temp_file,
122 r->request_body->bufs->next ? r->request_body->bufs->next:
123 r->request_body->bufs);
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000124
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000125 /* TODO: n == 0 or not complete and level event */
126
127 if (n == NGX_ERROR) {
Igor Sysoevae02c192004-03-19 05:25:53 +0000128 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000129 }
130
Igor Sysoev11dbe972004-03-29 17:43:58 +0000131 r->request_body->temp_file->offset += n;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000132
Igor Sysoev11dbe972004-03-29 17:43:58 +0000133 r->request_body->buf->pos = r->request_body->buf->start;
134 r->request_body->buf->last = r->request_body->buf->start;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000135 }
136
Igor Sysoev11dbe972004-03-29 17:43:58 +0000137 size = r->request_body->buf->end - r->request_body->buf->last;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000138
Igor Sysoev11dbe972004-03-29 17:43:58 +0000139 if (size > r->request_body->rest) {
140 size = r->request_body->rest;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000141 }
142
Igor Sysoev11dbe972004-03-29 17:43:58 +0000143 n = ngx_recv(c, r->request_body->buf->last, size);
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000144
Igor Sysoevae02c192004-03-19 05:25:53 +0000145 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
146 "http client request body recv " SIZE_T_FMT, n);
147
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000148 if (n == NGX_AGAIN) {
149 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevae02c192004-03-19 05:25:53 +0000150 ngx_add_timer(c->read, clcf->client_body_timeout);
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000151
Igor Sysoevae02c192004-03-19 05:25:53 +0000152 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
153 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000154 }
155
Igor Sysoevae02c192004-03-19 05:25:53 +0000156 return NGX_AGAIN;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000157 }
158
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000159 if (n == 0) {
160 ngx_log_error(NGX_LOG_INFO, c->log, 0,
161 "client closed prematurely connection");
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000162 }
163
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000164 if (n == 0 || n == NGX_ERROR) {
Igor Sysoev89690bf2004-03-23 06:01:52 +0000165 r->closed = 1;
Igor Sysoevae02c192004-03-19 05:25:53 +0000166 return NGX_HTTP_BAD_REQUEST;
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000167 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000168
Igor Sysoev11dbe972004-03-29 17:43:58 +0000169 r->request_body->buf->last += n;
170 r->request_body->rest -= n;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000171
Igor Sysoev11dbe972004-03-29 17:43:58 +0000172 if (r->request_body->rest == 0) {
Igor Sysoev89690bf2004-03-23 06:01:52 +0000173 break;
174 }
175
Igor Sysoev11dbe972004-03-29 17:43:58 +0000176 if (r->request_body->buf->last < r->request_body->buf->end) {
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000177 break;
178 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000179 }
180
Igor Sysoevae02c192004-03-19 05:25:53 +0000181 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev11dbe972004-03-29 17:43:58 +0000182 "http client request body rest " SIZE_T_FMT,
183 r->request_body->rest);
Igor Sysoevae02c192004-03-19 05:25:53 +0000184
Igor Sysoev11dbe972004-03-29 17:43:58 +0000185 if (r->request_body->rest) {
Igor Sysoevae02c192004-03-19 05:25:53 +0000186 return NGX_AGAIN;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000187 }
188
Igor Sysoev11dbe972004-03-29 17:43:58 +0000189 if (r->request_body->temp_file->file.fd != NGX_INVALID_FILE) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000190
191 /* save the last part */
Igor Sysoev11dbe972004-03-29 17:43:58 +0000192 n = ngx_write_chain_to_temp_file(r->request_body->temp_file,
193 r->request_body->bufs->next ? r->request_body->bufs->next:
194 r->request_body->bufs);
Igor Sysoevda85f7f2004-03-16 21:26:01 +0000195
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000196 /* TODO: n == 0 or not complete and level event */
197
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000198 if (n == NGX_ERROR) {
Igor Sysoevae02c192004-03-19 05:25:53 +0000199 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000200 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000201
202 h = ngx_calloc_hunk(r->pool);
203 if (h == NULL) {
Igor Sysoevae02c192004-03-19 05:25:53 +0000204 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000205 }
206
207 h->type = NGX_HUNK_FILE;
208 h->file_pos = 0;
Igor Sysoev11dbe972004-03-29 17:43:58 +0000209 h->file_last = r->request_body->temp_file->file.offset;
210 h->file = &r->request_body->temp_file->file;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000211
Igor Sysoev11dbe972004-03-29 17:43:58 +0000212 if (r->request_body->bufs->next) {
213 r->request_body->bufs->next->hunk = h;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000214
215 } else {
Igor Sysoev11dbe972004-03-29 17:43:58 +0000216 r->request_body->bufs->hunk = h;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000217 }
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000218 }
219
Igor Sysoev11dbe972004-03-29 17:43:58 +0000220 r->request_body->handler(r->request_body->data);
Igor Sysoevae02c192004-03-19 05:25:53 +0000221
222 return NGX_OK;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000223}