nginxtra 1.6.3.9 → 1.8.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nginxtra +1 -1
  3. data/bin/nginxtra_rails +1 -1
  4. data/lib/nginxtra/version.rb +1 -1
  5. data/vendor/nginx/CHANGES +358 -14
  6. data/vendor/nginx/CHANGES.ru +372 -18
  7. data/vendor/nginx/LICENSE +2 -2
  8. data/vendor/nginx/auto/cc/clang +5 -0
  9. data/vendor/nginx/auto/cc/gcc +5 -0
  10. data/vendor/nginx/auto/lib/google-perftools/conf +1 -1
  11. data/vendor/nginx/auto/lib/openssl/make +0 -5
  12. data/vendor/nginx/auto/lib/perl/conf +9 -1
  13. data/vendor/nginx/auto/make +1 -1
  14. data/vendor/nginx/auto/modules +11 -0
  15. data/vendor/nginx/auto/options +10 -2
  16. data/vendor/nginx/auto/os/darwin +0 -1
  17. data/vendor/nginx/auto/os/freebsd +6 -23
  18. data/vendor/nginx/auto/sources +16 -14
  19. data/vendor/nginx/auto/summary +3 -24
  20. data/vendor/nginx/auto/threads +20 -0
  21. data/vendor/nginx/auto/types/sizeof +2 -12
  22. data/vendor/nginx/auto/unix +50 -6
  23. data/vendor/nginx/configure +5 -0
  24. data/vendor/nginx/contrib/vim/syntax/nginx.vim +183 -50
  25. data/vendor/nginx/src/core/nginx.c +21 -9
  26. data/vendor/nginx/src/core/nginx.h +8 -2
  27. data/vendor/nginx/src/core/ngx_buf.c +88 -0
  28. data/vendor/nginx/src/core/ngx_buf.h +15 -1
  29. data/vendor/nginx/src/core/ngx_conf_file.c +4 -1
  30. data/vendor/nginx/src/core/ngx_connection.c +25 -66
  31. data/vendor/nginx/src/core/ngx_connection.h +1 -3
  32. data/vendor/nginx/src/core/ngx_core.h +11 -3
  33. data/vendor/nginx/src/core/ngx_crypt.c +1 -1
  34. data/vendor/nginx/src/core/ngx_cycle.c +7 -1
  35. data/vendor/nginx/src/core/ngx_cycle.h +6 -2
  36. data/vendor/nginx/src/core/ngx_file.c +13 -5
  37. data/vendor/nginx/src/core/ngx_file.h +6 -0
  38. data/vendor/nginx/src/core/ngx_log.c +215 -21
  39. data/vendor/nginx/src/core/ngx_log.h +9 -1
  40. data/vendor/nginx/src/core/ngx_output_chain.c +104 -15
  41. data/vendor/nginx/src/core/ngx_palloc.c +3 -7
  42. data/vendor/nginx/src/core/ngx_rbtree.c +2 -4
  43. data/vendor/nginx/src/core/ngx_rbtree.h +2 -4
  44. data/vendor/nginx/src/core/ngx_regex.c +14 -6
  45. data/vendor/nginx/src/core/ngx_resolver.c +16 -23
  46. data/vendor/nginx/src/core/ngx_resolver.h +8 -7
  47. data/vendor/nginx/src/core/ngx_shmtx.c +1 -1
  48. data/vendor/nginx/src/core/ngx_slab.c +89 -2
  49. data/vendor/nginx/src/core/ngx_slab.h +3 -0
  50. data/vendor/nginx/src/core/ngx_string.c +58 -2
  51. data/vendor/nginx/src/core/ngx_string.h +1 -0
  52. data/vendor/nginx/src/core/ngx_syslog.c +374 -0
  53. data/vendor/nginx/src/core/ngx_syslog.h +30 -0
  54. data/vendor/nginx/src/core/ngx_thread_pool.c +630 -0
  55. data/vendor/nginx/src/core/ngx_thread_pool.h +36 -0
  56. data/vendor/nginx/src/core/ngx_times.c +19 -2
  57. data/vendor/nginx/src/core/ngx_times.h +1 -0
  58. data/vendor/nginx/src/event/modules/ngx_aio_module.c +1 -1
  59. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +9 -24
  60. data/vendor/nginx/src/event/modules/ngx_epoll_module.c +152 -28
  61. data/vendor/nginx/src/event/modules/ngx_eventport_module.c +43 -25
  62. data/vendor/nginx/src/event/modules/ngx_kqueue_module.c +86 -156
  63. data/vendor/nginx/src/event/modules/ngx_poll_module.c +21 -37
  64. data/vendor/nginx/src/event/modules/ngx_rtsig_module.c +15 -27
  65. data/vendor/nginx/src/event/modules/ngx_select_module.c +10 -12
  66. data/vendor/nginx/src/event/modules/ngx_win32_select_module.c +7 -9
  67. data/vendor/nginx/src/event/ngx_event.c +5 -33
  68. data/vendor/nginx/src/event/ngx_event.h +15 -50
  69. data/vendor/nginx/src/event/ngx_event_accept.c +11 -10
  70. data/vendor/nginx/src/event/ngx_event_connect.c +0 -11
  71. data/vendor/nginx/src/event/ngx_event_connect.h +1 -4
  72. data/vendor/nginx/src/event/ngx_event_openssl.c +622 -38
  73. data/vendor/nginx/src/event/ngx_event_openssl.h +20 -2
  74. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +5 -1
  75. data/vendor/nginx/src/event/ngx_event_pipe.c +45 -19
  76. data/vendor/nginx/src/event/ngx_event_pipe.h +3 -0
  77. data/vendor/nginx/src/event/ngx_event_posted.c +7 -145
  78. data/vendor/nginx/src/event/ngx_event_posted.h +12 -39
  79. data/vendor/nginx/src/event/ngx_event_timer.c +50 -70
  80. data/vendor/nginx/src/event/ngx_event_timer.h +2 -14
  81. data/vendor/nginx/src/http/modules/ngx_http_addition_filter_module.c +1 -1
  82. data/vendor/nginx/src/http/modules/ngx_http_autoindex_module.c +416 -71
  83. data/vendor/nginx/src/http/modules/ngx_http_charset_filter_module.c +19 -15
  84. data/vendor/nginx/src/http/modules/ngx_http_dav_module.c +16 -4
  85. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +601 -134
  86. data/vendor/nginx/src/http/modules/ngx_http_geo_module.c +1 -1
  87. data/vendor/nginx/src/http/modules/ngx_http_geoip_module.c +9 -3
  88. data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +9 -3
  89. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +9 -3
  90. data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +0 -2
  91. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +197 -91
  92. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +1 -0
  93. data/vendor/nginx/src/http/modules/ngx_http_limit_conn_module.c +65 -162
  94. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +53 -67
  95. data/vendor/nginx/src/http/modules/ngx_http_log_module.c +128 -23
  96. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +25 -6
  97. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +1 -1
  98. data/vendor/nginx/src/http/modules/ngx_http_not_modified_filter_module.c +39 -13
  99. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +697 -141
  100. data/vendor/nginx/src/http/modules/ngx_http_rewrite_module.c +5 -1
  101. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +282 -125
  102. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +4 -1
  103. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +44 -1
  104. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +2 -0
  105. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +10 -8
  106. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +18 -3
  107. data/vendor/nginx/src/http/modules/ngx_http_upstream_hash_module.c +641 -0
  108. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +1 -1
  109. data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +3 -21
  110. data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +0 -5
  111. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +449 -125
  112. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +4 -2
  113. data/vendor/nginx/src/http/modules/perl/ngx_http_perl_module.c +2 -1
  114. data/vendor/nginx/src/http/ngx_http.c +10 -5
  115. data/vendor/nginx/src/http/ngx_http.h +4 -4
  116. data/vendor/nginx/src/http/ngx_http_cache.h +26 -1
  117. data/vendor/nginx/src/http/ngx_http_copy_filter_module.c +109 -68
  118. data/vendor/nginx/src/http/ngx_http_core_module.c +191 -46
  119. data/vendor/nginx/src/http/ngx_http_core_module.h +16 -4
  120. data/vendor/nginx/src/http/ngx_http_file_cache.c +584 -67
  121. data/vendor/nginx/src/http/ngx_http_parse.c +55 -4
  122. data/vendor/nginx/src/http/ngx_http_request.c +14 -6
  123. data/vendor/nginx/src/http/ngx_http_request.h +12 -4
  124. data/vendor/nginx/src/http/ngx_http_request_body.c +114 -28
  125. data/vendor/nginx/src/http/ngx_http_spdy.c +383 -229
  126. data/vendor/nginx/src/http/ngx_http_spdy.h +8 -5
  127. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +12 -4
  128. data/vendor/nginx/src/http/ngx_http_special_response.c +2 -2
  129. data/vendor/nginx/src/http/ngx_http_upstream.c +808 -132
  130. data/vendor/nginx/src/http/ngx_http_upstream.h +33 -3
  131. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +72 -65
  132. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.h +1 -2
  133. data/vendor/nginx/src/http/ngx_http_variables.c +47 -3
  134. data/vendor/nginx/src/http/ngx_http_write_filter_module.c +15 -6
  135. data/vendor/nginx/src/mail/ngx_mail.c +2 -3
  136. data/vendor/nginx/src/mail/ngx_mail.h +2 -0
  137. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +140 -11
  138. data/vendor/nginx/src/mail/ngx_mail_core_module.c +3 -3
  139. data/vendor/nginx/src/mail/ngx_mail_handler.c +79 -2
  140. data/vendor/nginx/src/mail/ngx_mail_imap_module.c +3 -1
  141. data/vendor/nginx/src/mail/ngx_mail_pop3_module.c +3 -1
  142. data/vendor/nginx/src/mail/ngx_mail_smtp_module.c +3 -1
  143. data/vendor/nginx/src/mail/ngx_mail_ssl_module.c +125 -1
  144. data/vendor/nginx/src/mail/ngx_mail_ssl_module.h +8 -0
  145. data/vendor/nginx/src/misc/ngx_cpp_test_module.cpp +1 -1
  146. data/vendor/nginx/src/os/unix/ngx_aio_read_chain.c +1 -1
  147. data/vendor/nginx/src/os/unix/ngx_channel.c +0 -7
  148. data/vendor/nginx/src/os/unix/ngx_darwin_config.h +0 -3
  149. data/vendor/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +44 -208
  150. data/vendor/nginx/src/os/unix/ngx_file_aio_read.c +25 -17
  151. data/vendor/nginx/src/os/unix/ngx_files.c +109 -0
  152. data/vendor/nginx/src/os/unix/ngx_files.h +6 -0
  153. data/vendor/nginx/src/os/unix/ngx_freebsd_config.h +0 -6
  154. data/vendor/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +78 -206
  155. data/vendor/nginx/src/os/unix/ngx_linux_aio_read.c +25 -14
  156. data/vendor/nginx/src/os/unix/ngx_linux_config.h +4 -1
  157. data/vendor/nginx/src/os/unix/ngx_linux_sendfile_chain.c +235 -194
  158. data/vendor/nginx/src/os/unix/ngx_os.h +25 -3
  159. data/vendor/nginx/src/os/unix/ngx_posix_init.c +4 -2
  160. data/vendor/nginx/src/os/unix/ngx_process_cycle.c +13 -195
  161. data/vendor/nginx/src/os/unix/ngx_process_cycle.h +0 -1
  162. data/vendor/nginx/src/os/unix/ngx_readv_chain.c +27 -108
  163. data/vendor/nginx/src/os/unix/ngx_setproctitle.h +2 -2
  164. data/vendor/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +12 -67
  165. data/vendor/nginx/src/os/unix/ngx_thread.h +26 -83
  166. data/vendor/nginx/src/os/unix/ngx_thread_cond.c +87 -0
  167. data/vendor/nginx/src/os/unix/ngx_thread_id.c +70 -0
  168. data/vendor/nginx/src/os/unix/ngx_thread_mutex.c +174 -0
  169. data/vendor/nginx/src/os/unix/ngx_user.c +2 -20
  170. data/vendor/nginx/src/os/unix/ngx_writev_chain.c +129 -98
  171. metadata +16 -17
  172. data/vendor/nginx/auto/lib/zlib/patch.zlib.h +0 -10
  173. data/vendor/nginx/src/event/ngx_event_busy_lock.c +0 -286
  174. data/vendor/nginx/src/event/ngx_event_busy_lock.h +0 -65
  175. data/vendor/nginx/src/event/ngx_event_mutex.c +0 -70
  176. data/vendor/nginx/src/http/ngx_http_busy_lock.c +0 -307
  177. data/vendor/nginx/src/http/ngx_http_busy_lock.h +0 -54
  178. data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +0 -756
  179. data/vendor/nginx/src/os/unix/ngx_freebsd_rfork_thread.h +0 -122
  180. data/vendor/nginx/src/os/unix/ngx_pthread_thread.c +0 -278
  181. data/vendor/nginx/src/os/unix/rfork_thread.S +0 -73
@@ -230,13 +230,16 @@ ngx_int_t ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc);
230
230
  #else
231
231
 
232
232
  #define ngx_spdy_frame_write_uint16(p, s) \
233
- ((p)[0] = (u_char) (s) >> 8, (p)[1] = (u_char) (s), (p) + sizeof(uint16_t))
233
+ ((p)[0] = (u_char) ((s) >> 8), \
234
+ (p)[1] = (u_char) (s), \
235
+ (p) + sizeof(uint16_t))
234
236
 
235
237
  #define ngx_spdy_frame_write_uint32(p, s) \
236
- ((p)[0] = (u_char) (s) >> 24, \
237
- (p)[1] = (u_char) (s) >> 16, \
238
- (p)[2] = (u_char) (s) >> 8, \
239
- (p)[3] = (u_char) (s), (p) + sizeof(uint32_t))
238
+ ((p)[0] = (u_char) ((s) >> 24), \
239
+ (p)[1] = (u_char) ((s) >> 16), \
240
+ (p)[2] = (u_char) ((s) >> 8), \
241
+ (p)[3] = (u_char) (s), \
242
+ (p) + sizeof(uint32_t))
240
243
 
241
244
  #endif
242
245
 
@@ -493,9 +493,13 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
493
493
  continue;
494
494
  }
495
495
 
496
- *last++ = '\0';
496
+ if (h[j].value.len) {
497
+ if (last != p) {
498
+ *last++ = '\0';
499
+ }
497
500
 
498
- last = ngx_cpymem(last, h[j].value.data, h[j].value.len);
501
+ last = ngx_cpymem(last, h[j].value.data, h[j].value.len);
502
+ }
499
503
 
500
504
  h[j].hash = 2;
501
505
  }
@@ -533,8 +537,7 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r)
533
537
  ngx_free(buf);
534
538
 
535
539
  if (rc != Z_OK) {
536
- ngx_log_error(NGX_LOG_ALERT, c->log, 0,
537
- "spdy deflate() failed: %d", rc);
540
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0, "deflate() failed: %d", rc);
538
541
  return NGX_ERROR;
539
542
  }
540
543
 
@@ -1142,6 +1145,11 @@ ngx_http_spdy_handle_stream(ngx_http_spdy_connection_t *sc,
1142
1145
 
1143
1146
  wev = stream->request->connection->write;
1144
1147
 
1148
+ /*
1149
+ * This timer can only be set if the stream was delayed because of rate
1150
+ * limit. In that case the event should be triggered by the timer.
1151
+ */
1152
+
1145
1153
  if (!wev->timer_set) {
1146
1154
  wev->delayed = 0;
1147
1155
 
@@ -553,7 +553,7 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
553
553
  return NGX_ERROR;
554
554
  }
555
555
 
556
- if (uri.data[0] == '/') {
556
+ if (uri.len && uri.data[0] == '/') {
557
557
 
558
558
  if (err_page->value.lengths) {
559
559
  ngx_http_split_args(r, &uri, &args);
@@ -570,7 +570,7 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
570
570
  return ngx_http_internal_redirect(r, &uri, &args);
571
571
  }
572
572
 
573
- if (uri.data[0] == '@') {
573
+ if (uri.len && uri.data[0] == '@') {
574
574
  return ngx_http_named_location(r, &uri);
575
575
  }
576
576
 
@@ -13,12 +13,16 @@
13
13
  #if (NGX_HTTP_CACHE)
14
14
  static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
15
15
  ngx_http_upstream_t *u);
16
+ static ngx_int_t ngx_http_upstream_cache_get(ngx_http_request_t *r,
17
+ ngx_http_upstream_t *u, ngx_http_file_cache_t **cache);
16
18
  static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
17
19
  ngx_http_upstream_t *u);
18
20
  static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
19
21
  ngx_http_variable_value_t *v, uintptr_t data);
20
22
  static ngx_int_t ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
21
23
  ngx_http_variable_value_t *v, uintptr_t data);
24
+ static ngx_int_t ngx_http_upstream_cache_etag(ngx_http_request_t *r,
25
+ ngx_http_variable_value_t *v, uintptr_t data);
22
26
  #endif
23
27
 
24
28
  static void ngx_http_upstream_init_request(ngx_http_request_t *r);
@@ -32,9 +36,12 @@ static void ngx_http_upstream_connect(ngx_http_request_t *r,
32
36
  static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
33
37
  ngx_http_upstream_t *u);
34
38
  static void ngx_http_upstream_send_request(ngx_http_request_t *r,
35
- ngx_http_upstream_t *u);
39
+ ngx_http_upstream_t *u, ngx_uint_t do_write);
40
+ static ngx_int_t ngx_http_upstream_send_request_body(ngx_http_request_t *r,
41
+ ngx_http_upstream_t *u, ngx_uint_t do_write);
36
42
  static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
37
43
  ngx_http_upstream_t *u);
44
+ static void ngx_http_upstream_read_request_handler(ngx_http_request_t *r);
38
45
  static void ngx_http_upstream_process_header(ngx_http_request_t *r,
39
46
  ngx_http_upstream_t *u);
40
47
  static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
@@ -72,7 +79,8 @@ static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
72
79
  static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
73
80
  static void ngx_http_upstream_process_upstream(ngx_http_request_t *r,
74
81
  ngx_http_upstream_t *u);
75
- static void ngx_http_upstream_process_request(ngx_http_request_t *r);
82
+ static void ngx_http_upstream_process_request(ngx_http_request_t *r,
83
+ ngx_http_upstream_t *u);
76
84
  static void ngx_http_upstream_store(ngx_http_request_t *r,
77
85
  ngx_http_upstream_t *u);
78
86
  static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
@@ -87,6 +95,8 @@ static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
87
95
  ngx_table_elt_t *h, ngx_uint_t offset);
88
96
  static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
89
97
  ngx_table_elt_t *h, ngx_uint_t offset);
98
+ static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
99
+ ngx_table_elt_t *h, ngx_uint_t offset);
90
100
  static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
91
101
  ngx_table_elt_t *h, ngx_uint_t offset);
92
102
  static ngx_int_t
@@ -109,6 +119,8 @@ static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
109
119
  static ngx_int_t
110
120
  ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
111
121
  ngx_table_elt_t *h, ngx_uint_t offset);
122
+ static ngx_int_t ngx_http_upstream_process_vary(ngx_http_request_t *r,
123
+ ngx_table_elt_t *h, ngx_uint_t offset);
112
124
  static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
113
125
  ngx_table_elt_t *h, ngx_uint_t offset);
114
126
  static ngx_int_t
@@ -156,6 +168,8 @@ static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
156
168
  static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
157
169
  ngx_http_upstream_t *u, ngx_connection_t *c);
158
170
  static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
171
+ static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r,
172
+ ngx_http_upstream_t *u, ngx_connection_t *c);
159
173
  #endif
160
174
 
161
175
 
@@ -172,8 +186,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
172
186
  ngx_http_upstream_copy_content_type, 0, 1 },
173
187
 
174
188
  { ngx_string("Content-Length"),
175
- ngx_http_upstream_process_content_length,
176
- offsetof(ngx_http_upstream_headers_in_t, content_length),
189
+ ngx_http_upstream_process_content_length, 0,
177
190
  ngx_http_upstream_ignore_header_line, 0, 0 },
178
191
 
179
192
  { ngx_string("Date"),
@@ -183,8 +196,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
183
196
  offsetof(ngx_http_headers_out_t, date), 0 },
184
197
 
185
198
  { ngx_string("Last-Modified"),
186
- ngx_http_upstream_process_header_line,
187
- offsetof(ngx_http_upstream_headers_in_t, last_modified),
199
+ ngx_http_upstream_process_last_modified, 0,
188
200
  ngx_http_upstream_copy_last_modified, 0, 0 },
189
201
 
190
202
  { ngx_string("ETag"),
@@ -214,7 +226,8 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
214
226
  ngx_http_upstream_rewrite_refresh, 0, 0 },
215
227
 
216
228
  { ngx_string("Set-Cookie"),
217
- ngx_http_upstream_process_set_cookie, 0,
229
+ ngx_http_upstream_process_set_cookie,
230
+ offsetof(ngx_http_upstream_headers_in_t, cookies),
218
231
  ngx_http_upstream_rewrite_set_cookie, 0, 1 },
219
232
 
220
233
  { ngx_string("Content-Disposition"),
@@ -245,6 +258,10 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
245
258
  ngx_http_upstream_ignore_header_line, 0,
246
259
  ngx_http_upstream_ignore_header_line, 0, 0 },
247
260
 
261
+ { ngx_string("Vary"),
262
+ ngx_http_upstream_process_vary, 0,
263
+ ngx_http_upstream_copy_header_line, 0, 0 },
264
+
248
265
  { ngx_string("X-Powered-By"),
249
266
  ngx_http_upstream_ignore_header_line, 0,
250
267
  ngx_http_upstream_copy_header_line, 0, 0 },
@@ -346,6 +363,10 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = {
346
363
  ngx_http_upstream_status_variable, 0,
347
364
  NGX_HTTP_VAR_NOCACHEABLE, 0 },
348
365
 
366
+ { ngx_string("upstream_header_time"), NULL,
367
+ ngx_http_upstream_response_time_variable, 1,
368
+ NGX_HTTP_VAR_NOCACHEABLE, 0 },
369
+
349
370
  { ngx_string("upstream_response_time"), NULL,
350
371
  ngx_http_upstream_response_time_variable, 0,
351
372
  NGX_HTTP_VAR_NOCACHEABLE, 0 },
@@ -364,6 +385,10 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = {
364
385
  ngx_http_upstream_cache_last_modified, 0,
365
386
  NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
366
387
 
388
+ { ngx_string("upstream_cache_etag"), NULL,
389
+ ngx_http_upstream_cache_etag, 0,
390
+ NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
391
+
367
392
  #endif
368
393
 
369
394
  { ngx_null_string, NULL, NULL, 0, 0, 0 }
@@ -398,6 +423,7 @@ ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks[] = {
398
423
  { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
399
424
  { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
400
425
  { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
426
+ { ngx_string("Vary"), NGX_HTTP_UPSTREAM_IGN_VARY },
401
427
  { ngx_null_string, 0 }
402
428
  };
403
429
 
@@ -423,15 +449,13 @@ ngx_http_upstream_create(ngx_http_request_t *r)
423
449
 
424
450
  u->peer.log = r->connection->log;
425
451
  u->peer.log_error = NGX_ERROR_ERR;
426
- #if (NGX_THREADS)
427
- u->peer.lock = &r->connection->lock;
428
- #endif
429
452
 
430
453
  #if (NGX_HTTP_CACHE)
431
454
  r->cache = NULL;
432
455
  #endif
433
456
 
434
457
  u->headers_in.content_length_n = -1;
458
+ u->headers_in.last_modified_time = -1;
435
459
 
436
460
  return NGX_OK;
437
461
  }
@@ -510,6 +534,11 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
510
534
  return;
511
535
  }
512
536
 
537
+ if (rc == NGX_ERROR) {
538
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
539
+ return;
540
+ }
541
+
513
542
  if (rc != NGX_DECLINED) {
514
543
  ngx_http_finalize_request(r, rc);
515
544
  return;
@@ -518,7 +547,7 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
518
547
 
519
548
  #endif
520
549
 
521
- u->store = (u->conf->store || u->conf->store_lengths);
550
+ u->store = u->conf->store;
522
551
 
523
552
  if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
524
553
  r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
@@ -542,8 +571,11 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
542
571
  u->output.pool = r->pool;
543
572
  u->output.bufs.num = 1;
544
573
  u->output.bufs.size = clcf->client_body_buffer_size;
545
- u->output.output_filter = ngx_chain_writer;
546
- u->output.filter_ctx = &u->writer;
574
+
575
+ if (u->output.output_filter == NULL) {
576
+ u->output.output_filter = ngx_chain_writer;
577
+ u->output.filter_ctx = &u->writer;
578
+ }
547
579
 
548
580
  u->writer.pool = r->pool;
549
581
 
@@ -584,6 +616,10 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
584
616
 
585
617
  } else {
586
618
 
619
+ #if (NGX_HTTP_SSL)
620
+ u->ssl_name = u->resolved->host;
621
+ #endif
622
+
587
623
  if (u->resolved->sockaddr) {
588
624
 
589
625
  if (ngx_http_upstream_create_round_robin_peer(r, u->resolved)
@@ -670,12 +706,24 @@ found:
670
706
  return;
671
707
  }
672
708
 
709
+ #if (NGX_HTTP_SSL)
710
+ u->ssl_name = uscf->host;
711
+ #endif
712
+
673
713
  if (uscf->peer.init(r, uscf) != NGX_OK) {
674
714
  ngx_http_upstream_finalize_request(r, u,
675
715
  NGX_HTTP_INTERNAL_SERVER_ERROR);
676
716
  return;
677
717
  }
678
718
 
719
+ u->peer.start_time = ngx_current_msec;
720
+
721
+ if (u->conf->next_upstream_tries
722
+ && u->peer.tries > u->conf->next_upstream_tries)
723
+ {
724
+ u->peer.tries = u->conf->next_upstream_tries;
725
+ }
726
+
679
727
  ngx_http_upstream_connect(r, u);
680
728
  }
681
729
 
@@ -685,8 +733,9 @@ found:
685
733
  static ngx_int_t
686
734
  ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
687
735
  {
688
- ngx_int_t rc;
689
- ngx_http_cache_t *c;
736
+ ngx_int_t rc;
737
+ ngx_http_cache_t *c;
738
+ ngx_http_file_cache_t *cache;
690
739
 
691
740
  c = r->cache;
692
741
 
@@ -696,6 +745,12 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
696
745
  return NGX_DECLINED;
697
746
  }
698
747
 
748
+ rc = ngx_http_upstream_cache_get(r, u, &cache);
749
+
750
+ if (rc != NGX_OK) {
751
+ return rc;
752
+ }
753
+
699
754
  if (r->method & NGX_HTTP_HEAD) {
700
755
  u->method = ngx_http_core_get_method;
701
756
  }
@@ -725,6 +780,12 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
725
780
 
726
781
  u->cacheable = 1;
727
782
 
783
+ c = r->cache;
784
+
785
+ c->body_start = u->conf->buffer_size;
786
+ c->min_uses = u->conf->cache_min_uses;
787
+ c->file_cache = cache;
788
+
728
789
  switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
729
790
 
730
791
  case NGX_ERROR:
@@ -738,14 +799,9 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
738
799
  break;
739
800
  }
740
801
 
741
- c = r->cache;
742
-
743
- c->min_uses = u->conf->cache_min_uses;
744
- c->body_start = u->conf->buffer_size;
745
- c->file_cache = u->conf->cache->data;
746
-
747
802
  c->lock = u->conf->cache_lock;
748
803
  c->lock_timeout = u->conf->cache_lock_timeout;
804
+ c->lock_age = u->conf->cache_lock_age;
749
805
 
750
806
  u->cache_status = NGX_HTTP_CACHE_MISS;
751
807
  }
@@ -834,6 +890,49 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
834
890
  }
835
891
 
836
892
 
893
+ static ngx_int_t
894
+ ngx_http_upstream_cache_get(ngx_http_request_t *r, ngx_http_upstream_t *u,
895
+ ngx_http_file_cache_t **cache)
896
+ {
897
+ ngx_str_t *name, val;
898
+ ngx_uint_t i;
899
+ ngx_http_file_cache_t **caches;
900
+
901
+ if (u->conf->cache_zone) {
902
+ *cache = u->conf->cache_zone->data;
903
+ return NGX_OK;
904
+ }
905
+
906
+ if (ngx_http_complex_value(r, u->conf->cache_value, &val) != NGX_OK) {
907
+ return NGX_ERROR;
908
+ }
909
+
910
+ if (val.len == 0
911
+ || (val.len == 3 && ngx_strncmp(val.data, "off", 3) == 0))
912
+ {
913
+ return NGX_DECLINED;
914
+ }
915
+
916
+ caches = u->caches->elts;
917
+
918
+ for (i = 0; i < u->caches->nelts; i++) {
919
+ name = &caches[i]->shm_zone->shm.name;
920
+
921
+ if (name->len == val.len
922
+ && ngx_strncmp(name->data, val.data, val.len) == 0)
923
+ {
924
+ *cache = caches[i];
925
+ return NGX_OK;
926
+ }
927
+ }
928
+
929
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
930
+ "cache \"%V\" not found", &val);
931
+
932
+ return NGX_ERROR;
933
+ }
934
+
935
+
837
936
  static ngx_int_t
838
937
  ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
839
938
  {
@@ -855,6 +954,7 @@ ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
855
954
 
856
955
  ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
857
956
  u->headers_in.content_length_n = -1;
957
+ u->headers_in.last_modified_time = -1;
858
958
 
859
959
  if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
860
960
  sizeof(ngx_table_elt_t))
@@ -902,6 +1002,11 @@ ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
902
1002
  u = r->upstream;
903
1003
  ur = u->resolved;
904
1004
 
1005
+ ngx_http_set_log_request(c->log, r);
1006
+
1007
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1008
+ "http upstream resolve: \"%V?%V\"", &r->uri, &r->args);
1009
+
905
1010
  if (ctx->state) {
906
1011
  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
907
1012
  "%V could not be resolved (%i: %s)",
@@ -942,6 +1047,14 @@ ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
942
1047
  ngx_resolve_name_done(ctx);
943
1048
  ur->ctx = NULL;
944
1049
 
1050
+ u->peer.start_time = ngx_current_msec;
1051
+
1052
+ if (u->conf->next_upstream_tries
1053
+ && u->peer.tries > u->conf->next_upstream_tries)
1054
+ {
1055
+ u->peer.tries = u->conf->next_upstream_tries;
1056
+ }
1057
+
945
1058
  ngx_http_upstream_connect(r, u);
946
1059
 
947
1060
  failed:
@@ -955,7 +1068,6 @@ ngx_http_upstream_handler(ngx_event_t *ev)
955
1068
  {
956
1069
  ngx_connection_t *c;
957
1070
  ngx_http_request_t *r;
958
- ngx_http_log_ctx_t *ctx;
959
1071
  ngx_http_upstream_t *u;
960
1072
 
961
1073
  c = ev->data;
@@ -964,8 +1076,7 @@ ngx_http_upstream_handler(ngx_event_t *ev)
964
1076
  u = r->upstream;
965
1077
  c = r->connection;
966
1078
 
967
- ctx = c->log->data;
968
- ctx->current_request = r;
1079
+ ngx_http_set_log_request(c->log, r);
969
1080
 
970
1081
  ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
971
1082
  "http upstream request: \"%V?%V\"", &r->uri, &r->args);
@@ -1212,6 +1323,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
1212
1323
  tp = ngx_timeofday();
1213
1324
  u->state->response_sec = tp->sec;
1214
1325
  u->state->response_msec = tp->msec;
1326
+ u->state->header_sec = (time_t) NGX_ERROR;
1215
1327
 
1216
1328
  rc = ngx_event_connect_peer(&u->peer);
1217
1329
 
@@ -1326,7 +1438,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
1326
1438
 
1327
1439
  #endif
1328
1440
 
1329
- ngx_http_upstream_send_request(r, u);
1441
+ ngx_http_upstream_send_request(r, u, 1);
1330
1442
  }
1331
1443
 
1332
1444
 
@@ -1336,7 +1448,9 @@ static void
1336
1448
  ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
1337
1449
  ngx_http_upstream_t *u, ngx_connection_t *c)
1338
1450
  {
1339
- ngx_int_t rc;
1451
+ int tcp_nodelay;
1452
+ ngx_int_t rc;
1453
+ ngx_http_core_loc_conf_t *clcf;
1340
1454
 
1341
1455
  if (ngx_http_upstream_test_connect(c) != NGX_OK) {
1342
1456
  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
@@ -1355,12 +1469,42 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
1355
1469
  c->sendfile = 0;
1356
1470
  u->output.sendfile = 0;
1357
1471
 
1472
+ if (u->conf->ssl_server_name || u->conf->ssl_verify) {
1473
+ if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK) {
1474
+ ngx_http_upstream_finalize_request(r, u,
1475
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
1476
+ return;
1477
+ }
1478
+ }
1479
+
1358
1480
  if (u->conf->ssl_session_reuse) {
1359
1481
  if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
1360
1482
  ngx_http_upstream_finalize_request(r, u,
1361
1483
  NGX_HTTP_INTERNAL_SERVER_ERROR);
1362
1484
  return;
1363
1485
  }
1486
+
1487
+ /* abbreviated SSL handshake may interact badly with Nagle */
1488
+
1489
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1490
+
1491
+ if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
1492
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
1493
+
1494
+ tcp_nodelay = 1;
1495
+
1496
+ if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
1497
+ (const void *) &tcp_nodelay, sizeof(int)) == -1)
1498
+ {
1499
+ ngx_connection_error(c, ngx_socket_errno,
1500
+ "setsockopt(TCP_NODELAY) failed");
1501
+ ngx_http_upstream_finalize_request(r, u,
1502
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
1503
+ return;
1504
+ }
1505
+
1506
+ c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1507
+ }
1364
1508
  }
1365
1509
 
1366
1510
  r->connection->log->action = "SSL handshaking to upstream";
@@ -1368,6 +1512,11 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
1368
1512
  rc = ngx_ssl_handshake(c);
1369
1513
 
1370
1514
  if (rc == NGX_AGAIN) {
1515
+
1516
+ if (!c->write->timer_set) {
1517
+ ngx_add_timer(c->write, u->conf->connect_timeout);
1518
+ }
1519
+
1371
1520
  c->ssl->handler = ngx_http_upstream_ssl_handshake;
1372
1521
  return;
1373
1522
  }
@@ -1379,14 +1528,35 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
1379
1528
  static void
1380
1529
  ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
1381
1530
  {
1531
+ long rc;
1382
1532
  ngx_http_request_t *r;
1383
1533
  ngx_http_upstream_t *u;
1384
1534
 
1385
1535
  r = c->data;
1386
1536
  u = r->upstream;
1387
1537
 
1538
+ ngx_http_set_log_request(c->log, r);
1539
+
1388
1540
  if (c->ssl->handshaked) {
1389
1541
 
1542
+ if (u->conf->ssl_verify) {
1543
+ rc = SSL_get_verify_result(c->ssl->connection);
1544
+
1545
+ if (rc != X509_V_OK) {
1546
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
1547
+ "upstream SSL certificate verify error: (%l:%s)",
1548
+ rc, X509_verify_cert_error_string(rc));
1549
+ goto failed;
1550
+ }
1551
+
1552
+ if (ngx_ssl_check_host(c, &u->ssl_name) != NGX_OK) {
1553
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
1554
+ "upstream SSL certificate does not match \"%V\"",
1555
+ &u->ssl_name);
1556
+ goto failed;
1557
+ }
1558
+ }
1559
+
1390
1560
  if (u->conf->ssl_session_reuse) {
1391
1561
  u->peer.save_session(&u->peer, u->peer.data);
1392
1562
  }
@@ -1396,12 +1566,14 @@ ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
1396
1566
 
1397
1567
  c = r->connection;
1398
1568
 
1399
- ngx_http_upstream_send_request(r, u);
1569
+ ngx_http_upstream_send_request(r, u, 1);
1400
1570
 
1401
1571
  ngx_http_run_posted_requests(c);
1402
1572
  return;
1403
1573
  }
1404
1574
 
1575
+ failed:
1576
+
1405
1577
  c = r->connection;
1406
1578
 
1407
1579
  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
@@ -1409,12 +1581,104 @@ ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
1409
1581
  ngx_http_run_posted_requests(c);
1410
1582
  }
1411
1583
 
1584
+
1585
+ static ngx_int_t
1586
+ ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u,
1587
+ ngx_connection_t *c)
1588
+ {
1589
+ u_char *p, *last;
1590
+ ngx_str_t name;
1591
+
1592
+ if (u->conf->ssl_name) {
1593
+ if (ngx_http_complex_value(r, u->conf->ssl_name, &name) != NGX_OK) {
1594
+ return NGX_ERROR;
1595
+ }
1596
+
1597
+ } else {
1598
+ name = u->ssl_name;
1599
+ }
1600
+
1601
+ if (name.len == 0) {
1602
+ goto done;
1603
+ }
1604
+
1605
+ /*
1606
+ * ssl name here may contain port, notably if derived from $proxy_host
1607
+ * or $http_host; we have to strip it
1608
+ */
1609
+
1610
+ p = name.data;
1611
+ last = name.data + name.len;
1612
+
1613
+ if (*p == '[') {
1614
+ p = ngx_strlchr(p, last, ']');
1615
+
1616
+ if (p == NULL) {
1617
+ p = name.data;
1618
+ }
1619
+ }
1620
+
1621
+ p = ngx_strlchr(p, last, ':');
1622
+
1623
+ if (p != NULL) {
1624
+ name.len = p - name.data;
1625
+ }
1626
+
1627
+ if (!u->conf->ssl_server_name) {
1628
+ goto done;
1629
+ }
1630
+
1631
+ #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1632
+
1633
+ /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */
1634
+
1635
+ if (name.len == 0 || *name.data == '[') {
1636
+ goto done;
1637
+ }
1638
+
1639
+ if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) {
1640
+ goto done;
1641
+ }
1642
+
1643
+ /*
1644
+ * SSL_set_tlsext_host_name() needs a null-terminated string,
1645
+ * hence we explicitly null-terminate name here
1646
+ */
1647
+
1648
+ p = ngx_pnalloc(r->pool, name.len + 1);
1649
+ if (p == NULL) {
1650
+ return NGX_ERROR;
1651
+ }
1652
+
1653
+ (void) ngx_cpystrn(p, name.data, name.len + 1);
1654
+
1655
+ name.data = p;
1656
+
1657
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1658
+ "upstream SSL server name: \"%s\"", name.data);
1659
+
1660
+ if (SSL_set_tlsext_host_name(c->ssl->connection, name.data) == 0) {
1661
+ ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0,
1662
+ "SSL_set_tlsext_host_name(\"%s\") failed", name.data);
1663
+ return NGX_ERROR;
1664
+ }
1665
+
1666
+ #endif
1667
+
1668
+ done:
1669
+
1670
+ u->ssl_name = name;
1671
+
1672
+ return NGX_OK;
1673
+ }
1674
+
1412
1675
  #endif
1413
1676
 
1414
1677
 
1415
1678
  static ngx_int_t
1416
1679
  ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
1417
1680
  {
1681
+ off_t file_pos;
1418
1682
  ngx_chain_t *cl;
1419
1683
 
1420
1684
  if (u->reinit_request(r) != NGX_OK) {
@@ -1426,6 +1690,7 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
1426
1690
 
1427
1691
  ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
1428
1692
  u->headers_in.content_length_n = -1;
1693
+ u->headers_in.last_modified_time = -1;
1429
1694
 
1430
1695
  if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
1431
1696
  sizeof(ngx_table_elt_t))
@@ -1436,9 +1701,17 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
1436
1701
 
1437
1702
  /* reinit the request chain */
1438
1703
 
1704
+ file_pos = 0;
1705
+
1439
1706
  for (cl = u->request_bufs; cl; cl = cl->next) {
1440
1707
  cl->buf->pos = cl->buf->start;
1441
- cl->buf->file_pos = 0;
1708
+
1709
+ /* there is at most one file */
1710
+
1711
+ if (cl->buf->in_file) {
1712
+ cl->buf->file_pos = file_pos;
1713
+ file_pos = cl->buf->file_last;
1714
+ }
1442
1715
  }
1443
1716
 
1444
1717
  /* reinit the subrequest's ngx_output_chain() context */
@@ -1481,7 +1754,8 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
1481
1754
 
1482
1755
 
1483
1756
  static void
1484
- ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
1757
+ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u,
1758
+ ngx_uint_t do_write)
1485
1759
  {
1486
1760
  ngx_int_t rc;
1487
1761
  ngx_connection_t *c;
@@ -1498,21 +1772,25 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
1498
1772
 
1499
1773
  c->log->action = "sending request to upstream";
1500
1774
 
1501
- rc = ngx_output_chain(&u->output, u->request_sent ? NULL : u->request_bufs);
1502
-
1503
- u->request_sent = 1;
1775
+ rc = ngx_http_upstream_send_request_body(r, u, do_write);
1504
1776
 
1505
1777
  if (rc == NGX_ERROR) {
1506
1778
  ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1507
1779
  return;
1508
1780
  }
1509
1781
 
1510
- if (c->write->timer_set) {
1511
- ngx_del_timer(c->write);
1782
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
1783
+ ngx_http_upstream_finalize_request(r, u, rc);
1784
+ return;
1512
1785
  }
1513
1786
 
1514
1787
  if (rc == NGX_AGAIN) {
1515
- ngx_add_timer(c->write, u->conf->send_timeout);
1788
+ if (!c->write->ready) {
1789
+ ngx_add_timer(c->write, u->conf->send_timeout);
1790
+
1791
+ } else if (c->write->timer_set) {
1792
+ ngx_del_timer(c->write);
1793
+ }
1516
1794
 
1517
1795
  if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) {
1518
1796
  ngx_http_upstream_finalize_request(r, u,
@@ -1525,6 +1803,10 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
1525
1803
 
1526
1804
  /* rc == NGX_OK */
1527
1805
 
1806
+ if (c->write->timer_set) {
1807
+ ngx_del_timer(c->write);
1808
+ }
1809
+
1528
1810
  if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
1529
1811
  if (ngx_tcp_push(c->fd) == NGX_ERROR) {
1530
1812
  ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
@@ -1537,20 +1819,137 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
1537
1819
  c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
1538
1820
  }
1539
1821
 
1822
+ u->write_event_handler = ngx_http_upstream_dummy_handler;
1823
+
1824
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1825
+ ngx_http_upstream_finalize_request(r, u,
1826
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
1827
+ return;
1828
+ }
1829
+
1540
1830
  ngx_add_timer(c->read, u->conf->read_timeout);
1541
1831
 
1542
1832
  if (c->read->ready) {
1543
1833
  ngx_http_upstream_process_header(r, u);
1544
1834
  return;
1545
1835
  }
1836
+ }
1546
1837
 
1547
- u->write_event_handler = ngx_http_upstream_dummy_handler;
1548
1838
 
1549
- if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
1550
- ngx_http_upstream_finalize_request(r, u,
1551
- NGX_HTTP_INTERNAL_SERVER_ERROR);
1552
- return;
1839
+ static ngx_int_t
1840
+ ngx_http_upstream_send_request_body(ngx_http_request_t *r,
1841
+ ngx_http_upstream_t *u, ngx_uint_t do_write)
1842
+ {
1843
+ int tcp_nodelay;
1844
+ ngx_int_t rc;
1845
+ ngx_chain_t *out, *cl, *ln;
1846
+ ngx_connection_t *c;
1847
+ ngx_http_core_loc_conf_t *clcf;
1848
+
1849
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1850
+ "http upstream send request body");
1851
+
1852
+ if (!r->request_body_no_buffering) {
1853
+
1854
+ /* buffered request body */
1855
+
1856
+ if (!u->request_sent) {
1857
+ u->request_sent = 1;
1858
+ out = u->request_bufs;
1859
+
1860
+ } else {
1861
+ out = NULL;
1862
+ }
1863
+
1864
+ return ngx_output_chain(&u->output, out);
1553
1865
  }
1866
+
1867
+ if (!u->request_sent) {
1868
+ u->request_sent = 1;
1869
+ out = u->request_bufs;
1870
+
1871
+ if (r->request_body->bufs) {
1872
+ for (cl = out; cl->next; cl = out->next) { /* void */ }
1873
+ cl->next = r->request_body->bufs;
1874
+ r->request_body->bufs = NULL;
1875
+ }
1876
+
1877
+ c = u->peer.connection;
1878
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1879
+
1880
+ if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
1881
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
1882
+
1883
+ tcp_nodelay = 1;
1884
+
1885
+ if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
1886
+ (const void *) &tcp_nodelay, sizeof(int)) == -1)
1887
+ {
1888
+ ngx_connection_error(c, ngx_socket_errno,
1889
+ "setsockopt(TCP_NODELAY) failed");
1890
+ return NGX_ERROR;
1891
+ }
1892
+
1893
+ c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1894
+ }
1895
+
1896
+ r->read_event_handler = ngx_http_upstream_read_request_handler;
1897
+
1898
+ } else {
1899
+ out = NULL;
1900
+ }
1901
+
1902
+ for ( ;; ) {
1903
+
1904
+ if (do_write) {
1905
+ rc = ngx_output_chain(&u->output, out);
1906
+
1907
+ if (rc == NGX_ERROR) {
1908
+ return NGX_ERROR;
1909
+ }
1910
+
1911
+ while (out) {
1912
+ ln = out;
1913
+ out = out->next;
1914
+ ngx_free_chain(r->pool, ln);
1915
+ }
1916
+
1917
+ if (rc == NGX_OK && !r->reading_body) {
1918
+ break;
1919
+ }
1920
+ }
1921
+
1922
+ if (r->reading_body) {
1923
+ /* read client request body */
1924
+
1925
+ rc = ngx_http_read_unbuffered_request_body(r);
1926
+
1927
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
1928
+ return rc;
1929
+ }
1930
+
1931
+ out = r->request_body->bufs;
1932
+ r->request_body->bufs = NULL;
1933
+ }
1934
+
1935
+ /* stop if there is nothing to send */
1936
+
1937
+ if (out == NULL) {
1938
+ rc = NGX_AGAIN;
1939
+ break;
1940
+ }
1941
+
1942
+ do_write = 1;
1943
+ }
1944
+
1945
+ if (!r->reading_body) {
1946
+ if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
1947
+ r->read_event_handler =
1948
+ ngx_http_upstream_rd_check_broken_connection;
1949
+ }
1950
+ }
1951
+
1952
+ return rc;
1554
1953
  }
1555
1954
 
1556
1955
 
@@ -1587,7 +1986,29 @@ ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
1587
1986
  return;
1588
1987
  }
1589
1988
 
1590
- ngx_http_upstream_send_request(r, u);
1989
+ ngx_http_upstream_send_request(r, u, 1);
1990
+ }
1991
+
1992
+
1993
+ static void
1994
+ ngx_http_upstream_read_request_handler(ngx_http_request_t *r)
1995
+ {
1996
+ ngx_connection_t *c;
1997
+ ngx_http_upstream_t *u;
1998
+
1999
+ c = r->connection;
2000
+ u = r->upstream;
2001
+
2002
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2003
+ "http upstream read request handler");
2004
+
2005
+ if (c->read->timedout) {
2006
+ c->timedout = 1;
2007
+ ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
2008
+ return;
2009
+ }
2010
+
2011
+ ngx_http_upstream_send_request(r, u, 0);
1591
2012
  }
1592
2013
 
1593
2014
 
@@ -1596,6 +2017,7 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
1596
2017
  {
1597
2018
  ssize_t n;
1598
2019
  ngx_int_t rc;
2020
+ ngx_time_t *tp;
1599
2021
  ngx_connection_t *c;
1600
2022
 
1601
2023
  c = u->peer.connection;
@@ -1716,6 +2138,10 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
1716
2138
 
1717
2139
  /* rc == NGX_OK */
1718
2140
 
2141
+ tp = ngx_timeofday();
2142
+ u->state->header_sec = tp->sec - u->state->response_sec;
2143
+ u->state->header_msec = tp->msec - u->state->response_msec;
2144
+
1719
2145
  if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) {
1720
2146
 
1721
2147
  if (ngx_http_upstream_test_next(r, u) == NGX_OK) {
@@ -2035,20 +2461,27 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
2035
2461
  }
2036
2462
  }
2037
2463
 
2038
- uri = u->headers_in.x_accel_redirect->value;
2039
- ngx_str_null(&args);
2040
- flags = NGX_HTTP_LOG_UNSAFE;
2464
+ uri = u->headers_in.x_accel_redirect->value;
2465
+
2466
+ if (uri.data[0] == '@') {
2467
+ ngx_http_named_location(r, &uri);
2468
+
2469
+ } else {
2470
+ ngx_str_null(&args);
2471
+ flags = NGX_HTTP_LOG_UNSAFE;
2041
2472
 
2042
- if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) {
2043
- ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
2044
- return NGX_DONE;
2045
- }
2473
+ if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) {
2474
+ ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
2475
+ return NGX_DONE;
2476
+ }
2477
+
2478
+ if (r->method != NGX_HTTP_HEAD) {
2479
+ r->method = NGX_HTTP_GET;
2480
+ }
2046
2481
 
2047
- if (r->method != NGX_HTTP_HEAD) {
2048
- r->method = NGX_HTTP_GET;
2482
+ ngx_http_internal_redirect(r, &uri, &args);
2049
2483
  }
2050
2484
 
2051
- ngx_http_internal_redirect(r, &uri, &args);
2052
2485
  ngx_http_finalize_request(r, NGX_DONE);
2053
2486
  return NGX_DONE;
2054
2487
  }
@@ -2107,6 +2540,19 @@ ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
2107
2540
 
2108
2541
  r->headers_out.content_length_n = u->headers_in.content_length_n;
2109
2542
 
2543
+ r->disable_not_modified = !u->cacheable;
2544
+
2545
+ if (u->conf->force_ranges) {
2546
+ r->allow_ranges = 1;
2547
+ r->single_range = 1;
2548
+
2549
+ #if (NGX_HTTP_CACHE)
2550
+ if (r->cached) {
2551
+ r->single_range = 0;
2552
+ }
2553
+ #endif
2554
+ }
2555
+
2110
2556
  u->length = -1;
2111
2557
 
2112
2558
  return NGX_OK;
@@ -2218,21 +2664,17 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2218
2664
 
2219
2665
  if (r->header_only) {
2220
2666
 
2221
- if (u->cacheable || u->store) {
2222
-
2223
- if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
2224
- ngx_connection_error(c, ngx_socket_errno,
2225
- ngx_shutdown_socket_n " failed");
2226
- }
2227
-
2228
- r->read_event_handler = ngx_http_request_empty_handler;
2229
- r->write_event_handler = ngx_http_request_empty_handler;
2230
- c->error = 1;
2667
+ if (!u->buffering) {
2668
+ ngx_http_upstream_finalize_request(r, u, rc);
2669
+ return;
2670
+ }
2231
2671
 
2232
- } else {
2672
+ if (!u->cacheable && !u->store) {
2233
2673
  ngx_http_upstream_finalize_request(r, u, rc);
2234
2674
  return;
2235
2675
  }
2676
+
2677
+ u->pipe->downstream_error = 1;
2236
2678
  }
2237
2679
 
2238
2680
  if (r->request_body && r->request_body->temp_file) {
@@ -2332,9 +2774,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2332
2774
 
2333
2775
  if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
2334
2776
 
2335
- r->cache->min_uses = u->conf->cache_min_uses;
2336
- r->cache->body_start = u->conf->buffer_size;
2337
- r->cache->file_cache = u->conf->cache->data;
2777
+ /* create cache if previously bypassed */
2338
2778
 
2339
2779
  if (ngx_http_file_cache_create(r) != NGX_OK) {
2340
2780
  ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
@@ -2361,15 +2801,33 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2361
2801
  }
2362
2802
 
2363
2803
  if (valid) {
2364
- r->cache->last_modified = r->headers_out.last_modified_time;
2365
2804
  r->cache->date = now;
2366
2805
  r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
2367
2806
 
2368
- ngx_http_file_cache_set_header(r, u->buffer.start);
2807
+ if (u->headers_in.status_n == NGX_HTTP_OK
2808
+ || u->headers_in.status_n == NGX_HTTP_PARTIAL_CONTENT)
2809
+ {
2810
+ r->cache->last_modified = u->headers_in.last_modified_time;
2811
+
2812
+ if (u->headers_in.etag) {
2813
+ r->cache->etag = u->headers_in.etag->value;
2814
+
2815
+ } else {
2816
+ ngx_str_null(&r->cache->etag);
2817
+ }
2818
+
2819
+ } else {
2820
+ r->cache->last_modified = -1;
2821
+ ngx_str_null(&r->cache->etag);
2822
+ }
2823
+
2824
+ if (ngx_http_file_cache_set_header(r, u->buffer.start) != NGX_OK) {
2825
+ ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2826
+ return;
2827
+ }
2369
2828
 
2370
2829
  } else {
2371
2830
  u->cacheable = 0;
2372
- r->headers_out.last_modified_time = -1;
2373
2831
  }
2374
2832
  }
2375
2833
 
@@ -2393,6 +2851,8 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2393
2851
  p->downstream = c;
2394
2852
  p->pool = r->pool;
2395
2853
  p->log = c->log;
2854
+ p->limit_rate = u->conf->limit_rate;
2855
+ p->start_sec = ngx_time();
2396
2856
 
2397
2857
  p->cacheable = u->cacheable || u->store;
2398
2858
 
@@ -2410,6 +2870,12 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2410
2870
  if (p->cacheable) {
2411
2871
  p->temp_file->persistent = 1;
2412
2872
 
2873
+ #if (NGX_HTTP_CACHE)
2874
+ if (r->cache && r->cache->file_cache->temp_path) {
2875
+ p->temp_file->path = r->cache->file_cache->temp_path;
2876
+ }
2877
+ #endif
2878
+
2413
2879
  } else {
2414
2880
  p->temp_file->log_level = NGX_LOG_WARN;
2415
2881
  p->temp_file->warn = "an upstream response is buffered "
@@ -3059,7 +3525,7 @@ ngx_http_upstream_process_downstream(ngx_http_request_t *r)
3059
3525
  }
3060
3526
  }
3061
3527
 
3062
- ngx_http_upstream_process_request(r);
3528
+ ngx_http_upstream_process_request(r, u);
3063
3529
  }
3064
3530
 
3065
3531
 
@@ -3067,38 +3533,77 @@ static void
3067
3533
  ngx_http_upstream_process_upstream(ngx_http_request_t *r,
3068
3534
  ngx_http_upstream_t *u)
3069
3535
  {
3536
+ ngx_event_t *rev;
3537
+ ngx_event_pipe_t *p;
3070
3538
  ngx_connection_t *c;
3071
3539
 
3072
3540
  c = u->peer.connection;
3541
+ p = u->pipe;
3542
+ rev = c->read;
3073
3543
 
3074
3544
  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3075
3545
  "http upstream process upstream");
3076
3546
 
3077
3547
  c->log->action = "reading upstream";
3078
3548
 
3079
- if (c->read->timedout) {
3080
- u->pipe->upstream_error = 1;
3081
- ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
3549
+ if (rev->timedout) {
3550
+
3551
+ if (rev->delayed) {
3552
+
3553
+ rev->timedout = 0;
3554
+ rev->delayed = 0;
3555
+
3556
+ if (!rev->ready) {
3557
+ ngx_add_timer(rev, p->read_timeout);
3558
+
3559
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3560
+ ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3561
+ }
3562
+
3563
+ return;
3564
+ }
3565
+
3566
+ if (ngx_event_pipe(p, 0) == NGX_ABORT) {
3567
+ ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3568
+ return;
3569
+ }
3570
+
3571
+ } else {
3572
+ p->upstream_error = 1;
3573
+ ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
3574
+ }
3082
3575
 
3083
3576
  } else {
3084
- if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT) {
3577
+
3578
+ if (rev->delayed) {
3579
+
3580
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3581
+ "http upstream delayed");
3582
+
3583
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3584
+ ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3585
+ }
3586
+
3587
+ return;
3588
+ }
3589
+
3590
+ if (ngx_event_pipe(p, 0) == NGX_ABORT) {
3085
3591
  ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3086
3592
  return;
3087
3593
  }
3088
3594
  }
3089
3595
 
3090
- ngx_http_upstream_process_request(r);
3596
+ ngx_http_upstream_process_request(r, u);
3091
3597
  }
3092
3598
 
3093
3599
 
3094
3600
  static void
3095
- ngx_http_upstream_process_request(ngx_http_request_t *r)
3601
+ ngx_http_upstream_process_request(ngx_http_request_t *r,
3602
+ ngx_http_upstream_t *u)
3096
3603
  {
3097
- ngx_temp_file_t *tf;
3098
- ngx_event_pipe_t *p;
3099
- ngx_http_upstream_t *u;
3604
+ ngx_temp_file_t *tf;
3605
+ ngx_event_pipe_t *p;
3100
3606
 
3101
- u = r->upstream;
3102
3607
  p = u->pipe;
3103
3608
 
3104
3609
  if (u->peer.connection) {
@@ -3115,7 +3620,6 @@ ngx_http_upstream_process_request(ngx_http_request_t *r)
3115
3620
  || u->headers_in.content_length_n == tf->offset))
3116
3621
  {
3117
3622
  ngx_http_upstream_store(r, u);
3118
- u->store = 0;
3119
3623
  }
3120
3624
  }
3121
3625
  }
@@ -3237,7 +3741,9 @@ ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
3237
3741
 
3238
3742
  if (u->conf->store_lengths == NULL) {
3239
3743
 
3240
- ngx_http_map_uri_to_path(r, &path, &root, 0);
3744
+ if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
3745
+ return;
3746
+ }
3241
3747
 
3242
3748
  } else {
3243
3749
  if (ngx_http_script_run(r, &path, u->conf->store_lengths->elts, 0,
@@ -3255,6 +3761,8 @@ ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
3255
3761
  tf->file.name.data, path.data);
3256
3762
 
3257
3763
  (void) ngx_ext_rename_file(&tf->file.name, &path, &ext);
3764
+
3765
+ u->store = 0;
3258
3766
  }
3259
3767
 
3260
3768
 
@@ -3270,6 +3778,7 @@ static void
3270
3778
  ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
3271
3779
  ngx_uint_t ft_type)
3272
3780
  {
3781
+ ngx_msec_t timeout;
3273
3782
  ngx_uint_t status, state;
3274
3783
 
3275
3784
  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -3295,7 +3804,9 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
3295
3804
  "upstream timed out");
3296
3805
  }
3297
3806
 
3298
- if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
3807
+ if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR
3808
+ && (!u->request_sent || !r->request_body_no_buffering))
3809
+ {
3299
3810
  status = 0;
3300
3811
 
3301
3812
  /* TODO: inform balancer instead */
@@ -3303,7 +3814,7 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
3303
3814
  u->peer.tries++;
3304
3815
 
3305
3816
  } else {
3306
- switch(ft_type) {
3817
+ switch (ft_type) {
3307
3818
 
3308
3819
  case NGX_HTTP_UPSTREAM_FT_TIMEOUT:
3309
3820
  status = NGX_HTTP_GATEWAY_TIME_OUT;
@@ -3339,9 +3850,13 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
3339
3850
 
3340
3851
  if (status) {
3341
3852
  u->state->status = status;
3853
+ timeout = u->conf->next_upstream_timeout;
3342
3854
 
3343
- if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) {
3344
-
3855
+ if (u->peer.tries == 0
3856
+ || !(u->conf->next_upstream & ft_type)
3857
+ || (u->request_sent && r->request_body_no_buffering)
3858
+ || (timeout && ngx_current_msec - u->peer.start_time >= timeout))
3859
+ {
3345
3860
  #if (NGX_HTTP_CACHE)
3346
3861
 
3347
3862
  if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
@@ -3414,11 +3929,15 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
3414
3929
  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3415
3930
  "finalize http upstream request: %i", rc);
3416
3931
 
3417
- if (u->cleanup) {
3418
- *u->cleanup = NULL;
3419
- u->cleanup = NULL;
3932
+ if (u->cleanup == NULL) {
3933
+ /* the request was already finalized */
3934
+ ngx_http_finalize_request(r, NGX_DONE);
3935
+ return;
3420
3936
  }
3421
3937
 
3938
+ *u->cleanup = NULL;
3939
+ u->cleanup = NULL;
3940
+
3422
3941
  if (u->resolved && u->resolved->ctx) {
3423
3942
  ngx_resolve_name_done(u->resolved->ctx);
3424
3943
  u->resolved->ctx = NULL;
@@ -3598,15 +4117,55 @@ ngx_http_upstream_process_content_length(ngx_http_request_t *r,
3598
4117
  }
3599
4118
 
3600
4119
 
4120
+ static ngx_int_t
4121
+ ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
4122
+ ngx_table_elt_t *h, ngx_uint_t offset)
4123
+ {
4124
+ ngx_http_upstream_t *u;
4125
+
4126
+ u = r->upstream;
4127
+
4128
+ u->headers_in.last_modified = h;
4129
+
4130
+ #if (NGX_HTTP_CACHE)
4131
+
4132
+ if (u->cacheable) {
4133
+ u->headers_in.last_modified_time = ngx_http_parse_time(h->value.data,
4134
+ h->value.len);
4135
+ }
4136
+
4137
+ #endif
4138
+
4139
+ return NGX_OK;
4140
+ }
4141
+
4142
+
3601
4143
  static ngx_int_t
3602
4144
  ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
3603
4145
  ngx_uint_t offset)
3604
4146
  {
3605
- #if (NGX_HTTP_CACHE)
3606
- ngx_http_upstream_t *u;
4147
+ ngx_array_t *pa;
4148
+ ngx_table_elt_t **ph;
4149
+ ngx_http_upstream_t *u;
3607
4150
 
3608
4151
  u = r->upstream;
4152
+ pa = &u->headers_in.cookies;
4153
+
4154
+ if (pa->elts == NULL) {
4155
+ if (ngx_array_init(pa, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK)
4156
+ {
4157
+ return NGX_ERROR;
4158
+ }
4159
+ }
4160
+
4161
+ ph = ngx_array_push(pa);
4162
+ if (ph == NULL) {
4163
+ return NGX_ERROR;
4164
+ }
4165
+
4166
+ *ph = h;
3609
4167
 
4168
+ #if (NGX_HTTP_CACHE)
3610
4169
  if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
3611
4170
  u->cacheable = 0;
3612
4171
  }
@@ -3643,7 +4202,7 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
3643
4202
 
3644
4203
  #if (NGX_HTTP_CACHE)
3645
4204
  {
3646
- u_char *p, *last;
4205
+ u_char *p, *start, *last;
3647
4206
  ngx_int_t n;
3648
4207
 
3649
4208
  if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL) {
@@ -3658,18 +4217,24 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
3658
4217
  return NGX_OK;
3659
4218
  }
3660
4219
 
3661
- p = h->value.data;
3662
- last = p + h->value.len;
4220
+ start = h->value.data;
4221
+ last = start + h->value.len;
3663
4222
 
3664
- if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL
3665
- || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL
3666
- || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
4223
+ if (ngx_strlcasestrn(start, last, (u_char *) "no-cache", 8 - 1) != NULL
4224
+ || ngx_strlcasestrn(start, last, (u_char *) "no-store", 8 - 1) != NULL
4225
+ || ngx_strlcasestrn(start, last, (u_char *) "private", 7 - 1) != NULL)
3667
4226
  {
3668
4227
  u->cacheable = 0;
3669
4228
  return NGX_OK;
3670
4229
  }
3671
4230
 
3672
- p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
4231
+ p = ngx_strlcasestrn(start, last, (u_char *) "s-maxage=", 9 - 1);
4232
+ offset = 9;
4233
+
4234
+ if (p == NULL) {
4235
+ p = ngx_strlcasestrn(start, last, (u_char *) "max-age=", 8 - 1);
4236
+ offset = 8;
4237
+ }
3673
4238
 
3674
4239
  if (p == NULL) {
3675
4240
  return NGX_OK;
@@ -3677,7 +4242,7 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
3677
4242
 
3678
4243
  n = 0;
3679
4244
 
3680
- for (p += 8; p < last; p++) {
4245
+ for (p += offset; p < last; p++) {
3681
4246
  if (*p == ',' || *p == ';' || *p == ' ') {
3682
4247
  break;
3683
4248
  }
@@ -3912,6 +4477,39 @@ ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
3912
4477
  }
3913
4478
 
3914
4479
 
4480
+ static ngx_int_t
4481
+ ngx_http_upstream_process_vary(ngx_http_request_t *r,
4482
+ ngx_table_elt_t *h, ngx_uint_t offset)
4483
+ {
4484
+ ngx_http_upstream_t *u;
4485
+
4486
+ u = r->upstream;
4487
+ u->headers_in.vary = h;
4488
+
4489
+ #if (NGX_HTTP_CACHE)
4490
+
4491
+ if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_VARY) {
4492
+ return NGX_OK;
4493
+ }
4494
+
4495
+ if (r->cache == NULL) {
4496
+ return NGX_OK;
4497
+ }
4498
+
4499
+ if (h->value.len > NGX_HTTP_CACHE_VARY_LEN
4500
+ || (h->value.len == 1 && h->value.data[0] == '*'))
4501
+ {
4502
+ u->cacheable = 0;
4503
+ }
4504
+
4505
+ r->cache->vary = h->value;
4506
+
4507
+ #endif
4508
+
4509
+ return NGX_OK;
4510
+ }
4511
+
4512
+
3915
4513
  static ngx_int_t
3916
4514
  ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3917
4515
  ngx_uint_t offset)
@@ -4037,8 +4635,8 @@ ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
4037
4635
  #if (NGX_HTTP_CACHE)
4038
4636
 
4039
4637
  if (r->upstream->cacheable) {
4040
- r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
4041
- h->value.len);
4638
+ r->headers_out.last_modified_time =
4639
+ r->upstream->headers_in.last_modified_time;
4042
4640
  }
4043
4641
 
4044
4642
  #endif
@@ -4178,6 +4776,10 @@ ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
4178
4776
  {
4179
4777
  ngx_table_elt_t *ho;
4180
4778
 
4779
+ if (r->upstream->conf->force_ranges) {
4780
+ return NGX_OK;
4781
+ }
4782
+
4181
4783
  #if (NGX_HTTP_CACHE)
4182
4784
 
4183
4785
  if (r->cached) {
@@ -4417,8 +5019,18 @@ ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
4417
5019
 
4418
5020
  for ( ;; ) {
4419
5021
  if (state[i].status) {
4420
- ms = (ngx_msec_int_t)
4421
- (state[i].response_sec * 1000 + state[i].response_msec);
5022
+
5023
+ if (data
5024
+ && state[i].header_sec != (time_t) NGX_ERROR)
5025
+ {
5026
+ ms = (ngx_msec_int_t)
5027
+ (state[i].header_sec * 1000 + state[i].header_msec);
5028
+
5029
+ } else {
5030
+ ms = (ngx_msec_int_t)
5031
+ (state[i].response_sec * 1000 + state[i].response_msec);
5032
+ }
5033
+
4422
5034
  ms = ngx_max(ms, 0);
4423
5035
  p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);
4424
5036
 
@@ -4528,6 +5140,40 @@ ngx_http_upstream_header_variable(ngx_http_request_t *r,
4528
5140
  }
4529
5141
 
4530
5142
 
5143
+ ngx_int_t
5144
+ ngx_http_upstream_cookie_variable(ngx_http_request_t *r,
5145
+ ngx_http_variable_value_t *v, uintptr_t data)
5146
+ {
5147
+ ngx_str_t *name = (ngx_str_t *) data;
5148
+
5149
+ ngx_str_t cookie, s;
5150
+
5151
+ if (r->upstream == NULL) {
5152
+ v->not_found = 1;
5153
+ return NGX_OK;
5154
+ }
5155
+
5156
+ s.len = name->len - (sizeof("upstream_cookie_") - 1);
5157
+ s.data = name->data + sizeof("upstream_cookie_") - 1;
5158
+
5159
+ if (ngx_http_parse_set_cookie_lines(&r->upstream->headers_in.cookies,
5160
+ &s, &cookie)
5161
+ == NGX_DECLINED)
5162
+ {
5163
+ v->not_found = 1;
5164
+ return NGX_OK;
5165
+ }
5166
+
5167
+ v->len = cookie.len;
5168
+ v->valid = 1;
5169
+ v->no_cacheable = 0;
5170
+ v->not_found = 0;
5171
+ v->data = cookie.data;
5172
+
5173
+ return NGX_OK;
5174
+ }
5175
+
5176
+
4531
5177
  #if (NGX_HTTP_CACHE)
4532
5178
 
4533
5179
  ngx_int_t
@@ -4582,6 +5228,29 @@ ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
4582
5228
  return NGX_OK;
4583
5229
  }
4584
5230
 
5231
+
5232
+ static ngx_int_t
5233
+ ngx_http_upstream_cache_etag(ngx_http_request_t *r,
5234
+ ngx_http_variable_value_t *v, uintptr_t data)
5235
+ {
5236
+ if (r->upstream == NULL
5237
+ || !r->upstream->conf->cache_revalidate
5238
+ || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED
5239
+ || r->cache->etag.len == 0)
5240
+ {
5241
+ v->not_found = 1;
5242
+ return NGX_OK;
5243
+ }
5244
+
5245
+ v->valid = 1;
5246
+ v->no_cacheable = 0;
5247
+ v->not_found = 0;
5248
+ v->len = r->cache->etag.len;
5249
+ v->data = r->cache->etag.data;
5250
+
5251
+ return NGX_OK;
5252
+ }
5253
+
4585
5254
  #endif
4586
5255
 
4587
5256
 
@@ -4669,6 +5338,12 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
4669
5338
  }
4670
5339
  }
4671
5340
 
5341
+ uscf->servers = ngx_array_create(cf->pool, 4,
5342
+ sizeof(ngx_http_upstream_server_t));
5343
+ if (uscf->servers == NULL) {
5344
+ return NGX_CONF_ERROR;
5345
+ }
5346
+
4672
5347
 
4673
5348
  /* parse inside upstream{} */
4674
5349
 
@@ -4684,7 +5359,7 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
4684
5359
  return rv;
4685
5360
  }
4686
5361
 
4687
- if (uscf->servers == NULL) {
5362
+ if (uscf->servers->nelts == 0) {
4688
5363
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4689
5364
  "no servers are inside upstream");
4690
5365
  return NGX_CONF_ERROR;
@@ -4706,14 +5381,6 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4706
5381
  ngx_uint_t i;
4707
5382
  ngx_http_upstream_server_t *us;
4708
5383
 
4709
- if (uscf->servers == NULL) {
4710
- uscf->servers = ngx_array_create(cf->pool, 4,
4711
- sizeof(ngx_http_upstream_server_t));
4712
- if (uscf->servers == NULL) {
4713
- return NGX_CONF_ERROR;
4714
- }
4715
- }
4716
-
4717
5384
  us = ngx_array_push(uscf->servers);
4718
5385
  if (us == NULL) {
4719
5386
  return NGX_CONF_ERROR;
@@ -4723,20 +5390,6 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4723
5390
 
4724
5391
  value = cf->args->elts;
4725
5392
 
4726
- ngx_memzero(&u, sizeof(ngx_url_t));
4727
-
4728
- u.url = value[1];
4729
- u.default_port = 80;
4730
-
4731
- if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
4732
- if (u.err) {
4733
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4734
- "%s in upstream \"%V\"", u.err, &u.url);
4735
- }
4736
-
4737
- return NGX_CONF_ERROR;
4738
- }
4739
-
4740
5393
  weight = 1;
4741
5394
  max_fails = 1;
4742
5395
  fail_timeout = 10;
@@ -4746,7 +5399,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4746
5399
  if (ngx_strncmp(value[i].data, "weight=", 7) == 0) {
4747
5400
 
4748
5401
  if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT)) {
4749
- goto invalid;
5402
+ goto not_supported;
4750
5403
  }
4751
5404
 
4752
5405
  weight = ngx_atoi(&value[i].data[7], value[i].len - 7);
@@ -4761,7 +5414,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4761
5414
  if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) {
4762
5415
 
4763
5416
  if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) {
4764
- goto invalid;
5417
+ goto not_supported;
4765
5418
  }
4766
5419
 
4767
5420
  max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10);
@@ -4776,7 +5429,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4776
5429
  if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) {
4777
5430
 
4778
5431
  if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT)) {
4779
- goto invalid;
5432
+ goto not_supported;
4780
5433
  }
4781
5434
 
4782
5435
  s.len = value[i].len - 13;
@@ -4794,7 +5447,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4794
5447
  if (ngx_strcmp(value[i].data, "backup") == 0) {
4795
5448
 
4796
5449
  if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP)) {
4797
- goto invalid;
5450
+ goto not_supported;
4798
5451
  }
4799
5452
 
4800
5453
  us->backup = 1;
@@ -4805,7 +5458,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4805
5458
  if (ngx_strcmp(value[i].data, "down") == 0) {
4806
5459
 
4807
5460
  if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) {
4808
- goto invalid;
5461
+ goto not_supported;
4809
5462
  }
4810
5463
 
4811
5464
  us->down = 1;
@@ -4816,6 +5469,21 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4816
5469
  goto invalid;
4817
5470
  }
4818
5471
 
5472
+ ngx_memzero(&u, sizeof(ngx_url_t));
5473
+
5474
+ u.url = value[1];
5475
+ u.default_port = 80;
5476
+
5477
+ if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
5478
+ if (u.err) {
5479
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5480
+ "%s in upstream \"%V\"", u.err, &u.url);
5481
+ }
5482
+
5483
+ return NGX_CONF_ERROR;
5484
+ }
5485
+
5486
+ us->name = u.url;
4819
5487
  us->addrs = u.addrs;
4820
5488
  us->naddrs = u.naddrs;
4821
5489
  us->weight = weight;
@@ -4830,6 +5498,14 @@ invalid:
4830
5498
  "invalid parameter \"%V\"", &value[i]);
4831
5499
 
4832
5500
  return NGX_CONF_ERROR;
5501
+
5502
+ not_supported:
5503
+
5504
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5505
+ "balancing method does not support parameter \"%V\"",
5506
+ &value[i]);
5507
+
5508
+ return NGX_CONF_ERROR;
4833
5509
  }
4834
5510
 
4835
5511
 
@@ -4921,7 +5597,7 @@ ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
4921
5597
  uscf->default_port = u->default_port;
4922
5598
  uscf->no_port = u->no_port;
4923
5599
 
4924
- if (u->naddrs == 1) {
5600
+ if (u->naddrs == 1 && (u->port || u->family == AF_UNIX)) {
4925
5601
  uscf->servers = ngx_array_create(cf->pool, 1,
4926
5602
  sizeof(ngx_http_upstream_server_t));
4927
5603
  if (uscf->servers == NULL) {
@@ -5137,7 +5813,7 @@ ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
5137
5813
 
5138
5814
  if (conf->hide_headers_hash.buckets
5139
5815
  #if (NGX_HTTP_CACHE)
5140
- && ((conf->cache == NULL) == (prev->cache == NULL))
5816
+ && ((conf->cache == 0) == (prev->cache == 0))
5141
5817
  #endif
5142
5818
  )
5143
5819
  {