Mercurial > hg > nginx
comparison src/http/ngx_http_request_body.c @ 160:e7e094d34162
nginx-0.0.1-2003-10-27-11:53:49 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 27 Oct 2003 08:53:49 +0000 |
parents | a7e45c45a95c |
children | 96993d4d5067 |
comparison
equal
deleted
inserted
replaced
159:981e4af2a425 | 160:e7e094d34162 |
---|---|
1 | 1 |
2 #include <ngx_config.h> | 2 #include <ngx_config.h> |
3 #include <ngx_core.h> | 3 #include <ngx_core.h> |
4 #include <ngx_event.h> | |
4 #include <ngx_http.h> | 5 #include <ngx_http.h> |
5 | 6 |
6 | 7 |
7 int ngx_http_init_client_request_body(ngx_http_request_t *r, int size) | 8 static void ngx_http_read_client_request_body_handler(ngx_event_t *rev); |
9 | |
10 | |
11 int ngx_http_read_client_request_body(ngx_http_request_t *r, | |
12 int request_buffer_size) | |
8 { | 13 { |
9 int header_in_part, len; | 14 ssize_t size; |
10 ngx_hunk_t *h; | 15 ngx_hunk_t *h; |
11 ngx_http_request_body_t *rb; | 16 ngx_chain_t *cl; |
12 | 17 |
13 ngx_test_null(rb, ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)), | 18 size = r->header_in->last - r->header_in->pos; |
14 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
15 | 19 |
16 header_in_part = r->header_in->end - r->header_in->pos; | 20 if (size) { |
21 ngx_test_null(h, ngx_calloc_hunk(r->pool), | |
22 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
17 | 23 |
18 if (header_in_part) { | 24 h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP; |
19 rb->header_in_pos = r->header_in->pos; | 25 h->start = h->pos = r->header_in->pos; |
20 } | 26 h->end = h->last = r->header_in->last; |
21 | 27 |
22 if (header_in_part > r->headers_in.content_length_n) { | 28 ngx_alloc_link_and_set_hunk(r->request_hunks, h, r->pool, |
23 header_in_part = r->headers_in.content_length_n; | 29 NGX_HTTP_INTERNAL_SERVER_ERROR); |
24 | 30 |
25 } else { | 31 if (size >= r->headers_in.content_length_n) { |
26 len = r->headers_in.content_length_n - header_in_part; | 32 r->header_in->pos += r->headers_in.content_length_n; |
27 if (len > size) { | 33 return NGX_OK; |
28 len = size; | |
29 | |
30 } else if (len > NGX_PAGE_SIZE) { | |
31 len = ((len + NGX_PAGE_SIZE - 1) / NGX_PAGE_SIZE) * NGX_PAGE_SIZE; | |
32 } | |
33 | |
34 if (len) { | |
35 ngx_test_null(rb->hunk, ngx_create_temp_hunk(r->pool, len, 0, 0), | |
36 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
37 } | 34 } |
38 } | 35 } |
39 | 36 |
40 r->request_body = rb; | 37 r->request_body_len = r->headers_in.content_length_n - size; |
38 | |
39 if (r->request_body_len < request_buffer_size + (request_buffer_size >> 2)) | |
40 { | |
41 size = r->request_body_len; | |
42 | |
43 } else { | |
44 size = request_buffer_size; | |
45 } | |
46 | |
47 ngx_test_null(r->request_body_hunk, | |
48 ngx_create_temp_hunk(r->pool, size, 0, 0), | |
49 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
50 | |
51 r->connection->read->event_handler = | |
52 ngx_http_read_client_request_body_handler; | |
53 | |
54 ngx_http_read_client_request_body_handler(r->connection->read); | |
55 | |
56 ngx_alloc_link_and_set_hunk(cl, r->request_body_hunk, r->pool, | |
57 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
58 | |
59 if (r->request_hunks) { | |
60 r->request_hunks->next = cl; | |
61 | |
62 } else { | |
63 r->request_hunks = cl; | |
64 } | |
65 | |
66 if (r->request_body_len) { | |
67 return NGX_AGAIN; | |
68 } | |
41 | 69 |
42 return NGX_OK; | 70 return NGX_OK; |
43 } | 71 } |
44 | 72 |
45 | 73 |
46 int ngx_http_read_client_request_body(ngx_http_request_t *r) | 74 static void ngx_http_read_client_request_body_handler(ngx_event_t *rev) |
47 { | 75 { |
48 int size, n, rc; | 76 ssize_t n, size; |
49 ngx_chain_t *entry; | 77 ngx_hunk_t *h; |
50 ngx_http_request_body_t *rb; | 78 ngx_connection_t *c; |
79 ngx_http_request_t *r; | |
51 | 80 |
52 rb = r->request_body; | 81 c = rev->data; |
82 r = c->data; | |
53 | 83 |
54 do { | 84 if (r->request_body_hunk->end - r->request_body_hunk->last == 0) { |
55 if (r->header_in->last < r->header_in->end) { | 85 n = ngx_write_chain_to_temp_file(r->temp_file, |
56 rb->chain[0].hunk = r->header_in; | 86 r->request_hunks->next ? r->request_hunks->next: |
87 r->request_hunks); | |
88 /* TODO: n == 0 or not complete and level event */ | |
57 | 89 |
58 if (rb->hunk) { | 90 r->request_body_hunk->pos = r->request_body_hunk->start; |
59 rb->chain[0].next = &rb->chain[1]; | 91 r->request_body_hunk->last = r->request_body_hunk->start; |
60 rb->chain[1].hunk = rb->hunk; | 92 } |
61 rb->chain[1].next = NULL; | |
62 | 93 |
63 } else { | 94 size = r->request_body_hunk->end - r->request_body_hunk->last; |
64 rb->chain[0].next = NULL; | 95 |
65 } | 96 if (size > r->request_body_len) { |
97 size = r->request_body_len; | |
98 } | |
99 | |
100 n = ngx_recv(c, r->request_body_hunk->last, size); | |
101 | |
102 if (n == NGX_AGAIN) { | |
103 if (ngx_handle_read_event(rev) == NGX_ERROR) { | |
104 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
105 } | |
106 | |
107 return; | |
108 } | |
109 | |
110 if (n == 0) { | |
111 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
112 "client closed prematurely connection"); | |
113 } | |
114 | |
115 if (n == 0 || n == NGX_ERROR) { | |
116 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | |
117 return; | |
118 } | |
119 | |
120 r->request_body_hunk->last += n; | |
121 r->request_body_len -= n; | |
122 | |
123 if (r->request_body_len) { | |
124 return; | |
125 } | |
126 | |
127 if (r->temp_file->file.fd != NGX_INVALID_FILE) { | |
128 | |
129 /* save the last part */ | |
130 n = ngx_write_chain_to_temp_file(r->temp_file, | |
131 r->request_hunks->next ? r->request_hunks->next: | |
132 r->request_hunks); | |
133 /* TODO: n == 0 or not complete and level event */ | |
134 | |
135 | |
136 h = ngx_calloc_hunk(r->pool); | |
137 if (h == NULL) { | |
138 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
139 return; | |
140 } | |
141 | |
142 h->type = NGX_HUNK_FILE; | |
143 h->file_pos = 0; | |
144 h->file_last = r->temp_file->file.offset; | |
145 h->file = &r->temp_file->file; | |
146 | |
147 if (r->request_hunks->next) { | |
148 r->request_hunks->next->hunk = h; | |
66 | 149 |
67 } else { | 150 } else { |
68 rb->chain[0].hunk = rb->hunk; | 151 r->request_hunks->hunk = h; |
69 rb->chain[0].next = NULL; | |
70 } | 152 } |
71 | |
72 n = ngx_recv_chain(r->connection, rb->chain); | |
73 | |
74 if (n == NGX_ERROR) { | |
75 return NGX_ERROR; | |
76 } | |
77 | |
78 if (n == NGX_AGAIN) { | |
79 return NGX_AGAIN; | |
80 } | |
81 | |
82 for (entry = rb->chain; entry; entry = entry->next) { | |
83 size = entry->hunk->end - entry->hunk->last; | |
84 | |
85 if (n >= size) { | |
86 n -= size; | |
87 entry->hunk->last = entry->hunk->end; | |
88 | |
89 continue; | |
90 } | |
91 | |
92 entry->hunk->last += n; | |
93 | |
94 break; | |
95 } | |
96 | |
97 if (rb->hunk && rb->hunk->last == rb->hunk->end) { | |
98 if (rb->temp_file.fd == NGX_INVALID_FILE) { | |
99 rc = ngx_create_temp_file(&rb->temp_file, rb->temp_path, | |
100 r->pool, 0); | |
101 | |
102 if (rc == NGX_ERROR) { | |
103 return NGX_ERROR; | |
104 } | |
105 | |
106 if (rc == NGX_AGAIN) { | |
107 return NGX_AGAIN; | |
108 } | |
109 } | |
110 | |
111 n = ngx_write_file(&rb->temp_file, rb->hunk->pos, | |
112 rb->hunk->last - rb->hunk->pos, rb->offset); | |
113 | |
114 if (rc == NGX_ERROR) { | |
115 return NGX_ERROR; | |
116 } | |
117 | |
118 rb->offset += n; | |
119 rb->hunk->last = rb->hunk->pos; | |
120 } | |
121 | |
122 } while (r->connection->read->ready); | |
123 | |
124 return NGX_OK; | |
125 } | |
126 | |
127 | |
128 int ngx_http_init_client_request_body_chain(ngx_http_request_t *r) | |
129 { | |
130 int i; | |
131 ngx_hunk_t *h; | |
132 ngx_http_request_body_t *rb; | |
133 | |
134 rb = r->request_body; | |
135 | |
136 rb->chain[0].hunk = rb->header_out; | |
137 i = 0; | |
138 | |
139 if (r->header_in->pos < r->header_in->last) { | |
140 rb->chain[i].next = &rb->chain[i + 1]; | |
141 i++; | |
142 rb->chain[i].hunk = r->header_in; | |
143 } | 153 } |
144 | 154 |
145 if (rb->temp_file.fd != NGX_INVALID_FILE) { | 155 r->request_body_handler(r->data); |
146 | |
147 if (rb->file_hunk == NULL) { | |
148 ngx_test_null(h, ngx_alloc_hunk(r->pool), NGX_ERROR); | |
149 | |
150 h->type = NGX_HUNK_FILE; | |
151 h->pos = h->start = h->pre_start = 0; | |
152 h->last = h->end = h->post_end = 0; | |
153 h->file_pos = 0; | |
154 h->file_last = rb->offset; | |
155 h->file = &rb->temp_file; | |
156 h->shadow = NULL; | |
157 h->tag = 0; | |
158 | |
159 rb->file_hunk = h; | |
160 } | |
161 | |
162 rb->chain[i].next = &rb->chain[i + 1]; | |
163 i++; | |
164 rb->chain[i].hunk = rb->file_hunk; | |
165 } | |
166 | |
167 if (rb->hunk && rb->hunk->pos < rb->hunk->last) { | |
168 rb->chain[i].next = &rb->chain[i + 1]; | |
169 i++; | |
170 rb->chain[i].hunk = h; | |
171 } | |
172 | |
173 rb->chain[i].next = NULL; | |
174 | |
175 return NGX_OK; | |
176 } | 156 } |
177 | |
178 | |
179 void ngx_http_reinit_client_request_body_hunks(ngx_http_request_t *r) | |
180 { | |
181 ngx_http_request_body_t *rb; | |
182 | |
183 rb = r->request_body; | |
184 | |
185 if (rb->header_in_pos) { | |
186 r->header_in->pos = rb->header_in_pos; | |
187 } | |
188 | |
189 if (rb->file_hunk) { | |
190 rb->file_hunk->file_pos = 0; | |
191 } | |
192 | |
193 if (rb->hunk) { | |
194 rb->hunk->pos = rb->hunk->start; | |
195 } | |
196 } |