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 }