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.
Files changed (89) hide show
  1. data/bin/nginxtra +1 -1
  2. data/bin/nginxtra_rails +1 -1
  3. data/lib/nginxtra/version.rb +1 -1
  4. data/vendor/nginx/CHANGES +202 -63
  5. data/vendor/nginx/CHANGES.ru +208 -66
  6. data/vendor/nginx/auto/lib/md5/conf +3 -3
  7. data/vendor/nginx/auto/lib/perl/conf +3 -1
  8. data/vendor/nginx/auto/lib/perl/make +21 -16
  9. data/vendor/nginx/auto/lib/sha1/conf +1 -1
  10. data/vendor/nginx/auto/modules +25 -4
  11. data/vendor/nginx/auto/options +7 -1
  12. data/vendor/nginx/auto/sources +15 -1
  13. data/vendor/nginx/auto/unix +14 -0
  14. data/vendor/nginx/src/core/nginx.h +2 -2
  15. data/vendor/nginx/src/core/ngx_array.c +1 -7
  16. data/vendor/nginx/src/core/ngx_array.h +2 -2
  17. data/vendor/nginx/src/core/ngx_connection.c +13 -7
  18. data/vendor/nginx/src/core/ngx_connection.h +1 -2
  19. data/vendor/nginx/src/core/ngx_core.h +1 -2
  20. data/vendor/nginx/src/core/ngx_crypt.c +37 -0
  21. data/vendor/nginx/src/core/ngx_cycle.h +1 -1
  22. data/vendor/nginx/src/core/ngx_inet.c +219 -48
  23. data/vendor/nginx/src/core/ngx_inet.h +1 -1
  24. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +7 -1
  25. data/vendor/nginx/src/event/modules/ngx_eventport_module.c +1 -1
  26. data/vendor/nginx/src/event/ngx_event.c +5 -1
  27. data/vendor/nginx/src/event/ngx_event.h +1 -0
  28. data/vendor/nginx/src/event/ngx_event_connect.c +1 -1
  29. data/vendor/nginx/src/event/ngx_event_openssl.c +135 -9
  30. data/vendor/nginx/src/event/ngx_event_openssl.h +9 -0
  31. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +1749 -0
  32. data/vendor/nginx/src/http/modules/ngx_http_addition_filter_module.c +1 -0
  33. data/vendor/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -0
  34. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +5 -0
  35. data/vendor/nginx/src/http/modules/ngx_http_flv_module.c +4 -0
  36. data/vendor/nginx/src/http/modules/ngx_http_geo_module.c +7 -8
  37. data/vendor/nginx/src/http/modules/ngx_http_geoip_module.c +10 -12
  38. data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +677 -0
  39. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +3 -0
  40. data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +36 -10
  41. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +31 -13
  42. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +13 -0
  43. data/vendor/nginx/src/http/modules/ngx_http_limit_conn_module.c +18 -2
  44. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +19 -2
  45. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +1 -1
  46. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +60 -8
  47. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +4 -8
  48. data/vendor/nginx/src/http/modules/ngx_http_not_modified_filter_module.c +126 -29
  49. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +59 -301
  50. data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +34 -6
  51. data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +13 -12
  52. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +30 -11
  53. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +1 -0
  54. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +155 -4
  55. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +6 -0
  56. data/vendor/nginx/src/http/modules/ngx_http_static_module.c +4 -0
  57. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +90 -3
  58. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +1 -0
  59. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +5 -0
  60. data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +5 -0
  61. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +14 -1
  62. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +1 -0
  63. data/vendor/nginx/src/http/modules/perl/Makefile.PL +4 -2
  64. data/vendor/nginx/src/http/modules/perl/nginx.pm +1 -1
  65. data/vendor/nginx/src/http/modules/perl/nginx.xs +36 -3
  66. data/vendor/nginx/src/http/ngx_http.c +24 -1
  67. data/vendor/nginx/src/http/ngx_http.h +26 -2
  68. data/vendor/nginx/src/http/ngx_http_core_module.c +136 -10
  69. data/vendor/nginx/src/http/ngx_http_core_module.h +37 -13
  70. data/vendor/nginx/src/http/ngx_http_header_filter_module.c +9 -2
  71. data/vendor/nginx/src/http/ngx_http_parse.c +404 -0
  72. data/vendor/nginx/src/http/ngx_http_request.c +840 -517
  73. data/vendor/nginx/src/http/ngx_http_request.h +37 -25
  74. data/vendor/nginx/src/http/ngx_http_request_body.c +585 -156
  75. data/vendor/nginx/src/http/ngx_http_spdy.c +2882 -0
  76. data/vendor/nginx/src/http/ngx_http_spdy.h +235 -0
  77. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +999 -0
  78. data/vendor/nginx/src/http/ngx_http_spdy_module.c +351 -0
  79. data/vendor/nginx/src/http/ngx_http_spdy_module.h +36 -0
  80. data/vendor/nginx/src/http/ngx_http_special_response.c +3 -1
  81. data/vendor/nginx/src/http/ngx_http_upstream.c +415 -26
  82. data/vendor/nginx/src/http/ngx_http_upstream.h +11 -1
  83. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +2 -45
  84. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.h +0 -2
  85. data/vendor/nginx/src/http/ngx_http_variables.c +72 -12
  86. data/vendor/nginx/src/mail/ngx_mail.h +2 -2
  87. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +35 -25
  88. data/vendor/nginx/src/mail/ngx_mail_core_module.c +5 -1
  89. 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
- ngx_table_elt_t *x_forwarded_for;
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 *to_write;
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
- ngx_http_request_t *request;
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
- ngx_uint_t pipeline; /* unsigned pipeline:1; */
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 *cl, **next;
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
- if (r->request_body || r->discard_body) {
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->rest = 0;
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
- b = ngx_calloc_buf(r->pool);
101
- if (b == NULL) {
102
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
103
- goto done;
104
- }
97
+ out.buf = r->header_in;
98
+ out.next = NULL;
105
99
 
106
- b->temporary = 1;
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
- rb->bufs = ngx_alloc_chain_link(r->pool);
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
- rb->bufs->buf = b;
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 ((off_t) preread >= r->headers_in.content_length_n) {
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
- /* the whole request body was pre-read */
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
- r->header_in->pos += (size_t) r->headers_in.content_length_n;
128
- r->request_length += r->headers_in.content_length_n;
129
- b->last = r->header_in->pos;
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
- if (r->request_body_in_file_only) {
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
- post_handler(r);
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
- return NGX_OK;
131
+ rc = ngx_http_do_read_client_request_body(r);
132
+ goto done;
141
133
  }
142
134
 
143
- /*
144
- * to not consider the body as pipelined request in
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->request_length += preread;
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
- rb->rest = r->headers_in.content_length_n - preread;
144
+ if (rb->rest == 0) {
145
+ /* the whole request body was pre-read */
152
146
 
153
- if (rb->rest <= (off_t) (b->end - b->last)) {
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
- /* the whole request body may be placed in r->header_in */
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
- rb->to_write = rb->bufs;
158
+ b = cl->buf;
158
159
 
159
- r->read_event_handler = ngx_http_read_client_request_body_handler;
160
+ ngx_memzero(b, sizeof(ngx_buf_t));
160
161
 
161
- rc = ngx_http_do_read_client_request_body(r);
162
- goto done;
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
- next = &rb->bufs->next;
169
+ post_handler(r);
166
170
 
167
- } else {
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
- if (rb->rest < size) {
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
- if (ngx_http_write_request_body(r, rb->to_write) != NGX_OK) {
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
- rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs;
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 > rb->rest) {
286
- size = (size_t) rb->rest;
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, rb->to_write) != NGX_OK) {
373
+ if (ngx_http_write_request_body(r) != NGX_OK) {
349
374
  return NGX_HTTP_INTERNAL_SERVER_ERROR;
350
375
  }
351
376
 
352
- b = ngx_calloc_buf(r->pool);
353
- if (b == NULL) {
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
- if (rb->bufs->next) {
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, ngx_chain_t *body)
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 (body == NULL) {
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
- n = ngx_write_chain_to_temp_file(rb->temp_file, body);
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
- if (r != r->main || r->discard_body) {
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 || r->request_body) {
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
- if (r->headers_in.content_length_n > size) {
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
- } else {
479
- r->header_in->pos += (size_t) r->headers_in.content_length_n;
480
- r->headers_in.content_length_n = 0;
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
- if (ngx_http_read_discarded_request_body(r) == NGX_OK) {
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
- /* == NGX_AGAIN */
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 size;
574
- ssize_t n;
575
- u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
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 > NGX_HTTP_DISCARD_BUFFER_SIZE) ?
591
- NGX_HTTP_DISCARD_BUFFER_SIZE:
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
- r->headers_in.content_length_n -= n;
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
+ }