nginxtra 1.2.8.8 → 1.4.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/nginxtra +1 -1
- data/bin/nginxtra_rails +1 -1
- data/lib/nginxtra/version.rb +1 -1
- data/vendor/nginx/CHANGES +202 -63
- data/vendor/nginx/CHANGES.ru +208 -66
- data/vendor/nginx/auto/lib/md5/conf +3 -3
- data/vendor/nginx/auto/lib/perl/conf +3 -1
- data/vendor/nginx/auto/lib/perl/make +21 -16
- data/vendor/nginx/auto/lib/sha1/conf +1 -1
- data/vendor/nginx/auto/modules +25 -4
- data/vendor/nginx/auto/options +7 -1
- data/vendor/nginx/auto/sources +15 -1
- data/vendor/nginx/auto/unix +14 -0
- data/vendor/nginx/src/core/nginx.h +2 -2
- data/vendor/nginx/src/core/ngx_array.c +1 -7
- data/vendor/nginx/src/core/ngx_array.h +2 -2
- data/vendor/nginx/src/core/ngx_connection.c +13 -7
- data/vendor/nginx/src/core/ngx_connection.h +1 -2
- data/vendor/nginx/src/core/ngx_core.h +1 -2
- data/vendor/nginx/src/core/ngx_crypt.c +37 -0
- data/vendor/nginx/src/core/ngx_cycle.h +1 -1
- data/vendor/nginx/src/core/ngx_inet.c +219 -48
- data/vendor/nginx/src/core/ngx_inet.h +1 -1
- data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +7 -1
- data/vendor/nginx/src/event/modules/ngx_eventport_module.c +1 -1
- data/vendor/nginx/src/event/ngx_event.c +5 -1
- data/vendor/nginx/src/event/ngx_event.h +1 -0
- data/vendor/nginx/src/event/ngx_event_connect.c +1 -1
- data/vendor/nginx/src/event/ngx_event_openssl.c +135 -9
- data/vendor/nginx/src/event/ngx_event_openssl.h +9 -0
- data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +1749 -0
- data/vendor/nginx/src/http/modules/ngx_http_addition_filter_module.c +1 -0
- data/vendor/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -0
- data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +5 -0
- data/vendor/nginx/src/http/modules/ngx_http_flv_module.c +4 -0
- data/vendor/nginx/src/http/modules/ngx_http_geo_module.c +7 -8
- data/vendor/nginx/src/http/modules/ngx_http_geoip_module.c +10 -12
- data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +677 -0
- data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +3 -0
- data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +36 -10
- data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +31 -13
- data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +13 -0
- data/vendor/nginx/src/http/modules/ngx_http_limit_conn_module.c +18 -2
- data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +19 -2
- data/vendor/nginx/src/http/modules/ngx_http_map_module.c +1 -1
- data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +60 -8
- data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +4 -8
- data/vendor/nginx/src/http/modules/ngx_http_not_modified_filter_module.c +126 -29
- data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +59 -301
- data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +34 -6
- data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +13 -12
- data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +30 -11
- data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +1 -0
- data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +155 -4
- data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +6 -0
- data/vendor/nginx/src/http/modules/ngx_http_static_module.c +4 -0
- data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +90 -3
- data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +1 -0
- data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +5 -0
- data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +5 -0
- data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +14 -1
- data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +1 -0
- data/vendor/nginx/src/http/modules/perl/Makefile.PL +4 -2
- data/vendor/nginx/src/http/modules/perl/nginx.pm +1 -1
- data/vendor/nginx/src/http/modules/perl/nginx.xs +36 -3
- data/vendor/nginx/src/http/ngx_http.c +24 -1
- data/vendor/nginx/src/http/ngx_http.h +26 -2
- data/vendor/nginx/src/http/ngx_http_core_module.c +136 -10
- data/vendor/nginx/src/http/ngx_http_core_module.h +37 -13
- data/vendor/nginx/src/http/ngx_http_header_filter_module.c +9 -2
- data/vendor/nginx/src/http/ngx_http_parse.c +404 -0
- data/vendor/nginx/src/http/ngx_http_request.c +840 -517
- data/vendor/nginx/src/http/ngx_http_request.h +37 -25
- data/vendor/nginx/src/http/ngx_http_request_body.c +585 -156
- data/vendor/nginx/src/http/ngx_http_spdy.c +2882 -0
- data/vendor/nginx/src/http/ngx_http_spdy.h +235 -0
- data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +999 -0
- data/vendor/nginx/src/http/ngx_http_spdy_module.c +351 -0
- data/vendor/nginx/src/http/ngx_http_spdy_module.h +36 -0
- data/vendor/nginx/src/http/ngx_http_special_response.c +3 -1
- data/vendor/nginx/src/http/ngx_http_upstream.c +415 -26
- data/vendor/nginx/src/http/ngx_http_upstream.h +11 -1
- data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +2 -45
- data/vendor/nginx/src/http/ngx_http_upstream_round_robin.h +0 -2
- data/vendor/nginx/src/http/ngx_http_variables.c +72 -12
- data/vendor/nginx/src/mail/ngx_mail.h +2 -2
- data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +35 -25
- data/vendor/nginx/src/mail/ngx_mail_core_module.c +5 -1
- metadata +9 -2
@@ -64,6 +64,10 @@
|
|
64
64
|
#define NGX_HTTP_LOG_UNSAFE 8
|
65
65
|
|
66
66
|
|
67
|
+
#define NGX_HTTP_CONTINUE 100
|
68
|
+
#define NGX_HTTP_SWITCHING_PROTOCOLS 101
|
69
|
+
#define NGX_HTTP_PROCESSING 102
|
70
|
+
|
67
71
|
#define NGX_HTTP_OK 200
|
68
72
|
#define NGX_HTTP_CREATED 201
|
69
73
|
#define NGX_HTTP_ACCEPTED 202
|
@@ -137,13 +141,6 @@
|
|
137
141
|
#define NGX_HTTP_COPY_BUFFERED 0x04
|
138
142
|
|
139
143
|
|
140
|
-
#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP || NGX_HTTP_GEO)
|
141
|
-
#ifndef NGX_HTTP_X_FORWARDED_FOR
|
142
|
-
#define NGX_HTTP_X_FORWARDED_FOR 1
|
143
|
-
#endif
|
144
|
-
#endif
|
145
|
-
|
146
|
-
|
147
144
|
typedef enum {
|
148
145
|
NGX_HTTP_INITING_REQUEST_STATE = 0,
|
149
146
|
NGX_HTTP_READING_REQUEST_STATE,
|
@@ -179,6 +176,8 @@ typedef struct {
|
|
179
176
|
ngx_table_elt_t *connection;
|
180
177
|
ngx_table_elt_t *if_modified_since;
|
181
178
|
ngx_table_elt_t *if_unmodified_since;
|
179
|
+
ngx_table_elt_t *if_match;
|
180
|
+
ngx_table_elt_t *if_none_match;
|
182
181
|
ngx_table_elt_t *user_agent;
|
183
182
|
ngx_table_elt_t *referer;
|
184
183
|
ngx_table_elt_t *content_length;
|
@@ -189,6 +188,7 @@ typedef struct {
|
|
189
188
|
|
190
189
|
ngx_table_elt_t *transfer_encoding;
|
191
190
|
ngx_table_elt_t *expect;
|
191
|
+
ngx_table_elt_t *upgrade;
|
192
192
|
|
193
193
|
#if (NGX_HTTP_GZIP)
|
194
194
|
ngx_table_elt_t *accept_encoding;
|
@@ -200,7 +200,7 @@ typedef struct {
|
|
200
200
|
ngx_table_elt_t *keep_alive;
|
201
201
|
|
202
202
|
#if (NGX_HTTP_X_FORWARDED_FOR)
|
203
|
-
|
203
|
+
ngx_array_t x_forwarded_for;
|
204
204
|
#endif
|
205
205
|
|
206
206
|
#if (NGX_HTTP_REALIP)
|
@@ -229,6 +229,7 @@ typedef struct {
|
|
229
229
|
time_t keep_alive_n;
|
230
230
|
|
231
231
|
unsigned connection_type:2;
|
232
|
+
unsigned chunked:1;
|
232
233
|
unsigned msie:1;
|
233
234
|
unsigned msie6:1;
|
234
235
|
unsigned opera:1;
|
@@ -281,13 +282,25 @@ typedef struct {
|
|
281
282
|
ngx_chain_t *bufs;
|
282
283
|
ngx_buf_t *buf;
|
283
284
|
off_t rest;
|
284
|
-
ngx_chain_t *
|
285
|
+
ngx_chain_t *free;
|
286
|
+
ngx_chain_t *busy;
|
287
|
+
ngx_http_chunked_t *chunked;
|
285
288
|
ngx_http_client_body_handler_pt post_handler;
|
286
289
|
} ngx_http_request_body_t;
|
287
290
|
|
288
291
|
|
292
|
+
typedef struct ngx_http_addr_conf_s ngx_http_addr_conf_t;
|
293
|
+
|
289
294
|
typedef struct {
|
290
|
-
|
295
|
+
ngx_http_addr_conf_t *addr_conf;
|
296
|
+
ngx_http_conf_ctx_t *conf_ctx;
|
297
|
+
|
298
|
+
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
299
|
+
ngx_str_t *ssl_servername;
|
300
|
+
#if (NGX_PCRE)
|
301
|
+
ngx_http_regex_t *ssl_servername_regex;
|
302
|
+
#endif
|
303
|
+
#endif
|
291
304
|
|
292
305
|
ngx_buf_t **busy;
|
293
306
|
ngx_int_t nbusy;
|
@@ -295,21 +308,12 @@ typedef struct {
|
|
295
308
|
ngx_buf_t **free;
|
296
309
|
ngx_int_t nfree;
|
297
310
|
|
298
|
-
|
311
|
+
#if (NGX_HTTP_SSL)
|
312
|
+
ngx_uint_t ssl; /* unsigned ssl:1; */
|
313
|
+
#endif
|
299
314
|
} ngx_http_connection_t;
|
300
315
|
|
301
316
|
|
302
|
-
typedef struct ngx_http_server_name_s ngx_http_server_name_t;
|
303
|
-
|
304
|
-
|
305
|
-
typedef struct {
|
306
|
-
ngx_hash_combined_t names;
|
307
|
-
|
308
|
-
ngx_uint_t nregex;
|
309
|
-
ngx_http_server_name_t *regex;
|
310
|
-
} ngx_http_virtual_names_t;
|
311
|
-
|
312
|
-
|
313
317
|
typedef void (*ngx_http_cleanup_pt)(void *data);
|
314
318
|
|
315
319
|
typedef struct ngx_http_cleanup_s ngx_http_cleanup_t;
|
@@ -403,8 +407,6 @@ struct ngx_http_request_s {
|
|
403
407
|
ngx_http_post_subrequest_t *post_subrequest;
|
404
408
|
ngx_http_posted_request_t *posted_requests;
|
405
409
|
|
406
|
-
ngx_http_virtual_names_t *virtual_names;
|
407
|
-
|
408
410
|
ngx_int_t phase_handler;
|
409
411
|
ngx_http_handler_pt content_handler;
|
410
412
|
ngx_uint_t access_code;
|
@@ -427,6 +429,9 @@ struct ngx_http_request_s {
|
|
427
429
|
ngx_uint_t err_status;
|
428
430
|
|
429
431
|
ngx_http_connection_t *http_connection;
|
432
|
+
#if (NGX_HTTP_SPDY)
|
433
|
+
ngx_http_spdy_stream_t *spdy_stream;
|
434
|
+
#endif
|
430
435
|
|
431
436
|
ngx_http_log_handler_pt log_handler;
|
432
437
|
|
@@ -497,7 +502,6 @@ struct ngx_http_request_s {
|
|
497
502
|
#endif
|
498
503
|
|
499
504
|
unsigned pipeline:1;
|
500
|
-
unsigned plain_http:1;
|
501
505
|
unsigned chunked:1;
|
502
506
|
unsigned header_only:1;
|
503
507
|
unsigned keepalive:1;
|
@@ -577,4 +581,12 @@ extern ngx_http_header_t ngx_http_headers_in[];
|
|
577
581
|
extern ngx_http_header_out_t ngx_http_headers_out[];
|
578
582
|
|
579
583
|
|
584
|
+
#define ngx_http_set_connection_log(c, l) \
|
585
|
+
\
|
586
|
+
c->log->file = l->file; \
|
587
|
+
if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { \
|
588
|
+
c->log->log_level = l->log_level; \
|
589
|
+
}
|
590
|
+
|
591
|
+
|
580
592
|
#endif /* _NGX_HTTP_REQUEST_H_INCLUDED_ */
|
@@ -12,18 +12,21 @@
|
|
12
12
|
|
13
13
|
static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
|
14
14
|
static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
|
15
|
-
static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r
|
16
|
-
ngx_chain_t *body);
|
15
|
+
static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r);
|
17
16
|
static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
|
17
|
+
static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r,
|
18
|
+
ngx_buf_t *b);
|
18
19
|
static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r);
|
19
20
|
|
21
|
+
static ngx_int_t ngx_http_request_body_filter(ngx_http_request_t *r,
|
22
|
+
ngx_chain_t *in);
|
23
|
+
static ngx_int_t ngx_http_request_body_length_filter(ngx_http_request_t *r,
|
24
|
+
ngx_chain_t *in);
|
25
|
+
static ngx_int_t ngx_http_request_body_chunked_filter(ngx_http_request_t *r,
|
26
|
+
ngx_chain_t *in);
|
27
|
+
static ngx_int_t ngx_http_request_body_save_filter(ngx_http_request_t *r,
|
28
|
+
ngx_chain_t *in);
|
20
29
|
|
21
|
-
/*
|
22
|
-
* on completion ngx_http_read_client_request_body() adds to
|
23
|
-
* r->request_body->bufs one or two bufs:
|
24
|
-
* *) one memory buf that was preread in r->header_in;
|
25
|
-
* *) one memory or file buf that contains the rest of the body
|
26
|
-
*/
|
27
30
|
|
28
31
|
ngx_int_t
|
29
32
|
ngx_http_read_client_request_body(ngx_http_request_t *r,
|
@@ -33,13 +36,20 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|
33
36
|
ssize_t size;
|
34
37
|
ngx_int_t rc;
|
35
38
|
ngx_buf_t *b;
|
36
|
-
ngx_chain_t
|
39
|
+
ngx_chain_t out, *cl;
|
37
40
|
ngx_http_request_body_t *rb;
|
38
41
|
ngx_http_core_loc_conf_t *clcf;
|
39
42
|
|
40
43
|
r->main->count++;
|
41
44
|
|
42
|
-
|
45
|
+
#if (NGX_HTTP_SPDY)
|
46
|
+
if (r->spdy_stream) {
|
47
|
+
rc = ngx_http_spdy_read_request_body(r, post_handler);
|
48
|
+
goto done;
|
49
|
+
}
|
50
|
+
#endif
|
51
|
+
|
52
|
+
if (r != r->main || r->request_body || r->discard_body) {
|
43
53
|
post_handler(r);
|
44
54
|
return NGX_OK;
|
45
55
|
}
|
@@ -55,39 +65,26 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|
55
65
|
goto done;
|
56
66
|
}
|
57
67
|
|
58
|
-
r->request_body = rb;
|
59
|
-
|
60
|
-
if (r->headers_in.content_length_n < 0) {
|
61
|
-
post_handler(r);
|
62
|
-
return NGX_OK;
|
63
|
-
}
|
64
|
-
|
65
|
-
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
66
|
-
|
67
|
-
if (r->headers_in.content_length_n == 0) {
|
68
|
-
|
69
|
-
if (r->request_body_in_file_only) {
|
70
|
-
if (ngx_http_write_request_body(r, NULL) != NGX_OK) {
|
71
|
-
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
72
|
-
goto done;
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
|
-
post_handler(r);
|
77
|
-
|
78
|
-
return NGX_OK;
|
79
|
-
}
|
80
|
-
|
81
|
-
rb->post_handler = post_handler;
|
82
|
-
|
83
68
|
/*
|
84
69
|
* set by ngx_pcalloc():
|
85
70
|
*
|
86
71
|
* rb->bufs = NULL;
|
87
72
|
* rb->buf = NULL;
|
88
|
-
* rb->
|
73
|
+
* rb->free = NULL;
|
74
|
+
* rb->busy = NULL;
|
75
|
+
* rb->chunked = NULL;
|
89
76
|
*/
|
90
77
|
|
78
|
+
rb->rest = -1;
|
79
|
+
rb->post_handler = post_handler;
|
80
|
+
|
81
|
+
r->request_body = rb;
|
82
|
+
|
83
|
+
if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
|
84
|
+
post_handler(r);
|
85
|
+
return NGX_OK;
|
86
|
+
}
|
87
|
+
|
91
88
|
preread = r->header_in->last - r->header_in->pos;
|
92
89
|
|
93
90
|
if (preread) {
|
@@ -97,83 +94,98 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|
97
94
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
98
95
|
"http client request body preread %uz", preread);
|
99
96
|
|
100
|
-
|
101
|
-
|
102
|
-
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
103
|
-
goto done;
|
104
|
-
}
|
97
|
+
out.buf = r->header_in;
|
98
|
+
out.next = NULL;
|
105
99
|
|
106
|
-
|
107
|
-
b->start = r->header_in->pos;
|
108
|
-
b->pos = r->header_in->pos;
|
109
|
-
b->last = r->header_in->last;
|
110
|
-
b->end = r->header_in->end;
|
100
|
+
rc = ngx_http_request_body_filter(r, &out);
|
111
101
|
|
112
|
-
|
113
|
-
if (rb->bufs == NULL) {
|
114
|
-
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
102
|
+
if (rc != NGX_OK) {
|
115
103
|
goto done;
|
116
104
|
}
|
117
105
|
|
118
|
-
|
119
|
-
rb->bufs->next = NULL;
|
120
|
-
|
121
|
-
rb->buf = b;
|
106
|
+
r->request_length += preread - (r->header_in->last - r->header_in->pos);
|
122
107
|
|
123
|
-
if (
|
108
|
+
if (!r->headers_in.chunked
|
109
|
+
&& rb->rest > 0
|
110
|
+
&& rb->rest <= (off_t) (r->header_in->end - r->header_in->last))
|
111
|
+
{
|
112
|
+
/* the whole request body may be placed in r->header_in */
|
124
113
|
|
125
|
-
|
114
|
+
b = ngx_calloc_buf(r->pool);
|
115
|
+
if (b == NULL) {
|
116
|
+
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
117
|
+
goto done;
|
118
|
+
}
|
126
119
|
|
127
|
-
|
128
|
-
|
129
|
-
b->
|
120
|
+
b->temporary = 1;
|
121
|
+
b->start = r->header_in->pos;
|
122
|
+
b->pos = r->header_in->pos;
|
123
|
+
b->last = r->header_in->last;
|
124
|
+
b->end = r->header_in->end;
|
130
125
|
|
131
|
-
|
132
|
-
if (ngx_http_write_request_body(r, rb->bufs) != NGX_OK) {
|
133
|
-
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
134
|
-
goto done;
|
135
|
-
}
|
136
|
-
}
|
126
|
+
rb->buf = b;
|
137
127
|
|
138
|
-
|
128
|
+
r->read_event_handler = ngx_http_read_client_request_body_handler;
|
129
|
+
r->write_event_handler = ngx_http_request_empty_handler;
|
139
130
|
|
140
|
-
|
131
|
+
rc = ngx_http_do_read_client_request_body(r);
|
132
|
+
goto done;
|
141
133
|
}
|
142
134
|
|
143
|
-
|
144
|
-
|
145
|
-
* ngx_http_set_keepalive()
|
146
|
-
*/
|
147
|
-
r->header_in->pos = r->header_in->last;
|
135
|
+
} else {
|
136
|
+
/* set rb->rest */
|
148
137
|
|
149
|
-
r
|
138
|
+
if (ngx_http_request_body_filter(r, NULL) != NGX_OK) {
|
139
|
+
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
140
|
+
goto done;
|
141
|
+
}
|
142
|
+
}
|
150
143
|
|
151
|
-
|
144
|
+
if (rb->rest == 0) {
|
145
|
+
/* the whole request body was pre-read */
|
152
146
|
|
153
|
-
if (
|
147
|
+
if (r->request_body_in_file_only) {
|
148
|
+
if (ngx_http_write_request_body(r) != NGX_OK) {
|
149
|
+
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
150
|
+
goto done;
|
151
|
+
}
|
154
152
|
|
155
|
-
|
153
|
+
cl = ngx_chain_get_free_buf(r->pool, &rb->free);
|
154
|
+
if (cl == NULL) {
|
155
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
156
|
+
}
|
156
157
|
|
157
|
-
|
158
|
+
b = cl->buf;
|
158
159
|
|
159
|
-
|
160
|
+
ngx_memzero(b, sizeof(ngx_buf_t));
|
160
161
|
|
161
|
-
|
162
|
-
|
162
|
+
b->in_file = 1;
|
163
|
+
b->file_last = rb->temp_file->file.offset;
|
164
|
+
b->file = &rb->temp_file->file;
|
165
|
+
|
166
|
+
rb->bufs = cl;
|
163
167
|
}
|
164
168
|
|
165
|
-
|
169
|
+
post_handler(r);
|
166
170
|
|
167
|
-
|
168
|
-
b = NULL;
|
169
|
-
rb->rest = r->headers_in.content_length_n;
|
170
|
-
next = &rb->bufs;
|
171
|
+
return NGX_OK;
|
171
172
|
}
|
172
173
|
|
174
|
+
if (rb->rest < 0) {
|
175
|
+
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
176
|
+
"negative request body rest");
|
177
|
+
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
178
|
+
goto done;
|
179
|
+
}
|
180
|
+
|
181
|
+
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
182
|
+
|
173
183
|
size = clcf->client_body_buffer_size;
|
174
184
|
size += size >> 2;
|
175
185
|
|
176
|
-
|
186
|
+
/* TODO: honor r->request_body_in_single_buf */
|
187
|
+
|
188
|
+
if (!r->headers_in.chunked && rb->rest < size) {
|
177
189
|
size = (ssize_t) rb->rest;
|
178
190
|
|
179
191
|
if (r->request_body_in_single_buf) {
|
@@ -182,9 +194,6 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|
182
194
|
|
183
195
|
} else {
|
184
196
|
size = clcf->client_body_buffer_size;
|
185
|
-
|
186
|
-
/* disable copying buffer for r->request_body_in_single_buf */
|
187
|
-
b = NULL;
|
188
197
|
}
|
189
198
|
|
190
199
|
rb->buf = ngx_create_temp_buf(r->pool, size);
|
@@ -193,33 +202,8 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|
193
202
|
goto done;
|
194
203
|
}
|
195
204
|
|
196
|
-
cl = ngx_alloc_chain_link(r->pool);
|
197
|
-
if (cl == NULL) {
|
198
|
-
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
199
|
-
goto done;
|
200
|
-
}
|
201
|
-
|
202
|
-
cl->buf = rb->buf;
|
203
|
-
cl->next = NULL;
|
204
|
-
|
205
|
-
if (b && r->request_body_in_single_buf) {
|
206
|
-
size = b->last - b->pos;
|
207
|
-
ngx_memcpy(rb->buf->pos, b->pos, size);
|
208
|
-
rb->buf->last += size;
|
209
|
-
|
210
|
-
next = &rb->bufs;
|
211
|
-
}
|
212
|
-
|
213
|
-
*next = cl;
|
214
|
-
|
215
|
-
if (r->request_body_in_file_only || r->request_body_in_single_buf) {
|
216
|
-
rb->to_write = rb->bufs;
|
217
|
-
|
218
|
-
} else {
|
219
|
-
rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs;
|
220
|
-
}
|
221
|
-
|
222
205
|
r->read_event_handler = ngx_http_read_client_request_body_handler;
|
206
|
+
r->write_event_handler = ngx_http_request_empty_handler;
|
223
207
|
|
224
208
|
rc = ngx_http_do_read_client_request_body(r);
|
225
209
|
|
@@ -255,9 +239,12 @@ ngx_http_read_client_request_body_handler(ngx_http_request_t *r)
|
|
255
239
|
static ngx_int_t
|
256
240
|
ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
257
241
|
{
|
242
|
+
off_t rest;
|
258
243
|
size_t size;
|
259
244
|
ssize_t n;
|
245
|
+
ngx_int_t rc;
|
260
246
|
ngx_buf_t *b;
|
247
|
+
ngx_chain_t *cl, out;
|
261
248
|
ngx_connection_t *c;
|
262
249
|
ngx_http_request_body_t *rb;
|
263
250
|
ngx_http_core_loc_conf_t *clcf;
|
@@ -272,18 +259,44 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|
272
259
|
for ( ;; ) {
|
273
260
|
if (rb->buf->last == rb->buf->end) {
|
274
261
|
|
275
|
-
|
262
|
+
/* pass buffer to request body filter chain */
|
263
|
+
|
264
|
+
out.buf = rb->buf;
|
265
|
+
out.next = NULL;
|
266
|
+
|
267
|
+
rc = ngx_http_request_body_filter(r, &out);
|
268
|
+
|
269
|
+
if (rc != NGX_OK) {
|
270
|
+
return rc;
|
271
|
+
}
|
272
|
+
|
273
|
+
/* write to file */
|
274
|
+
|
275
|
+
if (ngx_http_write_request_body(r) != NGX_OK) {
|
276
276
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
277
277
|
}
|
278
278
|
|
279
|
-
|
279
|
+
/* update chains */
|
280
|
+
|
281
|
+
rc = ngx_http_request_body_filter(r, NULL);
|
282
|
+
|
283
|
+
if (rc != NGX_OK) {
|
284
|
+
return rc;
|
285
|
+
}
|
286
|
+
|
287
|
+
if (rb->busy != NULL) {
|
288
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
289
|
+
}
|
290
|
+
|
291
|
+
rb->buf->pos = rb->buf->start;
|
280
292
|
rb->buf->last = rb->buf->start;
|
281
293
|
}
|
282
294
|
|
283
295
|
size = rb->buf->end - rb->buf->last;
|
296
|
+
rest = rb->rest - (rb->buf->last - rb->buf->pos);
|
284
297
|
|
285
|
-
if ((off_t) size >
|
286
|
-
size = (size_t)
|
298
|
+
if ((off_t) size > rest) {
|
299
|
+
size = (size_t) rest;
|
287
300
|
}
|
288
301
|
|
289
302
|
n = c->recv(c, rb->buf->last, size);
|
@@ -306,9 +319,21 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|
306
319
|
}
|
307
320
|
|
308
321
|
rb->buf->last += n;
|
309
|
-
rb->rest -= n;
|
310
322
|
r->request_length += n;
|
311
323
|
|
324
|
+
if (n == rest) {
|
325
|
+
/* pass buffer to request body filter chain */
|
326
|
+
|
327
|
+
out.buf = rb->buf;
|
328
|
+
out.next = NULL;
|
329
|
+
|
330
|
+
rc = ngx_http_request_body_filter(r, &out);
|
331
|
+
|
332
|
+
if (rc != NGX_OK) {
|
333
|
+
return rc;
|
334
|
+
}
|
335
|
+
}
|
336
|
+
|
312
337
|
if (rb->rest == 0) {
|
313
338
|
break;
|
314
339
|
}
|
@@ -345,32 +370,24 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|
345
370
|
|
346
371
|
/* save the last part */
|
347
372
|
|
348
|
-
if (ngx_http_write_request_body(r
|
373
|
+
if (ngx_http_write_request_body(r) != NGX_OK) {
|
349
374
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
350
375
|
}
|
351
376
|
|
352
|
-
|
353
|
-
if (
|
377
|
+
cl = ngx_chain_get_free_buf(r->pool, &rb->free);
|
378
|
+
if (cl == NULL) {
|
354
379
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
355
380
|
}
|
356
381
|
|
382
|
+
b = cl->buf;
|
383
|
+
|
384
|
+
ngx_memzero(b, sizeof(ngx_buf_t));
|
385
|
+
|
357
386
|
b->in_file = 1;
|
358
|
-
b->file_pos = 0;
|
359
387
|
b->file_last = rb->temp_file->file.offset;
|
360
388
|
b->file = &rb->temp_file->file;
|
361
389
|
|
362
|
-
|
363
|
-
rb->bufs->next->buf = b;
|
364
|
-
|
365
|
-
} else {
|
366
|
-
rb->bufs->buf = b;
|
367
|
-
}
|
368
|
-
}
|
369
|
-
|
370
|
-
if (rb->bufs->next
|
371
|
-
&& (r->request_body_in_file_only || r->request_body_in_single_buf))
|
372
|
-
{
|
373
|
-
rb->bufs = rb->bufs->next;
|
390
|
+
rb->bufs = cl;
|
374
391
|
}
|
375
392
|
|
376
393
|
r->read_event_handler = ngx_http_block_reading;
|
@@ -382,15 +399,19 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
|
|
382
399
|
|
383
400
|
|
384
401
|
static ngx_int_t
|
385
|
-
ngx_http_write_request_body(ngx_http_request_t *r
|
402
|
+
ngx_http_write_request_body(ngx_http_request_t *r)
|
386
403
|
{
|
387
404
|
ssize_t n;
|
405
|
+
ngx_chain_t *cl;
|
388
406
|
ngx_temp_file_t *tf;
|
389
407
|
ngx_http_request_body_t *rb;
|
390
408
|
ngx_http_core_loc_conf_t *clcf;
|
391
409
|
|
392
410
|
rb = r->request_body;
|
393
411
|
|
412
|
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
413
|
+
"http write client request body, bufs %p", rb->bufs);
|
414
|
+
|
394
415
|
if (rb->temp_file == NULL) {
|
395
416
|
tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
|
396
417
|
if (tf == NULL) {
|
@@ -414,7 +435,7 @@ ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body)
|
|
414
435
|
|
415
436
|
rb->temp_file = tf;
|
416
437
|
|
417
|
-
if (
|
438
|
+
if (rb->bufs == NULL) {
|
418
439
|
/* empty body with r->request_body_in_file_only */
|
419
440
|
|
420
441
|
if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
|
@@ -428,7 +449,11 @@ ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body)
|
|
428
449
|
}
|
429
450
|
}
|
430
451
|
|
431
|
-
|
452
|
+
if (rb->bufs == NULL) {
|
453
|
+
return NGX_OK;
|
454
|
+
}
|
455
|
+
|
456
|
+
n = ngx_write_chain_to_temp_file(rb->temp_file, rb->bufs);
|
432
457
|
|
433
458
|
/* TODO: n == 0 or not complete and level event */
|
434
459
|
|
@@ -438,6 +463,14 @@ ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body)
|
|
438
463
|
|
439
464
|
rb->temp_file->offset += n;
|
440
465
|
|
466
|
+
/* mark all buffers as written */
|
467
|
+
|
468
|
+
for (cl = rb->bufs; cl; cl = cl->next) {
|
469
|
+
cl->buf->pos = cl->buf->last;
|
470
|
+
}
|
471
|
+
|
472
|
+
rb->bufs = NULL;
|
473
|
+
|
441
474
|
return NGX_OK;
|
442
475
|
}
|
443
476
|
|
@@ -446,9 +479,17 @@ ngx_int_t
|
|
446
479
|
ngx_http_discard_request_body(ngx_http_request_t *r)
|
447
480
|
{
|
448
481
|
ssize_t size;
|
482
|
+
ngx_int_t rc;
|
449
483
|
ngx_event_t *rev;
|
450
484
|
|
451
|
-
|
485
|
+
#if (NGX_HTTP_SPDY)
|
486
|
+
if (r->spdy_stream && r == r->main) {
|
487
|
+
r->spdy_stream->skip_data = NGX_SPDY_DATA_DISCARD;
|
488
|
+
return NGX_OK;
|
489
|
+
}
|
490
|
+
#endif
|
491
|
+
|
492
|
+
if (r != r->main || r->discard_body || r->request_body) {
|
452
493
|
return NGX_OK;
|
453
494
|
}
|
454
495
|
|
@@ -464,30 +505,36 @@ ngx_http_discard_request_body(ngx_http_request_t *r)
|
|
464
505
|
ngx_del_timer(rev);
|
465
506
|
}
|
466
507
|
|
467
|
-
if (r->headers_in.content_length_n <= 0
|
508
|
+
if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) {
|
468
509
|
return NGX_OK;
|
469
510
|
}
|
470
511
|
|
471
512
|
size = r->header_in->last - r->header_in->pos;
|
472
513
|
|
473
|
-
if (size) {
|
474
|
-
|
475
|
-
r->header_in->pos += size;
|
476
|
-
r->headers_in.content_length_n -= size;
|
514
|
+
if (size || r->headers_in.chunked) {
|
515
|
+
rc = ngx_http_discard_request_body_filter(r, r->header_in);
|
477
516
|
|
478
|
-
|
479
|
-
|
480
|
-
|
517
|
+
if (rc != NGX_OK) {
|
518
|
+
return rc;
|
519
|
+
}
|
520
|
+
|
521
|
+
if (r->headers_in.content_length_n == 0) {
|
481
522
|
return NGX_OK;
|
482
523
|
}
|
483
524
|
}
|
484
525
|
|
485
|
-
|
526
|
+
rc = ngx_http_read_discarded_request_body(r);
|
527
|
+
|
528
|
+
if (rc == NGX_OK) {
|
486
529
|
r->lingering_close = 0;
|
487
530
|
return NGX_OK;
|
488
531
|
}
|
489
532
|
|
490
|
-
|
533
|
+
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
534
|
+
return rc;
|
535
|
+
}
|
536
|
+
|
537
|
+
/* rc == NGX_AGAIN */
|
491
538
|
|
492
539
|
r->read_event_handler = ngx_http_discarded_request_body_handler;
|
493
540
|
|
@@ -544,6 +591,12 @@ ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
|
|
544
591
|
return;
|
545
592
|
}
|
546
593
|
|
594
|
+
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
595
|
+
c->error = 1;
|
596
|
+
ngx_http_finalize_request(r, NGX_ERROR);
|
597
|
+
return;
|
598
|
+
}
|
599
|
+
|
547
600
|
/* rc == NGX_AGAIN */
|
548
601
|
|
549
602
|
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
@@ -570,13 +623,19 @@ ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
|
|
570
623
|
static ngx_int_t
|
571
624
|
ngx_http_read_discarded_request_body(ngx_http_request_t *r)
|
572
625
|
{
|
573
|
-
size_t
|
574
|
-
ssize_t
|
575
|
-
|
626
|
+
size_t size;
|
627
|
+
ssize_t n;
|
628
|
+
ngx_int_t rc;
|
629
|
+
ngx_buf_t b;
|
630
|
+
u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
|
576
631
|
|
577
632
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
578
633
|
"http read discarded body");
|
579
634
|
|
635
|
+
ngx_memzero(&b, sizeof(ngx_buf_t));
|
636
|
+
|
637
|
+
b.temporary = 1;
|
638
|
+
|
580
639
|
for ( ;; ) {
|
581
640
|
if (r->headers_in.content_length_n == 0) {
|
582
641
|
r->read_event_handler = ngx_http_block_reading;
|
@@ -587,9 +646,8 @@ ngx_http_read_discarded_request_body(ngx_http_request_t *r)
|
|
587
646
|
return NGX_AGAIN;
|
588
647
|
}
|
589
648
|
|
590
|
-
size = (r->headers_in.content_length_n
|
591
|
-
|
592
|
-
(size_t) r->headers_in.content_length_n;
|
649
|
+
size = (size_t) ngx_min(r->headers_in.content_length_n,
|
650
|
+
NGX_HTTP_DISCARD_BUFFER_SIZE);
|
593
651
|
|
594
652
|
n = r->connection->recv(r->connection, buffer, size);
|
595
653
|
|
@@ -606,8 +664,104 @@ ngx_http_read_discarded_request_body(ngx_http_request_t *r)
|
|
606
664
|
return NGX_OK;
|
607
665
|
}
|
608
666
|
|
609
|
-
|
667
|
+
b.pos = buffer;
|
668
|
+
b.last = buffer + n;
|
669
|
+
|
670
|
+
rc = ngx_http_discard_request_body_filter(r, &b);
|
671
|
+
|
672
|
+
if (rc != NGX_OK) {
|
673
|
+
return rc;
|
674
|
+
}
|
675
|
+
}
|
676
|
+
}
|
677
|
+
|
678
|
+
|
679
|
+
static ngx_int_t
|
680
|
+
ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
|
681
|
+
{
|
682
|
+
size_t size;
|
683
|
+
ngx_int_t rc;
|
684
|
+
ngx_http_request_body_t *rb;
|
685
|
+
|
686
|
+
if (r->headers_in.chunked) {
|
687
|
+
|
688
|
+
rb = r->request_body;
|
689
|
+
|
690
|
+
if (rb == NULL) {
|
691
|
+
|
692
|
+
rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
|
693
|
+
if (rb == NULL) {
|
694
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
695
|
+
}
|
696
|
+
|
697
|
+
rb->chunked = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_t));
|
698
|
+
if (rb->chunked == NULL) {
|
699
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
700
|
+
}
|
701
|
+
|
702
|
+
r->request_body = rb;
|
703
|
+
}
|
704
|
+
|
705
|
+
for ( ;; ) {
|
706
|
+
|
707
|
+
rc = ngx_http_parse_chunked(r, b, rb->chunked);
|
708
|
+
|
709
|
+
if (rc == NGX_OK) {
|
710
|
+
|
711
|
+
/* a chunk has been parsed successfully */
|
712
|
+
|
713
|
+
size = b->last - b->pos;
|
714
|
+
|
715
|
+
if ((off_t) size > rb->chunked->size) {
|
716
|
+
b->pos += rb->chunked->size;
|
717
|
+
rb->chunked->size = 0;
|
718
|
+
|
719
|
+
} else {
|
720
|
+
rb->chunked->size -= size;
|
721
|
+
b->pos = b->last;
|
722
|
+
}
|
723
|
+
|
724
|
+
continue;
|
725
|
+
}
|
726
|
+
|
727
|
+
if (rc == NGX_DONE) {
|
728
|
+
|
729
|
+
/* a whole response has been parsed successfully */
|
730
|
+
|
731
|
+
r->headers_in.content_length_n = 0;
|
732
|
+
break;
|
733
|
+
}
|
734
|
+
|
735
|
+
if (rc == NGX_AGAIN) {
|
736
|
+
|
737
|
+
/* set amount of data we want to see next time */
|
738
|
+
|
739
|
+
r->headers_in.content_length_n = rb->chunked->length;
|
740
|
+
break;
|
741
|
+
}
|
742
|
+
|
743
|
+
/* invalid */
|
744
|
+
|
745
|
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
746
|
+
"client sent invalid chunked body");
|
747
|
+
|
748
|
+
return NGX_HTTP_BAD_REQUEST;
|
749
|
+
}
|
750
|
+
|
751
|
+
} else {
|
752
|
+
size = b->last - b->pos;
|
753
|
+
|
754
|
+
if ((off_t) size > r->headers_in.content_length_n) {
|
755
|
+
b->pos += r->headers_in.content_length_n;
|
756
|
+
r->headers_in.content_length_n = 0;
|
757
|
+
|
758
|
+
} else {
|
759
|
+
b->pos = b->last;
|
760
|
+
r->headers_in.content_length_n -= size;
|
761
|
+
}
|
610
762
|
}
|
763
|
+
|
764
|
+
return NGX_OK;
|
611
765
|
}
|
612
766
|
|
613
767
|
|
@@ -651,3 +805,278 @@ ngx_http_test_expect(ngx_http_request_t *r)
|
|
651
805
|
|
652
806
|
return NGX_ERROR;
|
653
807
|
}
|
808
|
+
|
809
|
+
|
810
|
+
static ngx_int_t
|
811
|
+
ngx_http_request_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
812
|
+
{
|
813
|
+
if (r->headers_in.chunked) {
|
814
|
+
return ngx_http_request_body_chunked_filter(r, in);
|
815
|
+
|
816
|
+
} else {
|
817
|
+
return ngx_http_request_body_length_filter(r, in);
|
818
|
+
}
|
819
|
+
}
|
820
|
+
|
821
|
+
|
822
|
+
static ngx_int_t
|
823
|
+
ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
824
|
+
{
|
825
|
+
size_t size;
|
826
|
+
ngx_int_t rc;
|
827
|
+
ngx_buf_t *b;
|
828
|
+
ngx_chain_t *cl, *tl, *out, **ll;
|
829
|
+
ngx_http_request_body_t *rb;
|
830
|
+
|
831
|
+
rb = r->request_body;
|
832
|
+
|
833
|
+
if (rb->rest == -1) {
|
834
|
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
835
|
+
"http request body content length filter");
|
836
|
+
|
837
|
+
rb->rest = r->headers_in.content_length_n;
|
838
|
+
}
|
839
|
+
|
840
|
+
out = NULL;
|
841
|
+
ll = &out;
|
842
|
+
|
843
|
+
for (cl = in; cl; cl = cl->next) {
|
844
|
+
|
845
|
+
tl = ngx_chain_get_free_buf(r->pool, &rb->free);
|
846
|
+
if (tl == NULL) {
|
847
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
848
|
+
}
|
849
|
+
|
850
|
+
b = tl->buf;
|
851
|
+
|
852
|
+
ngx_memzero(b, sizeof(ngx_buf_t));
|
853
|
+
|
854
|
+
b->temporary = 1;
|
855
|
+
b->tag = (ngx_buf_tag_t) &ngx_http_read_client_request_body;
|
856
|
+
b->start = cl->buf->pos;
|
857
|
+
b->pos = cl->buf->pos;
|
858
|
+
b->last = cl->buf->last;
|
859
|
+
b->end = cl->buf->end;
|
860
|
+
|
861
|
+
size = cl->buf->last - cl->buf->pos;
|
862
|
+
|
863
|
+
if ((off_t) size < rb->rest) {
|
864
|
+
cl->buf->pos = cl->buf->last;
|
865
|
+
rb->rest -= size;
|
866
|
+
|
867
|
+
} else {
|
868
|
+
cl->buf->pos += rb->rest;
|
869
|
+
rb->rest = 0;
|
870
|
+
b->last = cl->buf->pos;
|
871
|
+
b->last_buf = 1;
|
872
|
+
}
|
873
|
+
|
874
|
+
*ll = tl;
|
875
|
+
ll = &tl->next;
|
876
|
+
}
|
877
|
+
|
878
|
+
rc = ngx_http_request_body_save_filter(r, out);
|
879
|
+
|
880
|
+
ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &out,
|
881
|
+
(ngx_buf_tag_t) &ngx_http_read_client_request_body);
|
882
|
+
|
883
|
+
return rc;
|
884
|
+
}
|
885
|
+
|
886
|
+
|
887
|
+
static ngx_int_t
|
888
|
+
ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
889
|
+
{
|
890
|
+
size_t size;
|
891
|
+
ngx_int_t rc;
|
892
|
+
ngx_buf_t *b;
|
893
|
+
ngx_chain_t *cl, *out, *tl, **ll;
|
894
|
+
ngx_http_request_body_t *rb;
|
895
|
+
ngx_http_core_loc_conf_t *clcf;
|
896
|
+
|
897
|
+
rb = r->request_body;
|
898
|
+
|
899
|
+
if (rb->rest == -1) {
|
900
|
+
|
901
|
+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
902
|
+
"http request body chunked filter");
|
903
|
+
|
904
|
+
rb->chunked = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_t));
|
905
|
+
if (rb->chunked == NULL) {
|
906
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
907
|
+
}
|
908
|
+
|
909
|
+
r->headers_in.content_length_n = 0;
|
910
|
+
rb->rest = 3;
|
911
|
+
}
|
912
|
+
|
913
|
+
out = NULL;
|
914
|
+
ll = &out;
|
915
|
+
|
916
|
+
for (cl = in; cl; cl = cl->next) {
|
917
|
+
|
918
|
+
for ( ;; ) {
|
919
|
+
|
920
|
+
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
|
921
|
+
"http body chunked buf "
|
922
|
+
"t:%d f:%d %p, pos %p, size: %z file: %O, size: %z",
|
923
|
+
cl->buf->temporary, cl->buf->in_file,
|
924
|
+
cl->buf->start, cl->buf->pos,
|
925
|
+
cl->buf->last - cl->buf->pos,
|
926
|
+
cl->buf->file_pos,
|
927
|
+
cl->buf->file_last - cl->buf->file_pos);
|
928
|
+
|
929
|
+
rc = ngx_http_parse_chunked(r, cl->buf, rb->chunked);
|
930
|
+
|
931
|
+
if (rc == NGX_OK) {
|
932
|
+
|
933
|
+
/* a chunk has been parsed successfully */
|
934
|
+
|
935
|
+
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
936
|
+
|
937
|
+
if (clcf->client_max_body_size
|
938
|
+
&& clcf->client_max_body_size
|
939
|
+
< r->headers_in.content_length_n + rb->chunked->size)
|
940
|
+
{
|
941
|
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
942
|
+
"client intended to send too large chunked "
|
943
|
+
"body: %O bytes",
|
944
|
+
r->headers_in.content_length_n
|
945
|
+
+ rb->chunked->size);
|
946
|
+
|
947
|
+
r->lingering_close = 1;
|
948
|
+
|
949
|
+
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
|
950
|
+
}
|
951
|
+
|
952
|
+
tl = ngx_chain_get_free_buf(r->pool, &rb->free);
|
953
|
+
if (tl == NULL) {
|
954
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
955
|
+
}
|
956
|
+
|
957
|
+
b = tl->buf;
|
958
|
+
|
959
|
+
ngx_memzero(b, sizeof(ngx_buf_t));
|
960
|
+
|
961
|
+
b->temporary = 1;
|
962
|
+
b->tag = (ngx_buf_tag_t) &ngx_http_read_client_request_body;
|
963
|
+
b->start = cl->buf->pos;
|
964
|
+
b->pos = cl->buf->pos;
|
965
|
+
b->last = cl->buf->last;
|
966
|
+
b->end = cl->buf->end;
|
967
|
+
|
968
|
+
*ll = tl;
|
969
|
+
ll = &tl->next;
|
970
|
+
|
971
|
+
size = cl->buf->last - cl->buf->pos;
|
972
|
+
|
973
|
+
if ((off_t) size > rb->chunked->size) {
|
974
|
+
cl->buf->pos += rb->chunked->size;
|
975
|
+
r->headers_in.content_length_n += rb->chunked->size;
|
976
|
+
rb->chunked->size = 0;
|
977
|
+
|
978
|
+
} else {
|
979
|
+
rb->chunked->size -= size;
|
980
|
+
r->headers_in.content_length_n += size;
|
981
|
+
cl->buf->pos = cl->buf->last;
|
982
|
+
}
|
983
|
+
|
984
|
+
b->last = cl->buf->pos;
|
985
|
+
|
986
|
+
continue;
|
987
|
+
}
|
988
|
+
|
989
|
+
if (rc == NGX_DONE) {
|
990
|
+
|
991
|
+
/* a whole response has been parsed successfully */
|
992
|
+
|
993
|
+
rb->rest = 0;
|
994
|
+
|
995
|
+
tl = ngx_chain_get_free_buf(r->pool, &rb->free);
|
996
|
+
if (tl == NULL) {
|
997
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
998
|
+
}
|
999
|
+
|
1000
|
+
b = tl->buf;
|
1001
|
+
|
1002
|
+
ngx_memzero(b, sizeof(ngx_buf_t));
|
1003
|
+
|
1004
|
+
b->last_buf = 1;
|
1005
|
+
|
1006
|
+
*ll = tl;
|
1007
|
+
ll = &tl->next;
|
1008
|
+
|
1009
|
+
break;
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
if (rc == NGX_AGAIN) {
|
1013
|
+
|
1014
|
+
/* set rb->rest, amount of data we want to see next time */
|
1015
|
+
|
1016
|
+
rb->rest = rb->chunked->length;
|
1017
|
+
|
1018
|
+
break;
|
1019
|
+
}
|
1020
|
+
|
1021
|
+
/* invalid */
|
1022
|
+
|
1023
|
+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
1024
|
+
"client sent invalid chunked body");
|
1025
|
+
|
1026
|
+
return NGX_HTTP_BAD_REQUEST;
|
1027
|
+
}
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
rc = ngx_http_request_body_save_filter(r, out);
|
1031
|
+
|
1032
|
+
ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &out,
|
1033
|
+
(ngx_buf_tag_t) &ngx_http_read_client_request_body);
|
1034
|
+
|
1035
|
+
return rc;
|
1036
|
+
}
|
1037
|
+
|
1038
|
+
|
1039
|
+
static ngx_int_t
|
1040
|
+
ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
1041
|
+
{
|
1042
|
+
#if (NGX_DEBUG)
|
1043
|
+
ngx_chain_t *cl;
|
1044
|
+
#endif
|
1045
|
+
ngx_http_request_body_t *rb;
|
1046
|
+
|
1047
|
+
rb = r->request_body;
|
1048
|
+
|
1049
|
+
#if (NGX_DEBUG)
|
1050
|
+
|
1051
|
+
for (cl = rb->bufs; cl; cl = cl->next) {
|
1052
|
+
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
|
1053
|
+
"http body old buf t:%d f:%d %p, pos %p, size: %z "
|
1054
|
+
"file: %O, size: %z",
|
1055
|
+
cl->buf->temporary, cl->buf->in_file,
|
1056
|
+
cl->buf->start, cl->buf->pos,
|
1057
|
+
cl->buf->last - cl->buf->pos,
|
1058
|
+
cl->buf->file_pos,
|
1059
|
+
cl->buf->file_last - cl->buf->file_pos);
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
for (cl = in; cl; cl = cl->next) {
|
1063
|
+
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
|
1064
|
+
"http body new buf t:%d f:%d %p, pos %p, size: %z "
|
1065
|
+
"file: %O, size: %z",
|
1066
|
+
cl->buf->temporary, cl->buf->in_file,
|
1067
|
+
cl->buf->start, cl->buf->pos,
|
1068
|
+
cl->buf->last - cl->buf->pos,
|
1069
|
+
cl->buf->file_pos,
|
1070
|
+
cl->buf->file_last - cl->buf->file_pos);
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
#endif
|
1074
|
+
|
1075
|
+
/* TODO: coalesce neighbouring buffers */
|
1076
|
+
|
1077
|
+
if (ngx_chain_add_copy(r->pool, &rb->bufs, in) != NGX_OK) {
|
1078
|
+
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
return NGX_OK;
|
1082
|
+
}
|