Mercurial > hg > nginx-vendor-current
comparison src/http/ngx_http_request_body.c @ 0:f0b350454894 NGINX_0_1_0
nginx 0.1.0
*) The first public version.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 04 Oct 2004 00:00:00 +0400 |
parents | |
children | 46833bd150cb |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0b350454894 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
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); | |
15 | |
16 | |
17 ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r) | |
18 { | |
19 ssize_t size; | |
20 ngx_buf_t *b; | |
21 ngx_chain_t *cl; | |
22 ngx_http_core_loc_conf_t *clcf; | |
23 | |
24 size = r->header_in->last - r->header_in->pos; | |
25 | |
26 if (size) { | |
27 | |
28 /* there is the pre-read part of the request body */ | |
29 | |
30 ngx_test_null(b, ngx_calloc_buf(r->pool), | |
31 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
32 | |
33 b->temporary = 1; | |
34 b->start = b->pos = r->header_in->pos; | |
35 b->end = b->last = r->header_in->last; | |
36 | |
37 ngx_alloc_link_and_set_buf(r->request_body->bufs, b, r->pool, | |
38 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
39 | |
40 if (size >= r->headers_in.content_length_n) { | |
41 | |
42 /* the whole request body was pre-read */ | |
43 | |
44 r->header_in->pos += r->headers_in.content_length_n; | |
45 | |
46 r->request_body->handler(r->request_body->data); | |
47 | |
48 return NGX_OK; | |
49 } | |
50 | |
51 r->header_in->pos = r->header_in->last; | |
52 } | |
53 | |
54 | |
55 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
56 | |
57 r->request_body->rest = r->headers_in.content_length_n - size; | |
58 | |
59 if (r->request_body->rest | |
60 < clcf->client_body_buffer_size | |
61 + (clcf->client_body_buffer_size >> 2)) | |
62 { | |
63 size = r->request_body->rest; | |
64 | |
65 } else { | |
66 size = clcf->client_body_buffer_size; | |
67 } | |
68 | |
69 ngx_test_null(r->request_body->buf, ngx_create_temp_buf(r->pool, size), | |
70 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
71 | |
72 ngx_alloc_link_and_set_buf(cl, r->request_body->buf, r->pool, | |
73 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
74 | |
75 if (r->request_body->bufs) { | |
76 r->request_body->bufs->next = cl; | |
77 | |
78 } else { | |
79 r->request_body->bufs = cl; | |
80 } | |
81 | |
82 r->connection->read->event_handler = | |
83 ngx_http_read_client_request_body_handler; | |
84 | |
85 return ngx_http_do_read_client_request_body(r); | |
86 } | |
87 | |
88 | |
89 static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) | |
90 { | |
91 ngx_int_t rc; | |
92 ngx_connection_t *c; | |
93 ngx_http_request_t *r; | |
94 | |
95 c = rev->data; | |
96 r = c->data; | |
97 | |
98 if (rev->timedout) { | |
99 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); | |
100 return; | |
101 } | |
102 | |
103 rc = ngx_http_do_read_client_request_body(r); | |
104 | |
105 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
106 ngx_http_finalize_request(r, rc); | |
107 } | |
108 } | |
109 | |
110 | |
111 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r) | |
112 { | |
113 size_t size; | |
114 ssize_t n; | |
115 ngx_buf_t *b; | |
116 ngx_connection_t *c; | |
117 ngx_http_core_loc_conf_t *clcf; | |
118 | |
119 c = r->connection; | |
120 | |
121 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
122 "http read client request body"); | |
123 | |
124 for ( ;; ) { | |
125 if (r->request_body->buf->last == r->request_body->buf->end) { | |
126 n = ngx_write_chain_to_temp_file(r->request_body->temp_file, | |
127 r->request_body->bufs->next ? r->request_body->bufs->next: | |
128 r->request_body->bufs); | |
129 | |
130 /* TODO: n == 0 or not complete and level event */ | |
131 | |
132 if (n == NGX_ERROR) { | |
133 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
134 } | |
135 | |
136 r->request_body->temp_file->offset += n; | |
137 | |
138 r->request_body->buf->pos = r->request_body->buf->start; | |
139 r->request_body->buf->last = r->request_body->buf->start; | |
140 } | |
141 | |
142 size = r->request_body->buf->end - r->request_body->buf->last; | |
143 | |
144 if (size > r->request_body->rest) { | |
145 size = r->request_body->rest; | |
146 } | |
147 | |
148 n = c->recv(c, r->request_body->buf->last, size); | |
149 | |
150 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
151 "http client request body recv " SIZE_T_FMT, n); | |
152 | |
153 if (n == NGX_AGAIN) { | |
154 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
155 ngx_add_timer(c->read, clcf->client_body_timeout); | |
156 | |
157 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { | |
158 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
159 } | |
160 | |
161 return NGX_AGAIN; | |
162 } | |
163 | |
164 if (n == 0) { | |
165 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
166 "client closed prematurely connection"); | |
167 } | |
168 | |
169 if (n == 0 || n == NGX_ERROR) { | |
170 r->closed = 1; | |
171 return NGX_HTTP_BAD_REQUEST; | |
172 } | |
173 | |
174 r->request_body->buf->last += n; | |
175 r->request_body->rest -= n; | |
176 | |
177 if (r->request_body->rest == 0) { | |
178 break; | |
179 } | |
180 | |
181 if (r->request_body->buf->last < r->request_body->buf->end) { | |
182 break; | |
183 } | |
184 } | |
185 | |
186 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
187 "http client request body rest " SIZE_T_FMT, | |
188 r->request_body->rest); | |
189 | |
190 if (r->request_body->rest) { | |
191 return NGX_AGAIN; | |
192 } | |
193 | |
194 if (r->request_body->temp_file->file.fd != NGX_INVALID_FILE) { | |
195 | |
196 /* save the last part */ | |
197 n = ngx_write_chain_to_temp_file(r->request_body->temp_file, | |
198 r->request_body->bufs->next ? r->request_body->bufs->next: | |
199 r->request_body->bufs); | |
200 | |
201 /* TODO: n == 0 or not complete and level event */ | |
202 | |
203 if (n == NGX_ERROR) { | |
204 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
205 } | |
206 | |
207 if (!(b = ngx_calloc_buf(r->pool))) { | |
208 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
209 } | |
210 | |
211 b->in_file = 1; | |
212 b->file_pos = 0; | |
213 b->file_last = r->request_body->temp_file->file.offset; | |
214 b->file = &r->request_body->temp_file->file; | |
215 | |
216 if (r->request_body->bufs->next) { | |
217 r->request_body->bufs->next->buf = b; | |
218 | |
219 } else { | |
220 r->request_body->bufs->buf = b; | |
221 } | |
222 } | |
223 | |
224 r->request_body->handler(r->request_body->data); | |
225 | |
226 return NGX_OK; | |
227 } |