comparison src/http/ngx_http_request_body.c @ 28:7ca9bdc82b3f NGINX_0_1_14

nginx 0.1.14 *) Feature: the autoconfiguration directives: --http-client-body-temp-path=PATH, --http-proxy-temp-path=PATH, and --http-fastcgi-temp-path=PATH *) Change: the directory name for the temporary files with the client request body is specified by directive client_body_temp_path, by default it is <prefix>/client_body_temp. *) Feature: the ngx_http_fastcgi_module and the directives: fastcgi_pass, fastcgi_root, fastcgi_index, fastcgi_params, fastcgi_connect_timeout, fastcgi_send_timeout, fastcgi_read_timeout, fastcgi_send_lowat, fastcgi_header_buffer_size, fastcgi_buffers, fastcgi_busy_buffers_size, fastcgi_temp_path, fastcgi_max_temp_file_size, fastcgi_temp_file_write_size, fastcgi_next_upstream, and fastcgi_x_powered_by. *) Bugfix: the "[alert] zero size buf" error; bug appeared in 0.1.3. *) Change: the URI must be specified after the host name in the proxy_pass directive. *) Change: the %3F symbol in the URI was considered as the argument string start. *) Feature: the unix domain sockets support in the ngx_http_proxy_module. *) Feature: the ssl_engine and ssl_ciphers directives. Thanks to Sergey Skvortsov for SSL-accelerator.
author Igor Sysoev <http://sysoev.ru>
date Tue, 18 Jan 2005 00:00:00 +0300
parents 420dd3f9e703
children 72eb30262aac
comparison
equal deleted inserted replaced
27:66901c2556fd 28:7ca9bdc82b3f
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <ngx_http.h> 10 #include <ngx_http.h>
11 11
12 12
13 static void ngx_http_read_client_request_body_handler(ngx_event_t *rev); 13 static void ngx_http_read_client_request_body_handler(ngx_event_t *rev);
14 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r); 14 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r,
15 15 ngx_connection_t *c);
16 16
17 ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r) 17 /*
18 * on completion ngx_http_read_client_request_body() adds to
19 * r->request_body->bufs one or two bufs:
20 * *) one memory buf that was preread in r->header_in;
21 * *) one memory or file buf that contains the rest of the body
22 */
23
24 ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,
25 ngx_http_client_body_handler_pt post_handler)
26
18 { 27 {
19 ssize_t size; 28 ssize_t size;
20 ngx_buf_t *b; 29 ngx_buf_t *b;
21 ngx_chain_t *cl; 30 ngx_chain_t *cl;
31 ngx_http_request_body_t *rb;
22 ngx_http_core_loc_conf_t *clcf; 32 ngx_http_core_loc_conf_t *clcf;
23 33
34 if (!(rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)))) {
35 return NGX_HTTP_INTERNAL_SERVER_ERROR;
36 }
37
38 r->request_body = rb;
39
40 if (r->headers_in.content_length_n <= 0) {
41 post_handler(r);
42 return NGX_OK;
43 }
44
45 rb->post_handler = post_handler;
46
47 /*
48 * set by ngx_pcalloc():
49 *
50 * rb->bufs = NULL;
51 * rb->buf = NULL;
52 * rb->rest = 0;
53 */
54
24 size = r->header_in->last - r->header_in->pos; 55 size = r->header_in->last - r->header_in->pos;
25 56
26 if (size) { 57 if (size) {
27 58
28 /* there is the pre-read part of the request body */ 59 /* there is the pre-read part of the request body */
29 60
30 ngx_test_null(b, ngx_calloc_buf(r->pool), 61 if (!(b = ngx_calloc_buf(r->pool))) {
31 NGX_HTTP_INTERNAL_SERVER_ERROR); 62 return NGX_HTTP_INTERNAL_SERVER_ERROR;
63 }
32 64
33 b->temporary = 1; 65 b->temporary = 1;
34 b->start = b->pos = r->header_in->pos; 66 b->start = b->pos = r->header_in->pos;
35 b->end = b->last = r->header_in->last; 67 b->end = b->last = r->header_in->last;
36 68
37 ngx_alloc_link_and_set_buf(r->request_body->bufs, b, r->pool, 69 if (!(rb->bufs = ngx_alloc_chain_link(r->pool))) {
38 NGX_HTTP_INTERNAL_SERVER_ERROR); 70 return NGX_HTTP_INTERNAL_SERVER_ERROR;
71 }
72
73 rb->bufs->buf = b;
74 rb->bufs->next = NULL;
39 75
40 if (size >= r->headers_in.content_length_n) { 76 if (size >= r->headers_in.content_length_n) {
41 77
42 /* the whole request body was pre-read */ 78 /* the whole request body was pre-read */
43 79
44 r->header_in->pos += r->headers_in.content_length_n; 80 r->header_in->pos += r->headers_in.content_length_n;
45 r->request_length += r->headers_in.content_length_n; 81 r->request_length += r->headers_in.content_length_n;
46 82
47 r->request_body->handler(r->request_body->data); 83 post_handler(r);
48 84
49 return NGX_OK; 85 return NGX_OK;
50 } 86 }
51 87
52 r->header_in->pos = r->header_in->last; 88 r->header_in->pos = r->header_in->last;
54 } 90 }
55 91
56 92
57 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 93 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
58 94
59 r->request_body->rest = r->headers_in.content_length_n - size; 95 rb->rest = r->headers_in.content_length_n - size;
60 96
61 if (r->request_body->rest 97 if (rb->rest < clcf->client_body_buffer_size
62 < clcf->client_body_buffer_size
63 + (clcf->client_body_buffer_size >> 2)) 98 + (clcf->client_body_buffer_size >> 2))
64 { 99 {
65 size = r->request_body->rest; 100 size = rb->rest;
66 101
67 } else { 102 } else {
68 size = clcf->client_body_buffer_size; 103 size = clcf->client_body_buffer_size;
69 } 104 }
70 105
71 ngx_test_null(r->request_body->buf, ngx_create_temp_buf(r->pool, size), 106 if (!(rb->buf = ngx_create_temp_buf(r->pool, size))) {
72 NGX_HTTP_INTERNAL_SERVER_ERROR); 107 return NGX_HTTP_INTERNAL_SERVER_ERROR;
73 108 }
74 ngx_alloc_link_and_set_buf(cl, r->request_body->buf, r->pool, 109
75 NGX_HTTP_INTERNAL_SERVER_ERROR); 110 if (!(cl = ngx_alloc_chain_link(r->pool))) {
76 111 return NGX_HTTP_INTERNAL_SERVER_ERROR;
77 if (r->request_body->bufs) { 112 }
78 r->request_body->bufs->next = cl; 113
114 cl->buf = rb->buf;
115 cl->next = NULL;
116
117 if (rb->bufs) {
118 rb->bufs->next = cl;
79 119
80 } else { 120 } else {
81 r->request_body->bufs = cl; 121 rb->bufs = cl;
82 } 122 }
83 123
84 r->connection->read->event_handler = 124 r->connection->read->event_handler =
85 ngx_http_read_client_request_body_handler; 125 ngx_http_read_client_request_body_handler;
86 126
87 return ngx_http_do_read_client_request_body(r); 127 return ngx_http_do_read_client_request_body(r, r->connection);
88 } 128 }
89 129
90 130
91 static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) 131 static void ngx_http_read_client_request_body_handler(ngx_event_t *rev)
92 { 132 {
100 if (rev->timedout) { 140 if (rev->timedout) {
101 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); 141 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
102 return; 142 return;
103 } 143 }
104 144
105 rc = ngx_http_do_read_client_request_body(r); 145 rc = ngx_http_do_read_client_request_body(r, c);
106 146
107 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { 147 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
108 ngx_http_finalize_request(r, rc); 148 ngx_http_finalize_request(r, rc);
109 } 149 }
110 } 150 }
111 151
112 152
113 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r) 153 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r,
154 ngx_connection_t *c)
114 { 155 {
115 size_t size; 156 size_t size;
116 ssize_t n; 157 ssize_t n;
117 ngx_buf_t *b; 158 ngx_buf_t *b;
118 ngx_connection_t *c; 159 ngx_temp_file_t *tf;
160 ngx_http_request_body_t *rb;
119 ngx_http_core_loc_conf_t *clcf; 161 ngx_http_core_loc_conf_t *clcf;
120 162
121 c = r->connection; 163 rb = r->request_body;
122 164
123 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, 165 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
124 "http read client request body"); 166 "http read client request body");
125 167
126 for ( ;; ) { 168 for ( ;; ) {
127 if (r->request_body->buf->last == r->request_body->buf->end) { 169 if (rb->buf->last == rb->buf->end) {
128 n = ngx_write_chain_to_temp_file(r->request_body->temp_file, 170
129 r->request_body->bufs->next ? r->request_body->bufs->next: 171 if (rb->temp_file == NULL) {
130 r->request_body->bufs); 172 if (!(tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)))) {
173 return NGX_ERROR;
174 }
175
176 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
177
178 tf->file.fd = NGX_INVALID_FILE;
179 tf->file.log = r->connection->log;
180 tf->path = clcf->client_body_temp_path;
181 tf->pool = r->pool;
182 tf->warn = "a client request body is buffered "
183 "to a temporary file";
184
185 rb->temp_file = tf;
186
187 }
188
189 n = ngx_write_chain_to_temp_file(rb->temp_file,
190 rb->bufs->next ? rb->bufs->next:
191 rb->bufs);
131 192
132 /* TODO: n == 0 or not complete and level event */ 193 /* TODO: n == 0 or not complete and level event */
133 194
134 if (n == NGX_ERROR) { 195 if (n == NGX_ERROR) {
135 return NGX_HTTP_INTERNAL_SERVER_ERROR; 196 return NGX_HTTP_INTERNAL_SERVER_ERROR;
136 } 197 }
137 198
138 r->request_body->temp_file->offset += n; 199 rb->temp_file->offset += n;
139 200
140 r->request_body->buf->pos = r->request_body->buf->start; 201 rb->buf->pos = rb->buf->start;
141 r->request_body->buf->last = r->request_body->buf->start; 202 rb->buf->last = rb->buf->start;
142 } 203 }
143 204
144 size = r->request_body->buf->end - r->request_body->buf->last; 205 size = rb->buf->end - rb->buf->last;
145 206
146 if (size > r->request_body->rest) { 207 if (size > rb->rest) {
147 size = r->request_body->rest; 208 size = rb->rest;
148 } 209 }
149 210
150 n = c->recv(c, r->request_body->buf->last, size); 211 n = c->recv(c, rb->buf->last, size);
151 212
152 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 213 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
153 "http client request body recv %z", n); 214 "http client request body recv %z", n);
154 215
155 if (n == NGX_AGAIN) { 216 if (n == NGX_AGAIN) {
171 if (n == 0 || n == NGX_ERROR) { 232 if (n == 0 || n == NGX_ERROR) {
172 r->closed = 1; 233 r->closed = 1;
173 return NGX_HTTP_BAD_REQUEST; 234 return NGX_HTTP_BAD_REQUEST;
174 } 235 }
175 236
176 r->request_body->buf->last += n; 237 rb->buf->last += n;
177 r->request_body->rest -= n; 238 rb->rest -= n;
178 r->request_length += n; 239 r->request_length += n;
179 240
180 if (r->request_body->rest == 0) { 241 if (rb->rest == 0) {
181 break; 242 break;
182 } 243 }
183 244
184 if (r->request_body->buf->last < r->request_body->buf->end) { 245 if (rb->buf->last < rb->buf->end) {
185 break; 246 break;
186 } 247 }
187 } 248 }
188 249
189 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 250 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
190 "http client request body rest %uz", 251 "http client request body rest %uz", rb->rest);
191 r->request_body->rest); 252
192 253 if (rb->rest) {
193 if (r->request_body->rest) {
194 return NGX_AGAIN; 254 return NGX_AGAIN;
195 } 255 }
196 256
197 if (r->request_body->temp_file->file.fd != NGX_INVALID_FILE) { 257 if (rb->temp_file) {
198 258
199 /* save the last part */ 259 /* save the last part */
200 n = ngx_write_chain_to_temp_file(r->request_body->temp_file, 260
201 r->request_body->bufs->next ? r->request_body->bufs->next: 261 n = ngx_write_chain_to_temp_file(rb->temp_file,
202 r->request_body->bufs); 262 rb->bufs->next ? rb->bufs->next:
263 rb->bufs);
203 264
204 /* TODO: n == 0 or not complete and level event */ 265 /* TODO: n == 0 or not complete and level event */
205 266
206 if (n == NGX_ERROR) { 267 if (n == NGX_ERROR) {
207 return NGX_HTTP_INTERNAL_SERVER_ERROR; 268 return NGX_HTTP_INTERNAL_SERVER_ERROR;
211 return NGX_HTTP_INTERNAL_SERVER_ERROR; 272 return NGX_HTTP_INTERNAL_SERVER_ERROR;
212 } 273 }
213 274
214 b->in_file = 1; 275 b->in_file = 1;
215 b->file_pos = 0; 276 b->file_pos = 0;
216 b->file_last = r->request_body->temp_file->file.offset; 277 b->file_last = rb->temp_file->file.offset;
217 b->file = &r->request_body->temp_file->file; 278 b->file = &rb->temp_file->file;
218 279
219 if (r->request_body->bufs->next) { 280 if (rb->bufs->next) {
220 r->request_body->bufs->next->buf = b; 281 rb->bufs->next->buf = b;
221 282
222 } else { 283 } else {
223 r->request_body->bufs->buf = b; 284 rb->bufs->buf = b;
224 } 285 }
225 } 286 }
226 287
227 r->request_body->handler(r->request_body->data); 288 rb->post_handler(r);
228 289
229 return NGX_OK; 290 return NGX_OK;
230 } 291 }