nginxtra 1.0.15.0 → 1.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/VERSION +1 -1
  2. data/bin/nginxtra +1 -1
  3. data/lib/nginxtra/action.rb +10 -0
  4. data/lib/nginxtra/actions/compile.rb +16 -2
  5. data/lib/nginxtra/actions/start.rb +18 -2
  6. data/lib/nginxtra/actions/status.rb +1 -10
  7. data/lib/nginxtra/actions/stop.rb +18 -0
  8. data/lib/nginxtra/cli.rb +12 -3
  9. data/lib/nginxtra/config.rb +10 -0
  10. data/src/nginx/CHANGES +311 -90
  11. data/src/nginx/CHANGES.ru +315 -88
  12. data/src/nginx/auto/lib/pcre/conf +22 -5
  13. data/src/nginx/auto/lib/pcre/make +1 -1
  14. data/src/nginx/auto/modules +14 -3
  15. data/src/nginx/auto/options +17 -3
  16. data/src/nginx/auto/os/freebsd +8 -0
  17. data/src/nginx/auto/os/linux +5 -4
  18. data/src/nginx/auto/os/solaris +2 -1
  19. data/src/nginx/auto/sources +10 -2
  20. data/src/nginx/auto/summary +2 -0
  21. data/src/nginx/auto/types/sizeof +2 -1
  22. data/src/nginx/auto/types/typedef +1 -1
  23. data/src/nginx/auto/types/uintptr_t +7 -4
  24. data/src/nginx/auto/unix +82 -21
  25. data/src/nginx/conf/fastcgi.conf +1 -0
  26. data/src/nginx/conf/fastcgi_params +1 -0
  27. data/src/nginx/conf/scgi_params +1 -0
  28. data/src/nginx/conf/uwsgi_params +1 -0
  29. data/src/nginx/man/nginx.8 +49 -49
  30. data/src/nginx/src/core/nginx.c +10 -12
  31. data/src/nginx/src/core/nginx.h +2 -2
  32. data/src/nginx/src/core/ngx_buf.c +9 -7
  33. data/src/nginx/src/core/ngx_buf.h +2 -2
  34. data/src/nginx/src/core/ngx_conf_file.c +4 -11
  35. data/src/nginx/src/core/ngx_conf_file.h +1 -1
  36. data/src/nginx/src/core/ngx_connection.c +52 -1
  37. data/src/nginx/src/core/ngx_connection.h +6 -0
  38. data/src/nginx/src/core/ngx_core.h +5 -0
  39. data/src/nginx/src/core/ngx_cycle.c +1 -1
  40. data/src/nginx/src/core/ngx_cycle.h +2 -2
  41. data/src/nginx/src/core/ngx_file.c +1 -1
  42. data/src/nginx/src/core/ngx_inet.c +11 -8
  43. data/src/nginx/src/core/ngx_murmurhash.h +1 -1
  44. data/src/nginx/src/core/ngx_open_file_cache.c +343 -38
  45. data/src/nginx/src/core/ngx_open_file_cache.h +10 -0
  46. data/src/nginx/src/core/ngx_output_chain.c +2 -1
  47. data/src/nginx/src/core/ngx_parse.h +0 -3
  48. data/src/nginx/src/core/ngx_rbtree.c +1 -2
  49. data/src/nginx/src/core/ngx_regex.c +263 -5
  50. data/src/nginx/src/core/ngx_regex.h +6 -2
  51. data/src/nginx/src/core/ngx_resolver.c +88 -21
  52. data/src/nginx/src/core/ngx_resolver.h +7 -8
  53. data/src/nginx/src/core/ngx_shmtx.c +69 -44
  54. data/src/nginx/src/core/ngx_shmtx.h +12 -1
  55. data/src/nginx/src/core/ngx_slab.c +3 -3
  56. data/src/nginx/src/core/ngx_slab.h +1 -1
  57. data/src/nginx/src/core/ngx_string.c +19 -16
  58. data/src/nginx/src/core/ngx_times.c +2 -2
  59. data/src/nginx/src/event/modules/ngx_epoll_module.c +2 -2
  60. data/src/nginx/src/event/modules/ngx_eventport_module.c +1 -1
  61. data/src/nginx/src/event/modules/ngx_kqueue_module.c +1 -1
  62. data/src/nginx/src/event/ngx_event.c +25 -17
  63. data/src/nginx/src/event/ngx_event_openssl.c +3 -1
  64. data/src/nginx/src/event/ngx_event_pipe.c +108 -85
  65. data/src/nginx/src/event/ngx_event_pipe.h +1 -2
  66. data/src/nginx/src/event/ngx_event_timer.c +2 -3
  67. data/src/nginx/src/http/modules/ngx_http_access_module.c +9 -4
  68. data/src/nginx/src/http/modules/ngx_http_browser_module.c +5 -3
  69. data/src/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -1
  70. data/src/nginx/src/http/modules/ngx_http_degradation_module.c +1 -1
  71. data/src/nginx/src/http/modules/ngx_http_fastcgi_module.c +144 -22
  72. data/src/nginx/src/http/modules/ngx_http_flv_module.c +8 -0
  73. data/src/nginx/src/http/modules/ngx_http_geo_module.c +3 -3
  74. data/src/nginx/src/http/modules/ngx_http_gzip_filter_module.c +20 -6
  75. data/src/nginx/src/http/modules/ngx_http_gzip_static_module.c +8 -0
  76. data/src/nginx/src/http/modules/ngx_http_headers_filter_module.c +23 -27
  77. data/src/nginx/src/http/modules/ngx_http_image_filter_module.c +1 -3
  78. data/src/nginx/src/http/modules/ngx_http_index_module.c +24 -0
  79. data/src/nginx/src/http/modules/ngx_http_limit_conn_module.c +747 -0
  80. data/src/nginx/src/http/modules/ngx_http_limit_req_module.c +289 -133
  81. data/src/nginx/src/http/modules/ngx_http_log_module.c +34 -6
  82. data/src/nginx/src/http/modules/ngx_http_memcached_module.c +19 -3
  83. data/src/nginx/src/http/modules/ngx_http_mp4_module.c +8 -0
  84. data/src/nginx/src/http/modules/ngx_http_proxy_module.c +1446 -239
  85. data/src/nginx/src/http/modules/ngx_http_realip_module.c +4 -10
  86. data/src/nginx/src/http/modules/ngx_http_scgi_module.c +90 -21
  87. data/src/nginx/src/http/modules/ngx_http_split_clients_module.c +8 -11
  88. data/src/nginx/src/http/modules/ngx_http_ssi_filter_module.c +16 -6
  89. data/src/nginx/src/http/modules/ngx_http_static_module.c +8 -0
  90. data/src/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +2 -2
  91. data/src/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +570 -0
  92. data/src/nginx/src/http/modules/ngx_http_userid_filter_module.c +1 -5
  93. data/src/nginx/src/http/modules/ngx_http_uwsgi_module.c +77 -26
  94. data/src/nginx/src/http/modules/ngx_http_xslt_filter_module.c +171 -37
  95. data/src/nginx/src/http/modules/perl/nginx.pm +2 -1
  96. data/src/nginx/src/http/modules/perl/nginx.xs +4 -0
  97. data/src/nginx/src/http/ngx_http.c +8 -1
  98. data/src/nginx/src/http/ngx_http.h +1 -0
  99. data/src/nginx/src/http/ngx_http_busy_lock.c +2 -2
  100. data/src/nginx/src/http/ngx_http_cache.h +12 -1
  101. data/src/nginx/src/http/ngx_http_copy_filter_module.c +4 -3
  102. data/src/nginx/src/http/ngx_http_core_module.c +303 -37
  103. data/src/nginx/src/http/ngx_http_core_module.h +15 -0
  104. data/src/nginx/src/http/ngx_http_file_cache.c +226 -52
  105. data/src/nginx/src/http/ngx_http_parse.c +69 -3
  106. data/src/nginx/src/http/ngx_http_postpone_filter_module.c +4 -4
  107. data/src/nginx/src/http/ngx_http_request.c +61 -27
  108. data/src/nginx/src/http/ngx_http_request.h +3 -3
  109. data/src/nginx/src/http/ngx_http_request_body.c +1 -1
  110. data/src/nginx/src/http/ngx_http_script.c +6 -0
  111. data/src/nginx/src/http/ngx_http_upstream.c +200 -47
  112. data/src/nginx/src/http/ngx_http_upstream.h +20 -1
  113. data/src/nginx/src/http/ngx_http_upstream_round_robin.c +22 -6
  114. data/src/nginx/src/http/ngx_http_upstream_round_robin.h +1 -0
  115. data/src/nginx/src/http/ngx_http_variables.c +123 -4
  116. data/src/nginx/src/mail/ngx_mail.c +13 -0
  117. data/src/nginx/src/mail/ngx_mail.h +12 -0
  118. data/src/nginx/src/mail/ngx_mail_core_module.c +100 -15
  119. data/src/nginx/src/os/unix/ngx_daemon.c +2 -1
  120. data/src/nginx/src/os/unix/ngx_darwin.h +3 -0
  121. data/src/nginx/src/os/unix/ngx_darwin_config.h +1 -0
  122. data/src/nginx/src/os/unix/ngx_darwin_init.c +30 -0
  123. data/src/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +11 -5
  124. data/src/nginx/src/os/unix/ngx_errno.h +5 -0
  125. data/src/nginx/src/os/unix/ngx_files.h +50 -1
  126. data/src/nginx/src/os/unix/ngx_freebsd.h +2 -1
  127. data/src/nginx/src/os/unix/ngx_freebsd_config.h +2 -0
  128. data/src/nginx/src/os/unix/ngx_freebsd_init.c +4 -3
  129. data/src/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +2 -2
  130. data/src/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +12 -6
  131. data/src/nginx/src/os/unix/ngx_gcc_atomic_sparc64.h +1 -1
  132. data/src/nginx/src/os/unix/ngx_linux_config.h +1 -0
  133. data/src/nginx/src/os/unix/ngx_linux_sendfile_chain.c +6 -4
  134. data/src/nginx/src/os/unix/ngx_os.h +0 -1
  135. data/src/nginx/src/os/unix/ngx_posix_config.h +3 -0
  136. data/src/nginx/src/os/unix/ngx_process.c +50 -11
  137. data/src/nginx/src/os/unix/ngx_process.h +1 -0
  138. data/src/nginx/src/os/unix/ngx_process_cycle.c +6 -15
  139. data/src/nginx/src/os/unix/ngx_readv_chain.c +8 -0
  140. data/src/nginx/src/os/unix/ngx_setaffinity.c +69 -0
  141. data/src/nginx/src/os/unix/ngx_setaffinity.h +23 -0
  142. data/src/nginx/src/os/unix/ngx_setproctitle.c +1 -1
  143. data/src/nginx/src/os/unix/ngx_solaris_config.h +2 -0
  144. data/src/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +11 -3
  145. data/src/nginx/src/os/unix/ngx_writev_chain.c +7 -3
  146. metadata +7 -4
  147. data/src/nginx/src/http/modules/ngx_http_limit_zone_module.c +0 -553
@@ -111,7 +111,10 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
111
111
  sw_schema,
112
112
  sw_schema_slash,
113
113
  sw_schema_slash_slash,
114
+ sw_host_start,
114
115
  sw_host,
116
+ sw_host_end,
117
+ sw_host_ip_literal,
115
118
  sw_port,
116
119
  sw_host_http_09,
117
120
  sw_after_slash_in_uri,
@@ -324,14 +327,26 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
324
327
  case sw_schema_slash_slash:
325
328
  switch (ch) {
326
329
  case '/':
327
- r->host_start = p + 1;
328
- state = sw_host;
330
+ state = sw_host_start;
329
331
  break;
330
332
  default:
331
333
  return NGX_HTTP_PARSE_INVALID_REQUEST;
332
334
  }
333
335
  break;
334
336
 
337
+ case sw_host_start:
338
+
339
+ r->host_start = p;
340
+
341
+ if (ch == '[') {
342
+ state = sw_host_ip_literal;
343
+ break;
344
+ }
345
+
346
+ state = sw_host;
347
+
348
+ /* fall through */
349
+
335
350
  case sw_host:
336
351
 
337
352
  c = (u_char) (ch | 0x20);
@@ -343,6 +358,10 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
343
358
  break;
344
359
  }
345
360
 
361
+ /* fall through */
362
+
363
+ case sw_host_end:
364
+
346
365
  r->host_end = p;
347
366
 
348
367
  switch (ch) {
@@ -367,6 +386,47 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
367
386
  }
368
387
  break;
369
388
 
389
+ case sw_host_ip_literal:
390
+
391
+ if (ch >= '0' && ch <= '9') {
392
+ break;
393
+ }
394
+
395
+ c = (u_char) (ch | 0x20);
396
+ if (c >= 'a' && c <= 'z') {
397
+ break;
398
+ }
399
+
400
+ switch (ch) {
401
+ case ':':
402
+ break;
403
+ case ']':
404
+ state = sw_host_end;
405
+ break;
406
+ case '-':
407
+ case '.':
408
+ case '_':
409
+ case '~':
410
+ /* unreserved */
411
+ break;
412
+ case '!':
413
+ case '$':
414
+ case '&':
415
+ case '\'':
416
+ case '(':
417
+ case ')':
418
+ case '*':
419
+ case '+':
420
+ case ',':
421
+ case ';':
422
+ case '=':
423
+ /* sub-delims */
424
+ break;
425
+ default:
426
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
427
+ }
428
+ break;
429
+
370
430
  case sw_port:
371
431
  if (ch >= '0' && ch <= '9') {
372
432
  break;
@@ -1037,7 +1097,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
1037
1097
 
1038
1098
  /*
1039
1099
  * we use "ch = *p++" inside the cycle, but this operation is safe,
1040
- * because after the URI there is always at least one charcter:
1100
+ * because after the URI there is always at least one character:
1041
1101
  * the line feed
1042
1102
  */
1043
1103
 
@@ -1093,6 +1153,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
1093
1153
  break;
1094
1154
  case '+':
1095
1155
  r->plus_in_uri = 1;
1156
+ /* fall through */
1096
1157
  default:
1097
1158
  *u++ = ch;
1098
1159
  break;
@@ -1418,6 +1479,7 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b,
1418
1479
  return NGX_ERROR;
1419
1480
  }
1420
1481
 
1482
+ r->http_major = ch - '0';
1421
1483
  state = sw_major_digit;
1422
1484
  break;
1423
1485
 
@@ -1432,6 +1494,7 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b,
1432
1494
  return NGX_ERROR;
1433
1495
  }
1434
1496
 
1497
+ r->http_major = r->http_major * 10 + ch - '0';
1435
1498
  break;
1436
1499
 
1437
1500
  /* the first digit of minor HTTP version */
@@ -1440,6 +1503,7 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b,
1440
1503
  return NGX_ERROR;
1441
1504
  }
1442
1505
 
1506
+ r->http_minor = ch - '0';
1443
1507
  state = sw_minor_digit;
1444
1508
  break;
1445
1509
 
@@ -1454,6 +1518,7 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b,
1454
1518
  return NGX_ERROR;
1455
1519
  }
1456
1520
 
1521
+ r->http_minor = r->http_minor * 10 + ch - '0';
1457
1522
  break;
1458
1523
 
1459
1524
  /* HTTP status code */
@@ -1531,6 +1596,7 @@ done:
1531
1596
  status->end = p;
1532
1597
  }
1533
1598
 
1599
+ status->http_version = r->http_major * 1000 + r->http_minor;
1534
1600
  r->state = sw_start;
1535
1601
 
1536
1602
  return NGX_OK;
@@ -46,7 +46,7 @@ ngx_module_t ngx_http_postpone_filter_module = {
46
46
  };
47
47
 
48
48
 
49
- static ngx_http_output_body_filter_pt ngx_http_next_filter;
49
+ static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
50
50
 
51
51
 
52
52
  static ngx_int_t
@@ -80,7 +80,7 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
80
80
  if (r->postponed == NULL) {
81
81
 
82
82
  if (in || c->buffered) {
83
- return ngx_http_next_filter(r->main, in);
83
+ return ngx_http_next_body_filter(r->main, in);
84
84
  }
85
85
 
86
86
  return NGX_OK;
@@ -116,7 +116,7 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
116
116
  "http postpone filter output \"%V?%V\"",
117
117
  &r->uri, &r->args);
118
118
 
119
- if (ngx_http_next_filter(r->main, pr->out) == NGX_ERROR) {
119
+ if (ngx_http_next_body_filter(r->main, pr->out) == NGX_ERROR) {
120
120
  return NGX_ERROR;
121
121
  }
122
122
  }
@@ -171,7 +171,7 @@ found:
171
171
  static ngx_int_t
172
172
  ngx_http_postpone_filter_init(ngx_conf_t *cf)
173
173
  {
174
- ngx_http_next_filter = ngx_http_top_body_filter;
174
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
175
175
  ngx_http_top_body_filter = ngx_http_postpone_filter;
176
176
 
177
177
  return NGX_OK;
@@ -612,6 +612,8 @@ ngx_http_ssl_handshake_handler(ngx_connection_t *c)
612
612
 
613
613
  c->ssl->no_wait_shutdown = 1;
614
614
 
615
+ c->log->action = "reading client request line";
616
+
615
617
  c->read->handler = ngx_http_process_request_line;
616
618
  /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
617
619
 
@@ -1175,7 +1177,7 @@ ngx_http_read_request_header(ngx_http_request_t *r)
1175
1177
 
1176
1178
  if (n == 0) {
1177
1179
  ngx_log_error(NGX_LOG_INFO, c->log, 0,
1178
- "client closed prematurely connection");
1180
+ "client prematurely closed connection");
1179
1181
  }
1180
1182
 
1181
1183
  if (n == 0 || n == NGX_ERROR) {
@@ -1493,7 +1495,9 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1493
1495
  } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
1494
1496
  r->headers_in.chrome = 1;
1495
1497
 
1496
- } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)) {
1498
+ } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
1499
+ && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
1500
+ {
1497
1501
  r->headers_in.safari = 1;
1498
1502
 
1499
1503
  } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
@@ -1675,56 +1679,85 @@ static ssize_t
1675
1679
  ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len,
1676
1680
  ngx_uint_t alloc)
1677
1681
  {
1678
- u_char *h, ch;
1679
- size_t i, last;
1680
- ngx_uint_t dot;
1682
+ u_char *h, ch;
1683
+ size_t i, dot_pos, host_len;
1684
+
1685
+ enum {
1686
+ sw_usual = 0,
1687
+ sw_literal,
1688
+ sw_rest
1689
+ } state;
1690
+
1691
+ dot_pos = len;
1692
+ host_len = len;
1681
1693
 
1682
- last = len;
1683
1694
  h = *host;
1684
- dot = 0;
1695
+
1696
+ state = sw_usual;
1685
1697
 
1686
1698
  for (i = 0; i < len; i++) {
1687
1699
  ch = h[i];
1688
1700
 
1689
- if (ch == '.') {
1690
- if (dot) {
1701
+ switch (ch) {
1702
+
1703
+ case '.':
1704
+ if (dot_pos == i - 1) {
1691
1705
  return 0;
1692
1706
  }
1707
+ dot_pos = i;
1708
+ break;
1693
1709
 
1694
- dot = 1;
1695
- continue;
1696
- }
1710
+ case ':':
1711
+ if (state == sw_usual) {
1712
+ host_len = i;
1713
+ state = sw_rest;
1714
+ }
1715
+ break;
1697
1716
 
1698
- dot = 0;
1717
+ case '[':
1718
+ if (i == 0) {
1719
+ state = sw_literal;
1720
+ }
1721
+ break;
1699
1722
 
1700
- if (ch == ':') {
1701
- last = i;
1702
- continue;
1703
- }
1723
+ case ']':
1724
+ if (state == sw_literal) {
1725
+ host_len = i + 1;
1726
+ state = sw_rest;
1727
+ }
1728
+ break;
1704
1729
 
1705
- if (ngx_path_separator(ch) || ch == '\0') {
1730
+ case '\0':
1706
1731
  return 0;
1707
- }
1708
1732
 
1709
- if (ch >= 'A' || ch < 'Z') {
1710
- alloc = 1;
1733
+ default:
1734
+
1735
+ if (ngx_path_separator(ch)) {
1736
+ return 0;
1737
+ }
1738
+
1739
+ if (ch >= 'A' && ch <= 'Z') {
1740
+ alloc = 1;
1741
+ }
1742
+
1743
+ break;
1711
1744
  }
1712
1745
  }
1713
1746
 
1714
- if (dot) {
1715
- last--;
1747
+ if (dot_pos == host_len - 1) {
1748
+ host_len--;
1716
1749
  }
1717
1750
 
1718
1751
  if (alloc) {
1719
- *host = ngx_pnalloc(r->pool, last) ;
1752
+ *host = ngx_pnalloc(r->pool, host_len);
1720
1753
  if (*host == NULL) {
1721
1754
  return -1;
1722
1755
  }
1723
1756
 
1724
- ngx_strlow(*host, h, last);
1757
+ ngx_strlow(*host, h, host_len);
1725
1758
  }
1726
1759
 
1727
- return last;
1760
+ return host_len;
1728
1761
  }
1729
1762
 
1730
1763
 
@@ -1981,6 +2014,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1981
2014
  if (r == c->data) {
1982
2015
 
1983
2016
  r->main->count--;
2017
+ r->main->subrequests++;
1984
2018
 
1985
2019
  if (!r->logged) {
1986
2020
 
@@ -2394,7 +2428,7 @@ closed:
2394
2428
  }
2395
2429
 
2396
2430
  ngx_log_error(NGX_LOG_INFO, c->log, err,
2397
- "client closed prematurely connection");
2431
+ "client prematurely closed connection");
2398
2432
 
2399
2433
  ngx_http_finalize_request(r, 0);
2400
2434
  }
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
  #define NGX_HTTP_MAX_URI_CHANGES 10
13
- #define NGX_HTTP_MAX_SUBREQUESTS 50
13
+ #define NGX_HTTP_MAX_SUBREQUESTS 200
14
14
 
15
15
  /* must be 2^n */
16
16
  #define NGX_HTTP_LC_HEADER_LEN 32
@@ -479,10 +479,10 @@ struct ngx_http_request_s {
479
479
 
480
480
  /*
481
481
  * instead of using the request context data in
482
- * ngx_http_limit_zone_module and ngx_http_limit_req_module
482
+ * ngx_http_limit_conn_module and ngx_http_limit_req_module
483
483
  * we use the single bits in the request structure
484
484
  */
485
- unsigned limit_zone_set:1;
485
+ unsigned limit_conn_set:1;
486
486
  unsigned limit_req_set:1;
487
487
 
488
488
  #if 0
@@ -303,7 +303,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
303
303
 
304
304
  if (n == 0) {
305
305
  ngx_log_error(NGX_LOG_INFO, c->log, 0,
306
- "client closed prematurely connection");
306
+ "client prematurely closed connection");
307
307
  }
308
308
 
309
309
  if (n == 0 || n == NGX_ERROR) {
@@ -1506,6 +1506,12 @@ ngx_http_script_file_code(ngx_http_script_engine_t *e)
1506
1506
  of.errors = clcf->open_file_cache_errors;
1507
1507
  of.events = clcf->open_file_cache_events;
1508
1508
 
1509
+ if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
1510
+ e->ip = ngx_http_script_exit;
1511
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
1512
+ return;
1513
+ }
1514
+
1509
1515
  if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1510
1516
  != NGX_OK)
1511
1517
  {
@@ -73,6 +73,8 @@ static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
73
73
 
74
74
  static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
75
75
  ngx_table_elt_t *h, ngx_uint_t offset);
76
+ static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
77
+ ngx_table_elt_t *h, ngx_uint_t offset);
76
78
  static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
77
79
  ngx_table_elt_t *h, ngx_uint_t offset);
78
80
  static ngx_int_t
@@ -90,6 +92,11 @@ static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
90
92
  ngx_table_elt_t *h, ngx_uint_t offset);
91
93
  static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r,
92
94
  ngx_table_elt_t *h, ngx_uint_t offset);
95
+ static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
96
+ ngx_table_elt_t *h, ngx_uint_t offset);
97
+ static ngx_int_t
98
+ ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
99
+ ngx_table_elt_t *h, ngx_uint_t offset);
93
100
  static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
94
101
  ngx_table_elt_t *h, ngx_uint_t offset);
95
102
  static ngx_int_t
@@ -97,14 +104,14 @@ static ngx_int_t
97
104
  ngx_table_elt_t *h, ngx_uint_t offset);
98
105
  static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
99
106
  ngx_table_elt_t *h, ngx_uint_t offset);
100
- static ngx_int_t ngx_http_upstream_copy_content_length(ngx_http_request_t *r,
101
- ngx_table_elt_t *h, ngx_uint_t offset);
102
107
  static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
103
108
  ngx_table_elt_t *h, ngx_uint_t offset);
104
109
  static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
105
110
  ngx_table_elt_t *h, ngx_uint_t offset);
106
111
  static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
107
112
  ngx_table_elt_t *h, ngx_uint_t offset);
113
+ static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
114
+ ngx_table_elt_t *h, ngx_uint_t offset);
108
115
  static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
109
116
  ngx_table_elt_t *h, ngx_uint_t offset);
110
117
 
@@ -150,9 +157,9 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
150
157
  ngx_http_upstream_copy_content_type, 0, 1 },
151
158
 
152
159
  { ngx_string("Content-Length"),
153
- ngx_http_upstream_process_header_line,
160
+ ngx_http_upstream_process_content_length,
154
161
  offsetof(ngx_http_upstream_headers_in_t, content_length),
155
- ngx_http_upstream_copy_content_length, 0, 0 },
162
+ ngx_http_upstream_ignore_header_line, 0, 0 },
156
163
 
157
164
  { ngx_string("Date"),
158
165
  ngx_http_upstream_process_header_line,
@@ -193,7 +200,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
193
200
 
194
201
  { ngx_string("Set-Cookie"),
195
202
  ngx_http_upstream_process_set_cookie, 0,
196
- ngx_http_upstream_copy_header_line, 0, 1 },
203
+ ngx_http_upstream_rewrite_set_cookie, 0, 1 },
197
204
 
198
205
  { ngx_string("Content-Disposition"),
199
206
  ngx_http_upstream_ignore_header_line, 0,
@@ -216,7 +223,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
216
223
  offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
217
224
 
218
225
  { ngx_string("Connection"),
219
- ngx_http_upstream_ignore_header_line, 0,
226
+ ngx_http_upstream_process_connection, 0,
220
227
  ngx_http_upstream_ignore_header_line, 0, 0 },
221
228
 
222
229
  { ngx_string("Keep-Alive"),
@@ -248,6 +255,10 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
248
255
  ngx_http_upstream_process_charset, 0,
249
256
  ngx_http_upstream_copy_header_line, 0, 0 },
250
257
 
258
+ { ngx_string("Transfer-Encoding"),
259
+ ngx_http_upstream_process_transfer_encoding, 0,
260
+ ngx_http_upstream_ignore_header_line, 0, 0 },
261
+
251
262
  #if (NGX_HTTP_GZIP)
252
263
  { ngx_string("Content-Encoding"),
253
264
  ngx_http_upstream_process_header_line,
@@ -400,6 +411,8 @@ ngx_http_upstream_create(ngx_http_request_t *r)
400
411
  r->cache = NULL;
401
412
  #endif
402
413
 
414
+ u->headers_in.content_length_n = -1;
415
+
403
416
  return NGX_OK;
404
417
  }
405
418
 
@@ -697,6 +710,9 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
697
710
  c->body_start = u->conf->buffer_size;
698
711
  c->file_cache = u->conf->cache->data;
699
712
 
713
+ c->lock = u->conf->cache_lock;
714
+ c->lock_timeout = u->conf->cache_lock_timeout;
715
+
700
716
  u->cache_status = NGX_HTTP_CACHE_MISS;
701
717
  }
702
718
 
@@ -804,6 +820,7 @@ ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
804
820
  u->buffer.pos += c->header_start;
805
821
 
806
822
  ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
823
+ u->headers_in.content_length_n = -1;
807
824
 
808
825
  if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
809
826
  sizeof(ngx_table_elt_t))
@@ -1140,8 +1157,20 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
1140
1157
  c->sendfile &= r->connection->sendfile;
1141
1158
  u->output.sendfile = c->sendfile;
1142
1159
 
1143
- c->pool = r->pool;
1160
+ if (c->pool == NULL) {
1161
+
1162
+ /* we need separate pool here to be able to cache SSL connections */
1163
+
1164
+ c->pool = ngx_create_pool(128, r->connection->log);
1165
+ if (c->pool == NULL) {
1166
+ ngx_http_upstream_finalize_request(r, u,
1167
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
1168
+ return;
1169
+ }
1170
+ }
1171
+
1144
1172
  c->log = r->connection->log;
1173
+ c->pool->log = c->log;
1145
1174
  c->read->log = c->log;
1146
1175
  c->write->log = c->log;
1147
1176
 
@@ -1167,7 +1196,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
1167
1196
  {
1168
1197
  /*
1169
1198
  * the r->request_body->buf can be reused for one request only,
1170
- * the subrequests should allocate their own temporay bufs
1199
+ * the subrequests should allocate their own temporary bufs
1171
1200
  */
1172
1201
 
1173
1202
  u->output.free = ngx_alloc_chain_link(r->pool);
@@ -1286,7 +1315,10 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
1286
1315
  return NGX_ERROR;
1287
1316
  }
1288
1317
 
1318
+ u->keepalive = 0;
1319
+
1289
1320
  ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
1321
+ u->headers_in.content_length_n = -1;
1290
1322
 
1291
1323
  if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
1292
1324
  sizeof(ngx_table_elt_t))
@@ -1869,8 +1901,6 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
1869
1901
  r->method = NGX_HTTP_GET;
1870
1902
  }
1871
1903
 
1872
- r->valid_unparsed_uri = 0;
1873
-
1874
1904
  ngx_http_internal_redirect(r, uri, &args);
1875
1905
  ngx_http_finalize_request(r, NGX_DONE);
1876
1906
  return NGX_DONE;
@@ -1928,14 +1958,9 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
1928
1958
  r->headers_out.status = u->headers_in.status_n;
1929
1959
  r->headers_out.status_line = u->headers_in.status_line;
1930
1960
 
1931
- u->headers_in.content_length_n = r->headers_out.content_length_n;
1961
+ r->headers_out.content_length_n = u->headers_in.content_length_n;
1932
1962
 
1933
- if (r->headers_out.content_length_n != -1) {
1934
- u->length = (size_t) r->headers_out.content_length_n;
1935
-
1936
- } else {
1937
- u->length = NGX_MAX_SIZE_T_VALUE;
1938
- }
1963
+ u->length = u->headers_in.content_length_n;
1939
1964
 
1940
1965
  return NGX_OK;
1941
1966
  }
@@ -1999,6 +2024,11 @@ ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
1999
2024
  }
2000
2025
  }
2001
2026
 
2027
+ if (u->length == 0) {
2028
+ ngx_http_upstream_finalize_request(r, u, 0);
2029
+ return;
2030
+ }
2031
+
2002
2032
  if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2003
2033
  ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2004
2034
  return;
@@ -2119,7 +2149,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2119
2149
  return;
2120
2150
  }
2121
2151
 
2122
- if (u->peer.connection->read->ready) {
2152
+ if (u->peer.connection->read->ready || u->length == 0) {
2123
2153
  ngx_http_upstream_process_non_buffered_upstream(r, u);
2124
2154
  }
2125
2155
  }
@@ -2295,6 +2325,15 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2295
2325
  p->send_timeout = clcf->send_timeout;
2296
2326
  p->send_lowat = clcf->send_lowat;
2297
2327
 
2328
+ p->length = -1;
2329
+
2330
+ if (u->input_filter_init
2331
+ && u->input_filter_init(p->input_ctx) != NGX_OK)
2332
+ {
2333
+ ngx_http_upstream_finalize_request(r, u, 0);
2334
+ return;
2335
+ }
2336
+
2298
2337
  u->read_event_handler = ngx_http_upstream_process_upstream;
2299
2338
  r->write_event_handler = ngx_http_upstream_process_downstream;
2300
2339
 
@@ -2384,7 +2423,7 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
2384
2423
  return;
2385
2424
  }
2386
2425
 
2387
- ngx_chain_update_chains(&u->free_bufs, &u->busy_bufs,
2426
+ ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs,
2388
2427
  &u->out_bufs, u->output.tag);
2389
2428
  }
2390
2429
 
@@ -2405,10 +2444,6 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
2405
2444
 
2406
2445
  size = b->end - b->last;
2407
2446
 
2408
- if (size > u->length) {
2409
- size = u->length;
2410
- }
2411
-
2412
2447
  if (size && upstream->read->ready) {
2413
2448
 
2414
2449
  n = upstream->recv(upstream, b->last, size);
@@ -2505,7 +2540,7 @@ ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
2505
2540
  cl->buf->last = b->last;
2506
2541
  cl->buf->tag = u->output.tag;
2507
2542
 
2508
- if (u->length == NGX_MAX_SIZE_T_VALUE) {
2543
+ if (u->length == -1) {
2509
2544
  return NGX_OK;
2510
2545
  }
2511
2546
 
@@ -2650,9 +2685,17 @@ ngx_http_upstream_process_request(ngx_http_request_t *r)
2650
2685
 
2651
2686
  } else if (p->upstream_eof) {
2652
2687
 
2653
- /* TODO: check length & update cache */
2688
+ tf = u->pipe->temp_file;
2654
2689
 
2655
- ngx_http_file_cache_update(r, u->pipe->temp_file);
2690
+ if (u->headers_in.content_length_n == -1
2691
+ || u->headers_in.content_length_n
2692
+ == tf->offset - (off_t) r->cache->body_start)
2693
+ {
2694
+ ngx_http_file_cache_update(r, tf);
2695
+
2696
+ } else {
2697
+ ngx_http_file_cache_free(r->cache, tf);
2698
+ }
2656
2699
 
2657
2700
  } else if (p->upstream_error) {
2658
2701
  ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
@@ -2799,6 +2842,10 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
2799
2842
  if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
2800
2843
  status = 0;
2801
2844
 
2845
+ /* TODO: inform balancer instead */
2846
+
2847
+ u->peer.tries++;
2848
+
2802
2849
  } else {
2803
2850
  switch(ft_type) {
2804
2851
 
@@ -2873,6 +2920,10 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
2873
2920
  }
2874
2921
  #endif
2875
2922
 
2923
+ if (u->peer.connection->pool) {
2924
+ ngx_destroy_pool(u->peer.connection->pool);
2925
+ }
2926
+
2876
2927
  ngx_close_connection(u->peer.connection);
2877
2928
  u->peer.connection = NULL;
2878
2929
  }
@@ -2968,6 +3019,10 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
2968
3019
  "close http upstream connection: %d",
2969
3020
  u->peer.connection->fd);
2970
3021
 
3022
+ if (u->peer.connection->pool) {
3023
+ ngx_destroy_pool(u->peer.connection->pool);
3024
+ }
3025
+
2971
3026
  ngx_close_connection(u->peer.connection);
2972
3027
  }
2973
3028
 
@@ -3064,6 +3119,21 @@ ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3064
3119
  }
3065
3120
 
3066
3121
 
3122
+ static ngx_int_t
3123
+ ngx_http_upstream_process_content_length(ngx_http_request_t *r,
3124
+ ngx_table_elt_t *h, ngx_uint_t offset)
3125
+ {
3126
+ ngx_http_upstream_t *u;
3127
+
3128
+ u = r->upstream;
3129
+
3130
+ u->headers_in.content_length = h;
3131
+ u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len);
3132
+
3133
+ return NGX_OK;
3134
+ }
3135
+
3136
+
3067
3137
  static ngx_int_t
3068
3138
  ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
3069
3139
  ngx_uint_t offset)
@@ -3242,6 +3312,8 @@ ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
3242
3312
  switch (n) {
3243
3313
  case 0:
3244
3314
  u->cacheable = 0;
3315
+ /* fall through */
3316
+
3245
3317
  case NGX_ERROR:
3246
3318
  return NGX_OK;
3247
3319
 
@@ -3342,6 +3414,40 @@ ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
3342
3414
  }
3343
3415
 
3344
3416
 
3417
+ static ngx_int_t
3418
+ ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
3419
+ ngx_uint_t offset)
3420
+ {
3421
+ r->upstream->headers_in.connection = h;
3422
+
3423
+ if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
3424
+ (u_char *) "close", 5 - 1)
3425
+ != NULL)
3426
+ {
3427
+ r->upstream->headers_in.connection_close = 1;
3428
+ }
3429
+
3430
+ return NGX_OK;
3431
+ }
3432
+
3433
+
3434
+ static ngx_int_t
3435
+ ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
3436
+ ngx_table_elt_t *h, ngx_uint_t offset)
3437
+ {
3438
+ r->upstream->headers_in.transfer_encoding = h;
3439
+
3440
+ if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
3441
+ (u_char *) "chunked", 7 - 1)
3442
+ != NULL)
3443
+ {
3444
+ r->upstream->headers_in.chunked = 1;
3445
+ }
3446
+
3447
+ return NGX_OK;
3448
+ }
3449
+
3450
+
3345
3451
  static ngx_int_t
3346
3452
  ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3347
3453
  ngx_uint_t offset)
@@ -3449,26 +3555,6 @@ ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h,
3449
3555
  }
3450
3556
 
3451
3557
 
3452
- static ngx_int_t
3453
- ngx_http_upstream_copy_content_length(ngx_http_request_t *r, ngx_table_elt_t *h,
3454
- ngx_uint_t offset)
3455
- {
3456
- ngx_table_elt_t *ho;
3457
-
3458
- ho = ngx_list_push(&r->headers_out.headers);
3459
- if (ho == NULL) {
3460
- return NGX_ERROR;
3461
- }
3462
-
3463
- *ho = *h;
3464
-
3465
- r->headers_out.content_length = ho;
3466
- r->headers_out.content_length_n = ngx_atoof(h->value.data, h->value.len);
3467
-
3468
- return NGX_OK;
3469
- }
3470
-
3471
-
3472
3558
  static ngx_int_t
3473
3559
  ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
3474
3560
  ngx_uint_t offset)
@@ -3587,6 +3673,27 @@ ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
3587
3673
  }
3588
3674
 
3589
3675
 
3676
+ static ngx_int_t
3677
+ ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
3678
+ ngx_uint_t offset)
3679
+ {
3680
+ ngx_table_elt_t *ho;
3681
+
3682
+ ho = ngx_list_push(&r->headers_out.headers);
3683
+ if (ho == NULL) {
3684
+ return NGX_ERROR;
3685
+ }
3686
+
3687
+ *ho = *h;
3688
+
3689
+ if (r->upstream->rewrite_cookie) {
3690
+ return r->upstream->rewrite_cookie(r, ho);
3691
+ }
3692
+
3693
+ return NGX_OK;
3694
+ }
3695
+
3696
+
3590
3697
  static ngx_int_t
3591
3698
  ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
3592
3699
  ngx_table_elt_t *h, ngx_uint_t offset)
@@ -4163,7 +4270,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4163
4270
 
4164
4271
  fail_timeout = ngx_parse_time(&s, 1);
4165
4272
 
4166
- if (fail_timeout == NGX_ERROR) {
4273
+ if (fail_timeout == (time_t) NGX_ERROR) {
4167
4274
  goto invalid;
4168
4275
  }
4169
4276
 
@@ -4355,12 +4462,58 @@ ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
4355
4462
  case NGX_DECLINED:
4356
4463
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4357
4464
  "invalid address \"%V\"", &value[1]);
4465
+ /* fall through */
4466
+
4358
4467
  default:
4359
4468
  return NGX_CONF_ERROR;
4360
4469
  }
4361
4470
  }
4362
4471
 
4363
4472
 
4473
+ char *
4474
+ ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
4475
+ void *conf)
4476
+ {
4477
+ char *p = conf;
4478
+
4479
+ ngx_str_t *value;
4480
+ ngx_array_t **a;
4481
+ ngx_http_upstream_param_t *param;
4482
+
4483
+ a = (ngx_array_t **) (p + cmd->offset);
4484
+
4485
+ if (*a == NULL) {
4486
+ *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t));
4487
+ if (*a == NULL) {
4488
+ return NGX_CONF_ERROR;
4489
+ }
4490
+ }
4491
+
4492
+ param = ngx_array_push(*a);
4493
+ if (param == NULL) {
4494
+ return NGX_CONF_ERROR;
4495
+ }
4496
+
4497
+ value = cf->args->elts;
4498
+
4499
+ param->key = value[1];
4500
+ param->value = value[2];
4501
+ param->skip_empty = 0;
4502
+
4503
+ if (cf->args->nelts == 4) {
4504
+ if (ngx_strcmp(value[3].data, "if_not_empty") != 0) {
4505
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4506
+ "invalid parameter \"%V\"", &value[3]);
4507
+ return NGX_CONF_ERROR;
4508
+ }
4509
+
4510
+ param->skip_empty = 1;
4511
+ }
4512
+
4513
+ return NGX_CONF_OK;
4514
+ }
4515
+
4516
+
4364
4517
  ngx_int_t
4365
4518
  ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
4366
4519
  ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,