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
@@ -586,6 +586,10 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
586
586
  r->headers_out.status = NGX_HTTP_OK;
587
587
  r->headers_out.last_modified_time = of.mtime;
588
588
 
589
+ if (ngx_http_set_etag(r) != NGX_OK) {
590
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
591
+ }
592
+
589
593
  if (ngx_http_set_content_type(r) != NGX_OK) {
590
594
  return NGX_HTTP_INTERNAL_SERVER_ERROR;
591
595
  }
@@ -1845,14 +1849,6 @@ ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
1845
1849
  ngx_mp4_get_32value(stsd_atom->entries),
1846
1850
  4, stsd_atom->media_name);
1847
1851
 
1848
- /* supported media format: "avc1" (H.264) and "mp4a" (MPEG-4/AAC) */
1849
-
1850
- if (ngx_strncmp(stsd_atom->media_name, "avc1", 4) != 0
1851
- && ngx_strncmp(stsd_atom->media_name, "mp4a", 4) != 0)
1852
- {
1853
- return NGX_DECLINED;
1854
- }
1855
-
1856
1852
  trak = ngx_mp4_last_trak(mp4);
1857
1853
 
1858
1854
  atom = &trak->stsd_atom_buf;
@@ -10,8 +10,10 @@
10
10
  #include <ngx_http.h>
11
11
 
12
12
 
13
- static ngx_int_t ngx_http_test_precondition(ngx_http_request_t *r);
14
- static ngx_int_t ngx_http_test_not_modified(ngx_http_request_t *r);
13
+ static ngx_uint_t ngx_http_test_if_unmodified(ngx_http_request_t *r);
14
+ static ngx_uint_t ngx_http_test_if_modified(ngx_http_request_t *r);
15
+ static ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r,
16
+ ngx_table_elt_t *header);
15
17
  static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);
16
18
 
17
19
 
@@ -59,20 +61,56 @@ ngx_http_not_modified_header_filter(ngx_http_request_t *r)
59
61
  return ngx_http_next_header_filter(r);
60
62
  }
61
63
 
62
- if (r->headers_in.if_unmodified_since) {
63
- return ngx_http_test_precondition(r);
64
+ if (r->headers_in.if_unmodified_since
65
+ && !ngx_http_test_if_unmodified(r))
66
+ {
67
+ return ngx_http_filter_finalize_request(r, NULL,
68
+ NGX_HTTP_PRECONDITION_FAILED);
64
69
  }
65
70
 
66
- if (r->headers_in.if_modified_since) {
67
- return ngx_http_test_not_modified(r);
71
+ if (r->headers_in.if_match
72
+ && !ngx_http_test_if_match(r, r->headers_in.if_match))
73
+ {
74
+ return ngx_http_filter_finalize_request(r, NULL,
75
+ NGX_HTTP_PRECONDITION_FAILED);
76
+ }
77
+
78
+ if (r->headers_in.if_modified_since || r->headers_in.if_none_match) {
79
+
80
+ if (r->headers_in.if_modified_since
81
+ && ngx_http_test_if_modified(r))
82
+ {
83
+ return ngx_http_next_header_filter(r);
84
+ }
85
+
86
+ if (r->headers_in.if_none_match
87
+ && !ngx_http_test_if_match(r, r->headers_in.if_none_match))
88
+ {
89
+ return ngx_http_next_header_filter(r);
90
+ }
91
+
92
+ /* not modified */
93
+
94
+ r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
95
+ r->headers_out.status_line.len = 0;
96
+ r->headers_out.content_type.len = 0;
97
+ ngx_http_clear_content_length(r);
98
+ ngx_http_clear_accept_ranges(r);
99
+
100
+ if (r->headers_out.content_encoding) {
101
+ r->headers_out.content_encoding->hash = 0;
102
+ r->headers_out.content_encoding = NULL;
103
+ }
104
+
105
+ return ngx_http_next_header_filter(r);
68
106
  }
69
107
 
70
108
  return ngx_http_next_header_filter(r);
71
109
  }
72
110
 
73
111
 
74
- static ngx_int_t
75
- ngx_http_test_precondition(ngx_http_request_t *r)
112
+ static ngx_uint_t
113
+ ngx_http_test_if_unmodified(ngx_http_request_t *r)
76
114
  {
77
115
  time_t iums;
78
116
 
@@ -83,16 +121,15 @@ ngx_http_test_precondition(ngx_http_request_t *r)
83
121
  "http iums:%d lm:%d", iums, r->headers_out.last_modified_time);
84
122
 
85
123
  if (iums >= r->headers_out.last_modified_time) {
86
- return ngx_http_next_header_filter(r);
124
+ return 1;
87
125
  }
88
126
 
89
- return ngx_http_filter_finalize_request(r, NULL,
90
- NGX_HTTP_PRECONDITION_FAILED);
127
+ return 0;
91
128
  }
92
129
 
93
130
 
94
- static ngx_int_t
95
- ngx_http_test_not_modified(ngx_http_request_t *r)
131
+ static ngx_uint_t
132
+ ngx_http_test_if_modified(ngx_http_request_t *r)
96
133
  {
97
134
  time_t ims;
98
135
  ngx_http_core_loc_conf_t *clcf;
@@ -100,7 +137,7 @@ ngx_http_test_not_modified(ngx_http_request_t *r)
100
137
  clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
101
138
 
102
139
  if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
103
- return ngx_http_next_header_filter(r);
140
+ return 1;
104
141
  }
105
142
 
106
143
  ims = ngx_http_parse_time(r->headers_in.if_modified_since->value.data,
@@ -109,27 +146,87 @@ ngx_http_test_not_modified(ngx_http_request_t *r)
109
146
  ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
110
147
  "http ims:%d lm:%d", ims, r->headers_out.last_modified_time);
111
148
 
112
- if (ims != r->headers_out.last_modified_time) {
149
+ if (ims == r->headers_out.last_modified_time) {
150
+ return 0;
151
+ }
113
152
 
114
- if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
115
- || ims < r->headers_out.last_modified_time)
116
- {
117
- return ngx_http_next_header_filter(r);
118
- }
153
+ if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
154
+ || ims < r->headers_out.last_modified_time)
155
+ {
156
+ return 1;
119
157
  }
120
158
 
121
- r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
122
- r->headers_out.status_line.len = 0;
123
- r->headers_out.content_type.len = 0;
124
- ngx_http_clear_content_length(r);
125
- ngx_http_clear_accept_ranges(r);
159
+ return 0;
160
+ }
161
+
126
162
 
127
- if (r->headers_out.content_encoding) {
128
- r->headers_out.content_encoding->hash = 0;
129
- r->headers_out.content_encoding = NULL;
163
+ static ngx_uint_t
164
+ ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header)
165
+ {
166
+ u_char *start, *end, ch;
167
+ ngx_str_t *etag, *list;
168
+
169
+ list = &header->value;
170
+
171
+ if (list->len == 1 && list->data[0] == '*') {
172
+ return 1;
130
173
  }
131
174
 
132
- return ngx_http_next_header_filter(r);
175
+ if (r->headers_out.etag == NULL) {
176
+ return 0;
177
+ }
178
+
179
+ etag = &r->headers_out.etag->value;
180
+
181
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
182
+ "http im:\"%V\" etag:%V", list, etag);
183
+
184
+ start = list->data;
185
+ end = list->data + list->len;
186
+
187
+ while (start < end) {
188
+
189
+ if (etag->len > (size_t) (end - start)) {
190
+ return 0;
191
+ }
192
+
193
+ if (ngx_strncmp(start, etag->data, etag->len) != 0) {
194
+ goto skip;
195
+ }
196
+
197
+ start += etag->len;
198
+
199
+ while (start < end) {
200
+ ch = *start;
201
+
202
+ if (ch == ' ' || ch == '\t') {
203
+ start++;
204
+ continue;
205
+ }
206
+
207
+ break;
208
+ }
209
+
210
+ if (start == end || *start == ',') {
211
+ return 1;
212
+ }
213
+
214
+ skip:
215
+
216
+ while (start < end && *start != ',') { start++; }
217
+ while (start < end) {
218
+ ch = *start;
219
+
220
+ if (ch == ' ' || ch == '\t' || ch == ',') {
221
+ start++;
222
+ continue;
223
+ }
224
+
225
+ break;
226
+ }
227
+ }
228
+
229
+ return 0;
133
230
  }
134
231
 
135
232
 
@@ -81,12 +81,9 @@ typedef struct {
81
81
 
82
82
  typedef struct {
83
83
  ngx_http_status_t status;
84
+ ngx_http_chunked_t chunked;
84
85
  ngx_http_proxy_vars_t vars;
85
- size_t internal_body_length;
86
-
87
- ngx_uint_t state;
88
- off_t size;
89
- off_t length;
86
+ off_t internal_body_length;
90
87
 
91
88
  ngx_uint_t head; /* unsigned head:1 */
92
89
  } ngx_http_proxy_ctx_t;
@@ -558,6 +555,8 @@ static char ngx_http_proxy_version_11[] = " HTTP/1.1" CRLF;
558
555
  static ngx_keyval_t ngx_http_proxy_headers[] = {
559
556
  { ngx_string("Host"), ngx_string("$proxy_host") },
560
557
  { ngx_string("Connection"), ngx_string("close") },
558
+ { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
559
+ { ngx_string("Transfer-Encoding"), ngx_string("") },
561
560
  { ngx_string("Keep-Alive"), ngx_string("") },
562
561
  { ngx_string("Expect"), ngx_string("") },
563
562
  { ngx_string("Upgrade"), ngx_string("") },
@@ -583,6 +582,8 @@ static ngx_str_t ngx_http_proxy_hide_headers[] = {
583
582
  static ngx_keyval_t ngx_http_proxy_cache_headers[] = {
584
583
  { ngx_string("Host"), ngx_string("$proxy_host") },
585
584
  { ngx_string("Connection"), ngx_string("close") },
585
+ { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
586
+ { ngx_string("Transfer-Encoding"), ngx_string("") },
586
587
  { ngx_string("Keep-Alive"), ngx_string("") },
587
588
  { ngx_string("Expect"), ngx_string("") },
588
589
  { ngx_string("Upgrade"), ngx_string("") },
@@ -1006,6 +1007,9 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
1006
1007
 
1007
1008
  ctx->internal_body_length = body_len;
1008
1009
  len += body_len;
1010
+
1011
+ } else {
1012
+ ctx->internal_body_length = r->headers_in.content_length_n;
1009
1013
  }
1010
1014
 
1011
1015
  le.ip = plcf->headers_set_len->elts;
@@ -1252,7 +1256,7 @@ ngx_http_proxy_reinit_request(ngx_http_request_t *r)
1252
1256
  ctx->status.count = 0;
1253
1257
  ctx->status.start = NULL;
1254
1258
  ctx->status.end = NULL;
1255
- ctx->state = 0;
1259
+ ctx->chunked.state = 0;
1256
1260
 
1257
1261
  r->upstream->process_header = ngx_http_proxy_process_status_line;
1258
1262
  r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter;
@@ -1470,6 +1474,14 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
1470
1474
  u->keepalive = !u->headers_in.connection_close;
1471
1475
  }
1472
1476
 
1477
+ if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS) {
1478
+ u->keepalive = 0;
1479
+
1480
+ if (r->headers_in.upgrade) {
1481
+ u->upgrade = 1;
1482
+ }
1483
+ }
1484
+
1473
1485
  return NGX_OK;
1474
1486
  }
1475
1487
 
@@ -1618,265 +1630,6 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1618
1630
  }
1619
1631
 
1620
1632
 
1621
- static ngx_inline ngx_int_t
1622
- ngx_http_proxy_parse_chunked(ngx_http_request_t *r, ngx_buf_t *buf)
1623
- {
1624
- u_char *pos, ch, c;
1625
- ngx_int_t rc;
1626
- ngx_http_proxy_ctx_t *ctx;
1627
- enum {
1628
- sw_chunk_start = 0,
1629
- sw_chunk_size,
1630
- sw_chunk_extension,
1631
- sw_chunk_extension_almost_done,
1632
- sw_chunk_data,
1633
- sw_after_data,
1634
- sw_after_data_almost_done,
1635
- sw_last_chunk_extension,
1636
- sw_last_chunk_extension_almost_done,
1637
- sw_trailer,
1638
- sw_trailer_almost_done,
1639
- sw_trailer_header,
1640
- sw_trailer_header_almost_done
1641
- } state;
1642
-
1643
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1644
-
1645
- if (ctx == NULL) {
1646
- return NGX_ERROR;
1647
- }
1648
-
1649
- state = ctx->state;
1650
-
1651
- if (state == sw_chunk_data && ctx->size == 0) {
1652
- state = sw_after_data;
1653
- }
1654
-
1655
- rc = NGX_AGAIN;
1656
-
1657
- for (pos = buf->pos; pos < buf->last; pos++) {
1658
-
1659
- ch = *pos;
1660
-
1661
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1662
- "http proxy chunked byte: %02Xd s:%d", ch, state);
1663
-
1664
- switch (state) {
1665
-
1666
- case sw_chunk_start:
1667
- if (ch >= '0' && ch <= '9') {
1668
- state = sw_chunk_size;
1669
- ctx->size = ch - '0';
1670
- break;
1671
- }
1672
-
1673
- c = (u_char) (ch | 0x20);
1674
-
1675
- if (c >= 'a' && c <= 'f') {
1676
- state = sw_chunk_size;
1677
- ctx->size = c - 'a' + 10;
1678
- break;
1679
- }
1680
-
1681
- goto invalid;
1682
-
1683
- case sw_chunk_size:
1684
- if (ch >= '0' && ch <= '9') {
1685
- ctx->size = ctx->size * 16 + (ch - '0');
1686
- break;
1687
- }
1688
-
1689
- c = (u_char) (ch | 0x20);
1690
-
1691
- if (c >= 'a' && c <= 'f') {
1692
- ctx->size = ctx->size * 16 + (c - 'a' + 10);
1693
- break;
1694
- }
1695
-
1696
- if (ctx->size == 0) {
1697
-
1698
- switch (ch) {
1699
- case CR:
1700
- state = sw_last_chunk_extension_almost_done;
1701
- break;
1702
- case LF:
1703
- state = sw_trailer;
1704
- break;
1705
- case ';':
1706
- case ' ':
1707
- case '\t':
1708
- state = sw_last_chunk_extension;
1709
- break;
1710
- default:
1711
- goto invalid;
1712
- }
1713
-
1714
- break;
1715
- }
1716
-
1717
- switch (ch) {
1718
- case CR:
1719
- state = sw_chunk_extension_almost_done;
1720
- break;
1721
- case LF:
1722
- state = sw_chunk_data;
1723
- break;
1724
- case ';':
1725
- case ' ':
1726
- case '\t':
1727
- state = sw_chunk_extension;
1728
- break;
1729
- default:
1730
- goto invalid;
1731
- }
1732
-
1733
- break;
1734
-
1735
- case sw_chunk_extension:
1736
- switch (ch) {
1737
- case CR:
1738
- state = sw_chunk_extension_almost_done;
1739
- break;
1740
- case LF:
1741
- state = sw_chunk_data;
1742
- }
1743
- break;
1744
-
1745
- case sw_chunk_extension_almost_done:
1746
- if (ch == LF) {
1747
- state = sw_chunk_data;
1748
- break;
1749
- }
1750
- goto invalid;
1751
-
1752
- case sw_chunk_data:
1753
- rc = NGX_OK;
1754
- goto data;
1755
-
1756
- case sw_after_data:
1757
- switch (ch) {
1758
- case CR:
1759
- state = sw_after_data_almost_done;
1760
- break;
1761
- case LF:
1762
- state = sw_chunk_start;
1763
- }
1764
- break;
1765
-
1766
- case sw_after_data_almost_done:
1767
- if (ch == LF) {
1768
- state = sw_chunk_start;
1769
- break;
1770
- }
1771
- goto invalid;
1772
-
1773
- case sw_last_chunk_extension:
1774
- switch (ch) {
1775
- case CR:
1776
- state = sw_last_chunk_extension_almost_done;
1777
- break;
1778
- case LF:
1779
- state = sw_trailer;
1780
- }
1781
- break;
1782
-
1783
- case sw_last_chunk_extension_almost_done:
1784
- if (ch == LF) {
1785
- state = sw_trailer;
1786
- break;
1787
- }
1788
- goto invalid;
1789
-
1790
- case sw_trailer:
1791
- switch (ch) {
1792
- case CR:
1793
- state = sw_trailer_almost_done;
1794
- break;
1795
- case LF:
1796
- goto done;
1797
- default:
1798
- state = sw_trailer_header;
1799
- }
1800
- break;
1801
-
1802
- case sw_trailer_almost_done:
1803
- if (ch == LF) {
1804
- goto done;
1805
- }
1806
- goto invalid;
1807
-
1808
- case sw_trailer_header:
1809
- switch (ch) {
1810
- case CR:
1811
- state = sw_trailer_header_almost_done;
1812
- break;
1813
- case LF:
1814
- state = sw_trailer;
1815
- }
1816
- break;
1817
-
1818
- case sw_trailer_header_almost_done:
1819
- if (ch == LF) {
1820
- state = sw_trailer;
1821
- break;
1822
- }
1823
- goto invalid;
1824
-
1825
- }
1826
- }
1827
-
1828
- data:
1829
-
1830
- ctx->state = state;
1831
- buf->pos = pos;
1832
-
1833
- switch (state) {
1834
-
1835
- case sw_chunk_start:
1836
- ctx->length = 3 /* "0" LF LF */;
1837
- break;
1838
- case sw_chunk_size:
1839
- ctx->length = 2 /* LF LF */
1840
- + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ : 0);
1841
- break;
1842
- case sw_chunk_extension:
1843
- case sw_chunk_extension_almost_done:
1844
- ctx->length = 1 /* LF */ + ctx->size + 4 /* LF "0" LF LF */;
1845
- break;
1846
- case sw_chunk_data:
1847
- ctx->length = ctx->size + 4 /* LF "0" LF LF */;
1848
- break;
1849
- case sw_after_data:
1850
- case sw_after_data_almost_done:
1851
- ctx->length = 4 /* LF "0" LF LF */;
1852
- break;
1853
- case sw_last_chunk_extension:
1854
- case sw_last_chunk_extension_almost_done:
1855
- ctx->length = 2 /* LF LF */;
1856
- break;
1857
- case sw_trailer:
1858
- case sw_trailer_almost_done:
1859
- ctx->length = 1 /* LF */;
1860
- break;
1861
- case sw_trailer_header:
1862
- case sw_trailer_header_almost_done:
1863
- ctx->length = 2 /* LF LF */;
1864
- break;
1865
-
1866
- }
1867
-
1868
- return rc;
1869
-
1870
- done:
1871
-
1872
- return NGX_DONE;
1873
-
1874
- invalid:
1875
-
1876
- return NGX_ERROR;
1877
- }
1878
-
1879
-
1880
1633
  static ngx_int_t
1881
1634
  ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1882
1635
  {
@@ -1902,7 +1655,7 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1902
1655
 
1903
1656
  for ( ;; ) {
1904
1657
 
1905
- rc = ngx_http_proxy_parse_chunked(r, buf);
1658
+ rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
1906
1659
 
1907
1660
  if (rc == NGX_OK) {
1908
1661
 
@@ -1953,16 +1706,16 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1953
1706
  ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
1954
1707
  "input buf #%d %p", b->num, b->pos);
1955
1708
 
1956
- if (buf->last - buf->pos >= ctx->size) {
1709
+ if (buf->last - buf->pos >= ctx->chunked.size) {
1957
1710
 
1958
- buf->pos += ctx->size;
1711
+ buf->pos += ctx->chunked.size;
1959
1712
  b->last = buf->pos;
1960
- ctx->size = 0;
1713
+ ctx->chunked.size = 0;
1961
1714
 
1962
1715
  continue;
1963
1716
  }
1964
1717
 
1965
- ctx->size -= buf->last - buf->pos;
1718
+ ctx->chunked.size -= buf->last - buf->pos;
1966
1719
  buf->pos = buf->last;
1967
1720
  b->last = buf->last;
1968
1721
 
@@ -1983,7 +1736,7 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1983
1736
 
1984
1737
  /* set p->length, minimal amount of data we want to see */
1985
1738
 
1986
- p->length = ctx->length;
1739
+ p->length = ctx->chunked.length;
1987
1740
 
1988
1741
  break;
1989
1742
  }
@@ -1998,7 +1751,7 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1998
1751
 
1999
1752
  ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2000
1753
  "http proxy chunked state %d, length %d",
2001
- ctx->state, p->length);
1754
+ ctx->chunked.state, p->length);
2002
1755
 
2003
1756
  if (b) {
2004
1757
  b->shadow = buf;
@@ -2095,7 +1848,7 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
2095
1848
 
2096
1849
  for ( ;; ) {
2097
1850
 
2098
- rc = ngx_http_proxy_parse_chunked(r, buf);
1851
+ rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
2099
1852
 
2100
1853
  if (rc == NGX_OK) {
2101
1854
 
@@ -2117,13 +1870,13 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
2117
1870
  b->pos = buf->pos;
2118
1871
  b->tag = u->output.tag;
2119
1872
 
2120
- if (buf->last - buf->pos >= ctx->size) {
2121
- buf->pos += ctx->size;
1873
+ if (buf->last - buf->pos >= ctx->chunked.size) {
1874
+ buf->pos += ctx->chunked.size;
2122
1875
  b->last = buf->pos;
2123
- ctx->size = 0;
1876
+ ctx->chunked.size = 0;
2124
1877
 
2125
1878
  } else {
2126
- ctx->size -= buf->last - buf->pos;
1879
+ ctx->chunked.size -= buf->last - buf->pos;
2127
1880
  buf->pos = buf->last;
2128
1881
  b->last = buf->last;
2129
1882
  }
@@ -2261,32 +2014,44 @@ static ngx_int_t
2261
2014
  ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
2262
2015
  ngx_http_variable_value_t *v, uintptr_t data)
2263
2016
  {
2264
- u_char *p;
2017
+ size_t len;
2018
+ u_char *p;
2019
+ ngx_uint_t i, n;
2020
+ ngx_table_elt_t **h;
2265
2021
 
2266
2022
  v->valid = 1;
2267
2023
  v->no_cacheable = 0;
2268
2024
  v->not_found = 0;
2269
2025
 
2270
- if (r->headers_in.x_forwarded_for == NULL) {
2026
+ n = r->headers_in.x_forwarded_for.nelts;
2027
+ h = r->headers_in.x_forwarded_for.elts;
2028
+
2029
+ len = 0;
2030
+
2031
+ for (i = 0; i < n; i++) {
2032
+ len += h[i]->value.len + sizeof(", ") - 1;
2033
+ }
2034
+
2035
+ if (len == 0) {
2271
2036
  v->len = r->connection->addr_text.len;
2272
2037
  v->data = r->connection->addr_text.data;
2273
2038
  return NGX_OK;
2274
2039
  }
2275
2040
 
2276
- v->len = r->headers_in.x_forwarded_for->value.len
2277
- + sizeof(", ") - 1 + r->connection->addr_text.len;
2041
+ len += r->connection->addr_text.len;
2278
2042
 
2279
- p = ngx_pnalloc(r->pool, v->len);
2043
+ p = ngx_pnalloc(r->pool, len);
2280
2044
  if (p == NULL) {
2281
2045
  return NGX_ERROR;
2282
2046
  }
2283
2047
 
2048
+ v->len = len;
2284
2049
  v->data = p;
2285
2050
 
2286
- p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data,
2287
- r->headers_in.x_forwarded_for->value.len);
2288
-
2289
- *p++ = ','; *p++ = ' ';
2051
+ for (i = 0; i < n; i++) {
2052
+ p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
2053
+ *p++ = ','; *p++ = ' ';
2054
+ }
2290
2055
 
2291
2056
  ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
2292
2057
 
@@ -2302,7 +2067,7 @@ ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
2302
2067
 
2303
2068
  ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2304
2069
 
2305
- if (ctx == NULL) {
2070
+ if (ctx == NULL || ctx->internal_body_length < 0) {
2306
2071
  v->not_found = 1;
2307
2072
  return NGX_OK;
2308
2073
  }
@@ -2311,13 +2076,13 @@ ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
2311
2076
  v->no_cacheable = 0;
2312
2077
  v->not_found = 0;
2313
2078
 
2314
- v->data = ngx_pnalloc(r->connection->pool, NGX_SIZE_T_LEN);
2079
+ v->data = ngx_pnalloc(r->connection->pool, NGX_OFF_T_LEN);
2315
2080
 
2316
2081
  if (v->data == NULL) {
2317
2082
  return NGX_ERROR;
2318
2083
  }
2319
2084
 
2320
- v->len = ngx_sprintf(v->data, "%uz", ctx->internal_body_length) - v->data;
2085
+ v->len = ngx_sprintf(v->data, "%O", ctx->internal_body_length) - v->data;
2321
2086
 
2322
2087
  return NGX_OK;
2323
2088
  }
@@ -2624,6 +2389,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
2624
2389
  conf->upstream.buffering = NGX_CONF_UNSET;
2625
2390
  conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
2626
2391
 
2392
+ conf->upstream.local = NGX_CONF_UNSET_PTR;
2393
+
2627
2394
  conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
2628
2395
  conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
2629
2396
  conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
@@ -2708,6 +2475,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2708
2475
  ngx_conf_merge_value(conf->upstream.ignore_client_abort,
2709
2476
  prev->upstream.ignore_client_abort, 0);
2710
2477
 
2478
+ ngx_conf_merge_ptr_value(conf->upstream.local,
2479
+ prev->upstream.local, NULL);
2480
+
2711
2481
  ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
2712
2482
  prev->upstream.connect_timeout, 60000);
2713
2483
 
@@ -3086,8 +2856,6 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
3086
2856
  }
3087
2857
 
3088
2858
  if (conf->headers_set_hash.buckets
3089
- && ((conf->body_source.data == NULL)
3090
- == (prev->body_source.data == NULL))
3091
2859
  #if (NGX_HTTP_CACHE)
3092
2860
  && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))
3093
2861
  #endif
@@ -3170,16 +2938,6 @@ ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
3170
2938
  h++;
3171
2939
  }
3172
2940
 
3173
- if (conf->body_source.data) {
3174
- s = ngx_array_push(&headers_merged);
3175
- if (s == NULL) {
3176
- return NGX_ERROR;
3177
- }
3178
-
3179
- ngx_str_set(&s->key, "Content-Length");
3180
- ngx_str_set(&s->value, "$proxy_internal_body_length");
3181
- }
3182
-
3183
2941
 
3184
2942
  src = headers_merged.elts;
3185
2943
  for (i = 0; i < headers_merged.nelts; i++) {