Mercurial > hg > nginx
comparison src/http/ngx_http_request_body.c @ 4957:7556a7acb14f stable-1.2
Merge of r4921, r4922, r4923, r4924, r4925: request body fixes.
*) Request body: fixed "501 Not Implemented" error handling.
It is not about "Method" but a generic message, and is expected to be used
e.g. if specified Transfer-Encoding is not supported. Fixed message to
match RFC 2616.
Additionally, disable keepalive on such errors as we won't be able to read
request body correctly if we don't understand Transfer-Encoding used.
*) Request body: $request_body variable generalization.
The $request_body variable was assuming there can't be more than two
buffers. While this is currently true due to request body reading
implementation details, this is not a good thing to depend on and may
change in the future.
*) Request body: code duplication reduced, no functional changes.
The r->request_body_in_file_only with empty body case is now handled in
ngx_http_write_request_body().
*) Request body: fixed socket leak on errors.
The r->main->count reference counter was always incremented in
ngx_http_read_client_request_body(), while it is only needs to be
incremented on positive returns.
*) Request body: properly handle events while discarding body.
An attempt to call ngx_handle_read_event() before actually reading
data from a socket might result in read event being disabled, which is
wrong. Catched by body.t test on Solaris.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 11 Dec 2012 13:18:50 +0000 |
parents | 834049edae24 |
children |
comparison
equal
deleted
inserted
replaced
4956:bbcaeccbd928 | 4957:7556a7acb14f |
---|---|
29 ngx_http_read_client_request_body(ngx_http_request_t *r, | 29 ngx_http_read_client_request_body(ngx_http_request_t *r, |
30 ngx_http_client_body_handler_pt post_handler) | 30 ngx_http_client_body_handler_pt post_handler) |
31 { | 31 { |
32 size_t preread; | 32 size_t preread; |
33 ssize_t size; | 33 ssize_t size; |
34 ngx_int_t rc; | |
34 ngx_buf_t *b; | 35 ngx_buf_t *b; |
35 ngx_chain_t *cl, **next; | 36 ngx_chain_t *cl, **next; |
36 ngx_temp_file_t *tf; | |
37 ngx_http_request_body_t *rb; | 37 ngx_http_request_body_t *rb; |
38 ngx_http_core_loc_conf_t *clcf; | 38 ngx_http_core_loc_conf_t *clcf; |
39 | 39 |
40 r->main->count++; | 40 r->main->count++; |
41 | 41 |
43 post_handler(r); | 43 post_handler(r); |
44 return NGX_OK; | 44 return NGX_OK; |
45 } | 45 } |
46 | 46 |
47 if (ngx_http_test_expect(r) != NGX_OK) { | 47 if (ngx_http_test_expect(r) != NGX_OK) { |
48 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 48 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
49 goto done; | |
49 } | 50 } |
50 | 51 |
51 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); | 52 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); |
52 if (rb == NULL) { | 53 if (rb == NULL) { |
53 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 54 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
55 goto done; | |
54 } | 56 } |
55 | 57 |
56 r->request_body = rb; | 58 r->request_body = rb; |
57 | 59 |
58 if (r->headers_in.content_length_n < 0) { | 60 if (r->headers_in.content_length_n < 0) { |
63 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 65 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
64 | 66 |
65 if (r->headers_in.content_length_n == 0) { | 67 if (r->headers_in.content_length_n == 0) { |
66 | 68 |
67 if (r->request_body_in_file_only) { | 69 if (r->request_body_in_file_only) { |
68 tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); | 70 if (ngx_http_write_request_body(r, NULL) != NGX_OK) { |
69 if (tf == NULL) { | 71 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
70 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 72 goto done; |
71 } | |
72 | |
73 tf->file.fd = NGX_INVALID_FILE; | |
74 tf->file.log = r->connection->log; | |
75 tf->path = clcf->client_body_temp_path; | |
76 tf->pool = r->pool; | |
77 tf->warn = "a client request body is buffered to a temporary file"; | |
78 tf->log_level = r->request_body_file_log_level; | |
79 tf->persistent = r->request_body_in_persistent_file; | |
80 tf->clean = r->request_body_in_clean_file; | |
81 | |
82 if (r->request_body_file_group_access) { | |
83 tf->access = 0660; | |
84 } | |
85 | |
86 rb->temp_file = tf; | |
87 | |
88 if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, | |
89 tf->persistent, tf->clean, tf->access) | |
90 != NGX_OK) | |
91 { | |
92 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
93 } | 73 } |
94 } | 74 } |
95 | 75 |
96 post_handler(r); | 76 post_handler(r); |
97 | 77 |
117 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 97 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
118 "http client request body preread %uz", preread); | 98 "http client request body preread %uz", preread); |
119 | 99 |
120 b = ngx_calloc_buf(r->pool); | 100 b = ngx_calloc_buf(r->pool); |
121 if (b == NULL) { | 101 if (b == NULL) { |
122 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 102 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
103 goto done; | |
123 } | 104 } |
124 | 105 |
125 b->temporary = 1; | 106 b->temporary = 1; |
126 b->start = r->header_in->pos; | 107 b->start = r->header_in->pos; |
127 b->pos = r->header_in->pos; | 108 b->pos = r->header_in->pos; |
128 b->last = r->header_in->last; | 109 b->last = r->header_in->last; |
129 b->end = r->header_in->end; | 110 b->end = r->header_in->end; |
130 | 111 |
131 rb->bufs = ngx_alloc_chain_link(r->pool); | 112 rb->bufs = ngx_alloc_chain_link(r->pool); |
132 if (rb->bufs == NULL) { | 113 if (rb->bufs == NULL) { |
133 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 114 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
115 goto done; | |
134 } | 116 } |
135 | 117 |
136 rb->bufs->buf = b; | 118 rb->bufs->buf = b; |
137 rb->bufs->next = NULL; | 119 rb->bufs->next = NULL; |
138 | 120 |
146 r->request_length += r->headers_in.content_length_n; | 128 r->request_length += r->headers_in.content_length_n; |
147 b->last = r->header_in->pos; | 129 b->last = r->header_in->pos; |
148 | 130 |
149 if (r->request_body_in_file_only) { | 131 if (r->request_body_in_file_only) { |
150 if (ngx_http_write_request_body(r, rb->bufs) != NGX_OK) { | 132 if (ngx_http_write_request_body(r, rb->bufs) != NGX_OK) { |
151 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 133 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
134 goto done; | |
152 } | 135 } |
153 } | 136 } |
154 | 137 |
155 post_handler(r); | 138 post_handler(r); |
156 | 139 |
173 | 156 |
174 rb->to_write = rb->bufs; | 157 rb->to_write = rb->bufs; |
175 | 158 |
176 r->read_event_handler = ngx_http_read_client_request_body_handler; | 159 r->read_event_handler = ngx_http_read_client_request_body_handler; |
177 | 160 |
178 return ngx_http_do_read_client_request_body(r); | 161 rc = ngx_http_do_read_client_request_body(r); |
162 goto done; | |
179 } | 163 } |
180 | 164 |
181 next = &rb->bufs->next; | 165 next = &rb->bufs->next; |
182 | 166 |
183 } else { | 167 } else { |
203 b = NULL; | 187 b = NULL; |
204 } | 188 } |
205 | 189 |
206 rb->buf = ngx_create_temp_buf(r->pool, size); | 190 rb->buf = ngx_create_temp_buf(r->pool, size); |
207 if (rb->buf == NULL) { | 191 if (rb->buf == NULL) { |
208 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 192 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
193 goto done; | |
209 } | 194 } |
210 | 195 |
211 cl = ngx_alloc_chain_link(r->pool); | 196 cl = ngx_alloc_chain_link(r->pool); |
212 if (cl == NULL) { | 197 if (cl == NULL) { |
213 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 198 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
199 goto done; | |
214 } | 200 } |
215 | 201 |
216 cl->buf = rb->buf; | 202 cl->buf = rb->buf; |
217 cl->next = NULL; | 203 cl->next = NULL; |
218 | 204 |
233 rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs; | 219 rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs; |
234 } | 220 } |
235 | 221 |
236 r->read_event_handler = ngx_http_read_client_request_body_handler; | 222 r->read_event_handler = ngx_http_read_client_request_body_handler; |
237 | 223 |
238 return ngx_http_do_read_client_request_body(r); | 224 rc = ngx_http_do_read_client_request_body(r); |
225 | |
226 done: | |
227 | |
228 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
229 r->main->count--; | |
230 } | |
231 | |
232 return rc; | |
239 } | 233 } |
240 | 234 |
241 | 235 |
242 static void | 236 static void |
243 ngx_http_read_client_request_body_handler(ngx_http_request_t *r) | 237 ngx_http_read_client_request_body_handler(ngx_http_request_t *r) |
417 if (r->request_body_file_group_access) { | 411 if (r->request_body_file_group_access) { |
418 tf->access = 0660; | 412 tf->access = 0660; |
419 } | 413 } |
420 | 414 |
421 rb->temp_file = tf; | 415 rb->temp_file = tf; |
416 | |
417 if (body == NULL) { | |
418 /* empty body with r->request_body_in_file_only */ | |
419 | |
420 if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, | |
421 tf->persistent, tf->clean, tf->access) | |
422 != NGX_OK) | |
423 { | |
424 return NGX_ERROR; | |
425 } | |
426 | |
427 return NGX_OK; | |
428 } | |
422 } | 429 } |
423 | 430 |
424 n = ngx_write_chain_to_temp_file(rb->temp_file, body); | 431 n = ngx_write_chain_to_temp_file(rb->temp_file, body); |
425 | 432 |
426 /* TODO: n == 0 or not complete and level event */ | 433 /* TODO: n == 0 or not complete and level event */ |
473 r->headers_in.content_length_n = 0; | 480 r->headers_in.content_length_n = 0; |
474 return NGX_OK; | 481 return NGX_OK; |
475 } | 482 } |
476 } | 483 } |
477 | 484 |
485 if (ngx_http_read_discarded_request_body(r) == NGX_OK) { | |
486 r->lingering_close = 0; | |
487 return NGX_OK; | |
488 } | |
489 | |
490 /* == NGX_AGAIN */ | |
491 | |
478 r->read_event_handler = ngx_http_discarded_request_body_handler; | 492 r->read_event_handler = ngx_http_discarded_request_body_handler; |
479 | 493 |
480 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | 494 if (ngx_handle_read_event(rev, 0) != NGX_OK) { |
481 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 495 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
482 } | 496 } |
483 | 497 |
484 if (ngx_http_read_discarded_request_body(r) == NGX_OK) { | 498 r->count++; |
485 r->lingering_close = 0; | 499 r->discard_body = 1; |
486 | |
487 } else { | |
488 r->count++; | |
489 r->discard_body = 1; | |
490 } | |
491 | 500 |
492 return NGX_OK; | 501 return NGX_OK; |
493 } | 502 } |
494 | 503 |
495 | 504 |