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
@@ -1470,7 +1470,7 @@ ngx_http_geo_include_binary_base(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
1470
1470
 
1471
1471
  vv = (ngx_http_variable_value_t *) (base + sizeof(ngx_http_geo_header_t));
1472
1472
 
1473
- while(vv->data) {
1473
+ while (vv->data) {
1474
1474
  len = ngx_align(sizeof(ngx_http_variable_value_t) + vv->len,
1475
1475
  sizeof(void *));
1476
1476
  ngx_crc32_update(&crc32, (u_char *) vv, len);
@@ -553,6 +553,9 @@ ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
553
553
  val = *(float *) ((char *) gr + data);
554
554
 
555
555
  v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
556
+ v->valid = 1;
557
+ v->no_cacheable = 0;
558
+ v->not_found = 0;
556
559
 
557
560
  GeoIPRecord_delete(gr);
558
561
 
@@ -582,6 +585,9 @@ ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
582
585
  val = *(int *) ((char *) gr + data);
583
586
 
584
587
  v->len = ngx_sprintf(v->data, "%d", val) - v->data;
588
+ v->valid = 1;
589
+ v->no_cacheable = 0;
590
+ v->not_found = 0;
585
591
 
586
592
  GeoIPRecord_delete(gr);
587
593
 
@@ -691,7 +697,7 @@ ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
691
697
 
692
698
  if (cf->args->nelts == 3) {
693
699
  if (ngx_strcmp(value[2].data, "utf8") == 0) {
694
- GeoIP_set_charset (gcf->country, GEOIP_CHARSET_UTF8);
700
+ GeoIP_set_charset(gcf->country, GEOIP_CHARSET_UTF8);
695
701
 
696
702
  } else {
697
703
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -746,7 +752,7 @@ ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
746
752
 
747
753
  if (cf->args->nelts == 3) {
748
754
  if (ngx_strcmp(value[2].data, "utf8") == 0) {
749
- GeoIP_set_charset (gcf->org, GEOIP_CHARSET_UTF8);
755
+ GeoIP_set_charset(gcf->org, GEOIP_CHARSET_UTF8);
750
756
 
751
757
  } else {
752
758
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -807,7 +813,7 @@ ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
807
813
 
808
814
  if (cf->args->nelts == 3) {
809
815
  if (ngx_strcmp(value[2].data, "utf8") == 0) {
810
- GeoIP_set_charset (gcf->city, GEOIP_CHARSET_UTF8);
816
+ GeoIP_set_charset(gcf->city, GEOIP_CHARSET_UTF8);
811
817
 
812
818
  } else {
813
819
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -165,7 +165,7 @@ ngx_http_gunzip_header_filter(ngx_http_request_t *r)
165
165
 
166
166
  ngx_http_clear_content_length(r);
167
167
  ngx_http_clear_accept_ranges(r);
168
- ngx_http_clear_etag(r);
168
+ ngx_http_weak_etag(r);
169
169
 
170
170
  return ngx_http_next_header_filter(r);
171
171
  }
@@ -175,6 +175,7 @@ static ngx_int_t
175
175
  ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
176
176
  {
177
177
  int rc;
178
+ ngx_uint_t flush;
178
179
  ngx_chain_t *cl;
179
180
  ngx_http_gunzip_ctx_t *ctx;
180
181
 
@@ -199,7 +200,7 @@ ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
199
200
  }
200
201
  }
201
202
 
202
- if (ctx->nomem || in == NULL) {
203
+ if (ctx->nomem) {
203
204
 
204
205
  /* flush busy buffers */
205
206
 
@@ -212,6 +213,10 @@ ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
212
213
  ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
213
214
  (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
214
215
  ctx->nomem = 0;
216
+ flush = 0;
217
+
218
+ } else {
219
+ flush = ctx->busy ? 1 : 0;
215
220
  }
216
221
 
217
222
  for ( ;; ) {
@@ -258,7 +263,7 @@ ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
258
263
  /* rc == NGX_AGAIN */
259
264
  }
260
265
 
261
- if (ctx->out == NULL) {
266
+ if (ctx->out == NULL && !flush) {
262
267
  return ctx->busy ? NGX_AGAIN : NGX_OK;
263
268
  }
264
269
 
@@ -276,6 +281,7 @@ ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
276
281
  "gunzip out: %p", ctx->out);
277
282
 
278
283
  ctx->nomem = 0;
284
+ flush = 0;
279
285
 
280
286
  if (ctx->done) {
281
287
  return rc;
@@ -306,7 +306,7 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
306
306
 
307
307
  ngx_http_clear_content_length(r);
308
308
  ngx_http_clear_accept_ranges(r);
309
- ngx_http_clear_etag(r);
309
+ ngx_http_weak_etag(r);
310
310
 
311
311
  return ngx_http_next_header_filter(r);
312
312
  }
@@ -316,6 +316,7 @@ static ngx_int_t
316
316
  ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
317
317
  {
318
318
  int rc;
319
+ ngx_uint_t flush;
319
320
  ngx_chain_t *cl;
320
321
  ngx_http_gzip_ctx_t *ctx;
321
322
 
@@ -372,7 +373,7 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
372
373
  r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
373
374
  }
374
375
 
375
- if (ctx->nomem || in == NULL) {
376
+ if (ctx->nomem) {
376
377
 
377
378
  /* flush busy buffers */
378
379
 
@@ -385,6 +386,10 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
385
386
  ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
386
387
  (ngx_buf_tag_t) &ngx_http_gzip_filter_module);
387
388
  ctx->nomem = 0;
389
+ flush = 0;
390
+
391
+ } else {
392
+ flush = ctx->busy ? 1 : 0;
388
393
  }
389
394
 
390
395
  for ( ;; ) {
@@ -432,7 +437,7 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
432
437
  /* rc == NGX_AGAIN */
433
438
  }
434
439
 
435
- if (ctx->out == NULL) {
440
+ if (ctx->out == NULL && !flush) {
436
441
  ngx_http_gzip_filter_free_copy_buf(r, ctx);
437
442
 
438
443
  return ctx->busy ? NGX_AGAIN : NGX_OK;
@@ -457,6 +462,7 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
457
462
  ctx->last_out = &ctx->out;
458
463
 
459
464
  ctx->nomem = 0;
465
+ flush = 0;
460
466
 
461
467
  if (ctx->done) {
462
468
  return rc;
@@ -246,8 +246,6 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
246
246
  ngx_str_set(&h->value, "gzip");
247
247
  r->headers_out.content_encoding = h;
248
248
 
249
- r->ignore_content_encoding = 1;
250
-
251
249
  /* we need to allocate all before the header would be sent */
252
250
 
253
251
  b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
@@ -28,6 +28,7 @@ struct ngx_http_header_val_s {
28
28
  ngx_str_t key;
29
29
  ngx_http_set_header_pt handler;
30
30
  ngx_uint_t offset;
31
+ ngx_uint_t always; /* unsigned always:1 */
31
32
  };
32
33
 
33
34
 
@@ -43,14 +44,17 @@ typedef enum {
43
44
 
44
45
 
45
46
  typedef struct {
46
- ngx_http_expires_t expires;
47
- time_t expires_time;
48
- ngx_array_t *headers;
47
+ ngx_http_expires_t expires;
48
+ time_t expires_time;
49
+ ngx_http_complex_value_t *expires_value;
50
+ ngx_array_t *headers;
49
51
  } ngx_http_headers_conf_t;
50
52
 
51
53
 
52
54
  static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r,
53
55
  ngx_http_headers_conf_t *conf);
56
+ static ngx_int_t ngx_http_parse_expires(ngx_str_t *value,
57
+ ngx_http_expires_t *expires, time_t *expires_time, char **err);
54
58
  static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r,
55
59
  ngx_http_header_val_t *hv, ngx_str_t *value);
56
60
  static ngx_int_t ngx_http_add_header(ngx_http_request_t *r,
@@ -98,7 +102,7 @@ static ngx_command_t ngx_http_headers_filter_commands[] = {
98
102
 
99
103
  { ngx_string("add_header"),
100
104
  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
101
- |NGX_CONF_TAKE2,
105
+ |NGX_CONF_TAKE23,
102
106
  ngx_http_headers_add,
103
107
  NGX_HTTP_LOC_CONF_OFFSET,
104
108
  0,
@@ -146,28 +150,38 @@ static ngx_int_t
146
150
  ngx_http_headers_filter(ngx_http_request_t *r)
147
151
  {
148
152
  ngx_str_t value;
149
- ngx_uint_t i;
153
+ ngx_uint_t i, safe_status;
150
154
  ngx_http_header_val_t *h;
151
155
  ngx_http_headers_conf_t *conf;
152
156
 
153
157
  conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
154
158
 
155
159
  if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL)
156
- || r != r->main
157
- || (r->headers_out.status != NGX_HTTP_OK
158
- && r->headers_out.status != NGX_HTTP_CREATED
159
- && r->headers_out.status != NGX_HTTP_NO_CONTENT
160
- && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT
161
- && r->headers_out.status != NGX_HTTP_MOVED_PERMANENTLY
162
- && r->headers_out.status != NGX_HTTP_MOVED_TEMPORARILY
163
- && r->headers_out.status != NGX_HTTP_SEE_OTHER
164
- && r->headers_out.status != NGX_HTTP_NOT_MODIFIED
165
- && r->headers_out.status != NGX_HTTP_TEMPORARY_REDIRECT))
160
+ || r != r->main)
166
161
  {
167
162
  return ngx_http_next_header_filter(r);
168
163
  }
169
164
 
170
- if (conf->expires != NGX_HTTP_EXPIRES_OFF) {
165
+ switch (r->headers_out.status) {
166
+
167
+ case NGX_HTTP_OK:
168
+ case NGX_HTTP_CREATED:
169
+ case NGX_HTTP_NO_CONTENT:
170
+ case NGX_HTTP_PARTIAL_CONTENT:
171
+ case NGX_HTTP_MOVED_PERMANENTLY:
172
+ case NGX_HTTP_MOVED_TEMPORARILY:
173
+ case NGX_HTTP_SEE_OTHER:
174
+ case NGX_HTTP_NOT_MODIFIED:
175
+ case NGX_HTTP_TEMPORARY_REDIRECT:
176
+ safe_status = 1;
177
+ break;
178
+
179
+ default:
180
+ safe_status = 0;
181
+ break;
182
+ }
183
+
184
+ if (conf->expires != NGX_HTTP_EXPIRES_OFF && safe_status) {
171
185
  if (ngx_http_set_expires(r, conf) != NGX_OK) {
172
186
  return NGX_ERROR;
173
187
  }
@@ -177,6 +191,10 @@ ngx_http_headers_filter(ngx_http_request_t *r)
177
191
  h = conf->headers->elts;
178
192
  for (i = 0; i < conf->headers->nelts; i++) {
179
193
 
194
+ if (!safe_status && !h[i].always) {
195
+ continue;
196
+ }
197
+
180
198
  if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
181
199
  return NGX_ERROR;
182
200
  }
@@ -194,28 +212,52 @@ ngx_http_headers_filter(ngx_http_request_t *r)
194
212
  static ngx_int_t
195
213
  ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
196
214
  {
197
- size_t len;
198
- time_t now, expires_time, max_age;
199
- ngx_uint_t i;
200
- ngx_table_elt_t *expires, *cc, **ccp;
215
+ char *err;
216
+ size_t len;
217
+ time_t now, expires_time, max_age;
218
+ ngx_str_t value;
219
+ ngx_int_t rc;
220
+ ngx_uint_t i;
221
+ ngx_table_elt_t *e, *cc, **ccp;
222
+ ngx_http_expires_t expires;
223
+
224
+ expires = conf->expires;
225
+ expires_time = conf->expires_time;
226
+
227
+ if (conf->expires_value != NULL) {
228
+
229
+ if (ngx_http_complex_value(r, conf->expires_value, &value) != NGX_OK) {
230
+ return NGX_ERROR;
231
+ }
232
+
233
+ rc = ngx_http_parse_expires(&value, &expires, &expires_time, &err);
234
+
235
+ if (rc != NGX_OK) {
236
+ return NGX_OK;
237
+ }
238
+
239
+ if (expires == NGX_HTTP_EXPIRES_OFF) {
240
+ return NGX_OK;
241
+ }
242
+ }
201
243
 
202
- expires = r->headers_out.expires;
244
+ e = r->headers_out.expires;
203
245
 
204
- if (expires == NULL) {
246
+ if (e == NULL) {
205
247
 
206
- expires = ngx_list_push(&r->headers_out.headers);
207
- if (expires == NULL) {
248
+ e = ngx_list_push(&r->headers_out.headers);
249
+ if (e == NULL) {
208
250
  return NGX_ERROR;
209
251
  }
210
252
 
211
- r->headers_out.expires = expires;
253
+ r->headers_out.expires = e;
212
254
 
213
- expires->hash = 1;
214
- ngx_str_set(&expires->key, "Expires");
255
+ e->hash = 1;
256
+ ngx_str_set(&e->key, "Expires");
215
257
  }
216
258
 
217
259
  len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
218
- expires->value.len = len - 1;
260
+ e->value.len = len - 1;
219
261
 
220
262
  ccp = r->headers_out.cache_control.elts;
221
263
 
@@ -250,26 +292,26 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
250
292
  cc = ccp[0];
251
293
  }
252
294
 
253
- if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) {
254
- expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
295
+ if (expires == NGX_HTTP_EXPIRES_EPOCH) {
296
+ e->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
255
297
  ngx_str_set(&cc->value, "no-cache");
256
298
  return NGX_OK;
257
299
  }
258
300
 
259
- if (conf->expires == NGX_HTTP_EXPIRES_MAX) {
260
- expires->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT";
301
+ if (expires == NGX_HTTP_EXPIRES_MAX) {
302
+ e->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT";
261
303
  /* 10 years */
262
304
  ngx_str_set(&cc->value, "max-age=315360000");
263
305
  return NGX_OK;
264
306
  }
265
307
 
266
- expires->value.data = ngx_pnalloc(r->pool, len);
267
- if (expires->value.data == NULL) {
308
+ e->value.data = ngx_pnalloc(r->pool, len);
309
+ if (e->value.data == NULL) {
268
310
  return NGX_ERROR;
269
311
  }
270
312
 
271
- if (conf->expires_time == 0 && conf->expires != NGX_HTTP_EXPIRES_DAILY) {
272
- ngx_memcpy(expires->value.data, ngx_cached_http_time.data,
313
+ if (expires_time == 0 && expires != NGX_HTTP_EXPIRES_DAILY) {
314
+ ngx_memcpy(e->value.data, ngx_cached_http_time.data,
273
315
  ngx_cached_http_time.len + 1);
274
316
  ngx_str_set(&cc->value, "max-age=0");
275
317
  return NGX_OK;
@@ -277,22 +319,22 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
277
319
 
278
320
  now = ngx_time();
279
321
 
280
- if (conf->expires == NGX_HTTP_EXPIRES_DAILY) {
281
- expires_time = ngx_next_time(conf->expires_time);
322
+ if (expires == NGX_HTTP_EXPIRES_DAILY) {
323
+ expires_time = ngx_next_time(expires_time);
282
324
  max_age = expires_time - now;
283
325
 
284
- } else if (conf->expires == NGX_HTTP_EXPIRES_ACCESS
326
+ } else if (expires == NGX_HTTP_EXPIRES_ACCESS
285
327
  || r->headers_out.last_modified_time == -1)
286
328
  {
287
- expires_time = now + conf->expires_time;
288
- max_age = conf->expires_time;
329
+ max_age = expires_time;
330
+ expires_time += now;
289
331
 
290
332
  } else {
291
- expires_time = r->headers_out.last_modified_time + conf->expires_time;
333
+ expires_time += r->headers_out.last_modified_time;
292
334
  max_age = expires_time - now;
293
335
  }
294
336
 
295
- ngx_http_time(expires->value.data, expires_time);
337
+ ngx_http_time(e->value.data, expires_time);
296
338
 
297
339
  if (conf->expires_time < 0 || max_age < 0) {
298
340
  ngx_str_set(&cc->value, "no-cache");
@@ -312,6 +354,78 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
312
354
  }
313
355
 
314
356
 
357
+ static ngx_int_t
358
+ ngx_http_parse_expires(ngx_str_t *value, ngx_http_expires_t *expires,
359
+ time_t *expires_time, char **err)
360
+ {
361
+ ngx_uint_t minus;
362
+
363
+ if (*expires != NGX_HTTP_EXPIRES_MODIFIED) {
364
+
365
+ if (value->len == 5 && ngx_strncmp(value->data, "epoch", 5) == 0) {
366
+ *expires = NGX_HTTP_EXPIRES_EPOCH;
367
+ return NGX_OK;
368
+ }
369
+
370
+ if (value->len == 3 && ngx_strncmp(value->data, "max", 3) == 0) {
371
+ *expires = NGX_HTTP_EXPIRES_MAX;
372
+ return NGX_OK;
373
+ }
374
+
375
+ if (value->len == 3 && ngx_strncmp(value->data, "off", 3) == 0) {
376
+ *expires = NGX_HTTP_EXPIRES_OFF;
377
+ return NGX_OK;
378
+ }
379
+ }
380
+
381
+ if (value->len && value->data[0] == '@') {
382
+ value->data++;
383
+ value->len--;
384
+ minus = 0;
385
+
386
+ if (*expires == NGX_HTTP_EXPIRES_MODIFIED) {
387
+ *err = "daily time cannot be used with \"modified\" parameter";
388
+ return NGX_ERROR;
389
+ }
390
+
391
+ *expires = NGX_HTTP_EXPIRES_DAILY;
392
+
393
+ } else if (value->len && value->data[0] == '+') {
394
+ value->data++;
395
+ value->len--;
396
+ minus = 0;
397
+
398
+ } else if (value->len && value->data[0] == '-') {
399
+ value->data++;
400
+ value->len--;
401
+ minus = 1;
402
+
403
+ } else {
404
+ minus = 0;
405
+ }
406
+
407
+ *expires_time = ngx_parse_time(value, 1);
408
+
409
+ if (*expires_time == (time_t) NGX_ERROR) {
410
+ *err = "invalid value";
411
+ return NGX_ERROR;
412
+ }
413
+
414
+ if (*expires == NGX_HTTP_EXPIRES_DAILY
415
+ && *expires_time > 24 * 60 * 60)
416
+ {
417
+ *err = "daily time value must be less than 24 hours";
418
+ return NGX_ERROR;
419
+ }
420
+
421
+ if (minus) {
422
+ *expires_time = - *expires_time;
423
+ }
424
+
425
+ return NGX_OK;
426
+ }
427
+
428
+
315
429
  static ngx_int_t
316
430
  ngx_http_add_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
317
431
  ngx_str_t *value)
@@ -442,6 +556,7 @@ ngx_http_headers_create_conf(ngx_conf_t *cf)
442
556
  *
443
557
  * conf->headers = NULL;
444
558
  * conf->expires_time = 0;
559
+ * conf->expires_value = NULL;
445
560
  */
446
561
 
447
562
  conf->expires = NGX_HTTP_EXPIRES_UNSET;
@@ -459,6 +574,7 @@ ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child)
459
574
  if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
460
575
  conf->expires = prev->expires;
461
576
  conf->expires_time = prev->expires_time;
577
+ conf->expires_value = prev->expires_value;
462
578
 
463
579
  if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
464
580
  conf->expires = NGX_HTTP_EXPIRES_OFF;
@@ -488,8 +604,12 @@ ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
488
604
  {
489
605
  ngx_http_headers_conf_t *hcf = conf;
490
606
 
491
- ngx_uint_t minus, n;
492
- ngx_str_t *value;
607
+ char *err;
608
+ ngx_str_t *value;
609
+ ngx_int_t rc;
610
+ ngx_uint_t n;
611
+ ngx_http_complex_value_t cv;
612
+ ngx_http_compile_complex_value_t ccv;
493
613
 
494
614
  if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) {
495
615
  return "is duplicate";
@@ -499,21 +619,6 @@ ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
499
619
 
500
620
  if (cf->args->nelts == 2) {
501
621
 
502
- if (ngx_strcmp(value[1].data, "epoch") == 0) {
503
- hcf->expires = NGX_HTTP_EXPIRES_EPOCH;
504
- return NGX_CONF_OK;
505
- }
506
-
507
- if (ngx_strcmp(value[1].data, "max") == 0) {
508
- hcf->expires = NGX_HTTP_EXPIRES_MAX;
509
- return NGX_CONF_OK;
510
- }
511
-
512
- if (ngx_strcmp(value[1].data, "off") == 0) {
513
- hcf->expires = NGX_HTTP_EXPIRES_OFF;
514
- return NGX_CONF_OK;
515
- }
516
-
517
622
  hcf->expires = NGX_HTTP_EXPIRES_ACCESS;
518
623
 
519
624
  n = 1;
@@ -529,45 +634,33 @@ ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
529
634
  n = 2;
530
635
  }
531
636
 
532
- if (value[n].data[0] == '@') {
533
- value[n].data++;
534
- value[n].len--;
535
- minus = 0;
536
-
537
- if (hcf->expires == NGX_HTTP_EXPIRES_MODIFIED) {
538
- return "daily time cannot be used with \"modified\" parameter";
539
- }
540
-
541
- hcf->expires = NGX_HTTP_EXPIRES_DAILY;
542
-
543
- } else if (value[n].data[0] == '+') {
544
- value[n].data++;
545
- value[n].len--;
546
- minus = 0;
637
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
547
638
 
548
- } else if (value[n].data[0] == '-') {
549
- value[n].data++;
550
- value[n].len--;
551
- minus = 1;
639
+ ccv.cf = cf;
640
+ ccv.value = &value[n];
641
+ ccv.complex_value = &cv;
552
642
 
553
- } else {
554
- minus = 0;
643
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
644
+ return NGX_CONF_ERROR;
555
645
  }
556
646
 
557
- hcf->expires_time = ngx_parse_time(&value[n], 1);
647
+ if (cv.lengths != NULL) {
558
648
 
559
- if (hcf->expires_time == (time_t) NGX_ERROR) {
560
- return "invalid value";
561
- }
649
+ hcf->expires_value = ngx_palloc(cf->pool,
650
+ sizeof(ngx_http_complex_value_t));
651
+ if (hcf->expires_value == NULL) {
652
+ return NGX_CONF_ERROR;
653
+ }
562
654
 
563
- if (hcf->expires == NGX_HTTP_EXPIRES_DAILY
564
- && hcf->expires_time > 24 * 60 * 60)
565
- {
566
- return "daily time value must be less than 24 hours";
655
+ *hcf->expires_value = cv;
656
+
657
+ return NGX_CONF_OK;
567
658
  }
568
659
 
569
- if (minus) {
570
- hcf->expires_time = - hcf->expires_time;
660
+ rc = ngx_http_parse_expires(&value[n], &hcf->expires, &hcf->expires_time,
661
+ &err);
662
+ if (rc != NGX_OK) {
663
+ return err;
571
664
  }
572
665
 
573
666
  return NGX_CONF_OK;
@@ -603,6 +696,7 @@ ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
603
696
  hv->key = value[1];
604
697
  hv->handler = ngx_http_add_header;
605
698
  hv->offset = 0;
699
+ hv->always = 0;
606
700
 
607
701
  set = ngx_http_set_headers;
608
702
  for (i = 0; set[i].name.len; i++) {
@@ -631,5 +725,17 @@ ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
631
725
  return NGX_CONF_ERROR;
632
726
  }
633
727
 
728
+ if (cf->args->nelts == 3) {
729
+ return NGX_CONF_OK;
730
+ }
731
+
732
+ if (ngx_strcmp(value[3].data, "always") != 0) {
733
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
734
+ "invalid parameter \"%V\"", &value[3]);
735
+ return NGX_CONF_ERROR;
736
+ }
737
+
738
+ hv->always = 1;
739
+
634
740
  return NGX_CONF_OK;
635
741
  }