nginxtra 1.0.15.0 → 1.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/VERSION +1 -1
  2. data/bin/nginxtra +1 -1
  3. data/lib/nginxtra/action.rb +10 -0
  4. data/lib/nginxtra/actions/compile.rb +16 -2
  5. data/lib/nginxtra/actions/start.rb +18 -2
  6. data/lib/nginxtra/actions/status.rb +1 -10
  7. data/lib/nginxtra/actions/stop.rb +18 -0
  8. data/lib/nginxtra/cli.rb +12 -3
  9. data/lib/nginxtra/config.rb +10 -0
  10. data/src/nginx/CHANGES +311 -90
  11. data/src/nginx/CHANGES.ru +315 -88
  12. data/src/nginx/auto/lib/pcre/conf +22 -5
  13. data/src/nginx/auto/lib/pcre/make +1 -1
  14. data/src/nginx/auto/modules +14 -3
  15. data/src/nginx/auto/options +17 -3
  16. data/src/nginx/auto/os/freebsd +8 -0
  17. data/src/nginx/auto/os/linux +5 -4
  18. data/src/nginx/auto/os/solaris +2 -1
  19. data/src/nginx/auto/sources +10 -2
  20. data/src/nginx/auto/summary +2 -0
  21. data/src/nginx/auto/types/sizeof +2 -1
  22. data/src/nginx/auto/types/typedef +1 -1
  23. data/src/nginx/auto/types/uintptr_t +7 -4
  24. data/src/nginx/auto/unix +82 -21
  25. data/src/nginx/conf/fastcgi.conf +1 -0
  26. data/src/nginx/conf/fastcgi_params +1 -0
  27. data/src/nginx/conf/scgi_params +1 -0
  28. data/src/nginx/conf/uwsgi_params +1 -0
  29. data/src/nginx/man/nginx.8 +49 -49
  30. data/src/nginx/src/core/nginx.c +10 -12
  31. data/src/nginx/src/core/nginx.h +2 -2
  32. data/src/nginx/src/core/ngx_buf.c +9 -7
  33. data/src/nginx/src/core/ngx_buf.h +2 -2
  34. data/src/nginx/src/core/ngx_conf_file.c +4 -11
  35. data/src/nginx/src/core/ngx_conf_file.h +1 -1
  36. data/src/nginx/src/core/ngx_connection.c +52 -1
  37. data/src/nginx/src/core/ngx_connection.h +6 -0
  38. data/src/nginx/src/core/ngx_core.h +5 -0
  39. data/src/nginx/src/core/ngx_cycle.c +1 -1
  40. data/src/nginx/src/core/ngx_cycle.h +2 -2
  41. data/src/nginx/src/core/ngx_file.c +1 -1
  42. data/src/nginx/src/core/ngx_inet.c +11 -8
  43. data/src/nginx/src/core/ngx_murmurhash.h +1 -1
  44. data/src/nginx/src/core/ngx_open_file_cache.c +343 -38
  45. data/src/nginx/src/core/ngx_open_file_cache.h +10 -0
  46. data/src/nginx/src/core/ngx_output_chain.c +2 -1
  47. data/src/nginx/src/core/ngx_parse.h +0 -3
  48. data/src/nginx/src/core/ngx_rbtree.c +1 -2
  49. data/src/nginx/src/core/ngx_regex.c +263 -5
  50. data/src/nginx/src/core/ngx_regex.h +6 -2
  51. data/src/nginx/src/core/ngx_resolver.c +88 -21
  52. data/src/nginx/src/core/ngx_resolver.h +7 -8
  53. data/src/nginx/src/core/ngx_shmtx.c +69 -44
  54. data/src/nginx/src/core/ngx_shmtx.h +12 -1
  55. data/src/nginx/src/core/ngx_slab.c +3 -3
  56. data/src/nginx/src/core/ngx_slab.h +1 -1
  57. data/src/nginx/src/core/ngx_string.c +19 -16
  58. data/src/nginx/src/core/ngx_times.c +2 -2
  59. data/src/nginx/src/event/modules/ngx_epoll_module.c +2 -2
  60. data/src/nginx/src/event/modules/ngx_eventport_module.c +1 -1
  61. data/src/nginx/src/event/modules/ngx_kqueue_module.c +1 -1
  62. data/src/nginx/src/event/ngx_event.c +25 -17
  63. data/src/nginx/src/event/ngx_event_openssl.c +3 -1
  64. data/src/nginx/src/event/ngx_event_pipe.c +108 -85
  65. data/src/nginx/src/event/ngx_event_pipe.h +1 -2
  66. data/src/nginx/src/event/ngx_event_timer.c +2 -3
  67. data/src/nginx/src/http/modules/ngx_http_access_module.c +9 -4
  68. data/src/nginx/src/http/modules/ngx_http_browser_module.c +5 -3
  69. data/src/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -1
  70. data/src/nginx/src/http/modules/ngx_http_degradation_module.c +1 -1
  71. data/src/nginx/src/http/modules/ngx_http_fastcgi_module.c +144 -22
  72. data/src/nginx/src/http/modules/ngx_http_flv_module.c +8 -0
  73. data/src/nginx/src/http/modules/ngx_http_geo_module.c +3 -3
  74. data/src/nginx/src/http/modules/ngx_http_gzip_filter_module.c +20 -6
  75. data/src/nginx/src/http/modules/ngx_http_gzip_static_module.c +8 -0
  76. data/src/nginx/src/http/modules/ngx_http_headers_filter_module.c +23 -27
  77. data/src/nginx/src/http/modules/ngx_http_image_filter_module.c +1 -3
  78. data/src/nginx/src/http/modules/ngx_http_index_module.c +24 -0
  79. data/src/nginx/src/http/modules/ngx_http_limit_conn_module.c +747 -0
  80. data/src/nginx/src/http/modules/ngx_http_limit_req_module.c +289 -133
  81. data/src/nginx/src/http/modules/ngx_http_log_module.c +34 -6
  82. data/src/nginx/src/http/modules/ngx_http_memcached_module.c +19 -3
  83. data/src/nginx/src/http/modules/ngx_http_mp4_module.c +8 -0
  84. data/src/nginx/src/http/modules/ngx_http_proxy_module.c +1446 -239
  85. data/src/nginx/src/http/modules/ngx_http_realip_module.c +4 -10
  86. data/src/nginx/src/http/modules/ngx_http_scgi_module.c +90 -21
  87. data/src/nginx/src/http/modules/ngx_http_split_clients_module.c +8 -11
  88. data/src/nginx/src/http/modules/ngx_http_ssi_filter_module.c +16 -6
  89. data/src/nginx/src/http/modules/ngx_http_static_module.c +8 -0
  90. data/src/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +2 -2
  91. data/src/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +570 -0
  92. data/src/nginx/src/http/modules/ngx_http_userid_filter_module.c +1 -5
  93. data/src/nginx/src/http/modules/ngx_http_uwsgi_module.c +77 -26
  94. data/src/nginx/src/http/modules/ngx_http_xslt_filter_module.c +171 -37
  95. data/src/nginx/src/http/modules/perl/nginx.pm +2 -1
  96. data/src/nginx/src/http/modules/perl/nginx.xs +4 -0
  97. data/src/nginx/src/http/ngx_http.c +8 -1
  98. data/src/nginx/src/http/ngx_http.h +1 -0
  99. data/src/nginx/src/http/ngx_http_busy_lock.c +2 -2
  100. data/src/nginx/src/http/ngx_http_cache.h +12 -1
  101. data/src/nginx/src/http/ngx_http_copy_filter_module.c +4 -3
  102. data/src/nginx/src/http/ngx_http_core_module.c +303 -37
  103. data/src/nginx/src/http/ngx_http_core_module.h +15 -0
  104. data/src/nginx/src/http/ngx_http_file_cache.c +226 -52
  105. data/src/nginx/src/http/ngx_http_parse.c +69 -3
  106. data/src/nginx/src/http/ngx_http_postpone_filter_module.c +4 -4
  107. data/src/nginx/src/http/ngx_http_request.c +61 -27
  108. data/src/nginx/src/http/ngx_http_request.h +3 -3
  109. data/src/nginx/src/http/ngx_http_request_body.c +1 -1
  110. data/src/nginx/src/http/ngx_http_script.c +6 -0
  111. data/src/nginx/src/http/ngx_http_upstream.c +200 -47
  112. data/src/nginx/src/http/ngx_http_upstream.h +20 -1
  113. data/src/nginx/src/http/ngx_http_upstream_round_robin.c +22 -6
  114. data/src/nginx/src/http/ngx_http_upstream_round_robin.h +1 -0
  115. data/src/nginx/src/http/ngx_http_variables.c +123 -4
  116. data/src/nginx/src/mail/ngx_mail.c +13 -0
  117. data/src/nginx/src/mail/ngx_mail.h +12 -0
  118. data/src/nginx/src/mail/ngx_mail_core_module.c +100 -15
  119. data/src/nginx/src/os/unix/ngx_daemon.c +2 -1
  120. data/src/nginx/src/os/unix/ngx_darwin.h +3 -0
  121. data/src/nginx/src/os/unix/ngx_darwin_config.h +1 -0
  122. data/src/nginx/src/os/unix/ngx_darwin_init.c +30 -0
  123. data/src/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +11 -5
  124. data/src/nginx/src/os/unix/ngx_errno.h +5 -0
  125. data/src/nginx/src/os/unix/ngx_files.h +50 -1
  126. data/src/nginx/src/os/unix/ngx_freebsd.h +2 -1
  127. data/src/nginx/src/os/unix/ngx_freebsd_config.h +2 -0
  128. data/src/nginx/src/os/unix/ngx_freebsd_init.c +4 -3
  129. data/src/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +2 -2
  130. data/src/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +12 -6
  131. data/src/nginx/src/os/unix/ngx_gcc_atomic_sparc64.h +1 -1
  132. data/src/nginx/src/os/unix/ngx_linux_config.h +1 -0
  133. data/src/nginx/src/os/unix/ngx_linux_sendfile_chain.c +6 -4
  134. data/src/nginx/src/os/unix/ngx_os.h +0 -1
  135. data/src/nginx/src/os/unix/ngx_posix_config.h +3 -0
  136. data/src/nginx/src/os/unix/ngx_process.c +50 -11
  137. data/src/nginx/src/os/unix/ngx_process.h +1 -0
  138. data/src/nginx/src/os/unix/ngx_process_cycle.c +6 -15
  139. data/src/nginx/src/os/unix/ngx_readv_chain.c +8 -0
  140. data/src/nginx/src/os/unix/ngx_setaffinity.c +69 -0
  141. data/src/nginx/src/os/unix/ngx_setaffinity.h +23 -0
  142. data/src/nginx/src/os/unix/ngx_setproctitle.c +1 -1
  143. data/src/nginx/src/os/unix/ngx_solaris_config.h +2 -0
  144. data/src/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +11 -3
  145. data/src/nginx/src/os/unix/ngx_writev_chain.c +7 -3
  146. metadata +7 -4
  147. data/src/nginx/src/http/modules/ngx_http_limit_zone_module.c +0 -553
@@ -478,6 +478,7 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
478
478
  return NGX_OK;
479
479
  }
480
480
 
481
+
481
482
  ngx_int_t
482
483
  ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
483
484
  {
@@ -488,7 +489,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
488
489
 
489
490
  /*
490
491
  * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
491
- * from RFC 4492 section 5.1.1, or explicitely described curves over
492
+ * from RFC 4492 section 5.1.1, or explicitly described curves over
492
493
  * binary fields. OpenSSL only supports the "named curves", which provide
493
494
  * maximum interoperability.
494
495
  */
@@ -518,6 +519,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name)
518
519
  return NGX_OK;
519
520
  }
520
521
 
522
+
521
523
  ngx_int_t
522
524
  ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
523
525
  {
@@ -16,8 +16,6 @@ static ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p);
16
16
 
17
17
  static ngx_int_t ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p);
18
18
  static ngx_inline void ngx_event_pipe_remove_shadow_links(ngx_buf_t *buf);
19
- static ngx_inline void ngx_event_pipe_free_shadow_raw_buf(ngx_chain_t **free,
20
- ngx_buf_t *buf);
21
19
  static ngx_int_t ngx_event_pipe_drain_chains(ngx_event_pipe_t *p);
22
20
 
23
21
 
@@ -150,7 +148,7 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
150
148
  && p->upstream->read->pending_eof)
151
149
  {
152
150
  p->upstream->read->ready = 0;
153
- p->upstream->read->eof = 0;
151
+ p->upstream->read->eof = 1;
154
152
  p->upstream_eof = 1;
155
153
  p->read = 1;
156
154
 
@@ -393,8 +391,33 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
393
391
  cl->buf->file_last - cl->buf->file_pos);
394
392
  }
395
393
 
394
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0,
395
+ "pipe length: %O", p->length);
396
+
396
397
  #endif
397
398
 
399
+ if (p->free_raw_bufs && p->length != -1) {
400
+ cl = p->free_raw_bufs;
401
+
402
+ if (cl->buf->last - cl->buf->pos >= p->length) {
403
+
404
+ p->free_raw_bufs = cl->next;
405
+
406
+ /* STUB */ cl->buf->num = p->num++;
407
+
408
+ if (p->input_filter(p, cl->buf) == NGX_ERROR) {
409
+ return NGX_ABORT;
410
+ }
411
+
412
+ ngx_free_chain(p->pool, cl);
413
+ }
414
+ }
415
+
416
+ if (p->length == 0) {
417
+ p->upstream_done = 1;
418
+ p->read = 1;
419
+ }
420
+
398
421
  if ((p->upstream_eof || p->upstream_error) && p->free_raw_bufs) {
399
422
 
400
423
  /* STUB */ p->free_raw_bufs->buf->num = p->num++;
@@ -553,17 +576,13 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
553
576
  if (p->out) {
554
577
  cl = p->out;
555
578
 
556
- if (cl->buf->recycled
557
- && bsize + cl->buf->last - cl->buf->pos > p->busy_size)
558
- {
559
- flush = 1;
560
- break;
579
+ if (cl->buf->recycled) {
580
+ ngx_log_error(NGX_LOG_ALERT, p->log, 0,
581
+ "recycled buffer in pipe out chain");
561
582
  }
562
583
 
563
584
  p->out = p->out->next;
564
585
 
565
- ngx_event_pipe_free_shadow_raw_buf(&p->free_raw_bufs, cl->buf);
566
-
567
586
  } else if (!p->cacheable && p->in) {
568
587
  cl = p->in;
569
588
 
@@ -573,24 +592,13 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
573
592
  cl->buf->pos,
574
593
  cl->buf->last - cl->buf->pos);
575
594
 
576
- if (cl->buf->recycled
577
- && cl->buf->last_shadow
578
- && bsize + cl->buf->last - cl->buf->pos > p->busy_size)
579
- {
580
- if (!prev_last_shadow) {
581
- p->in = p->in->next;
582
-
583
- cl->next = NULL;
584
-
585
- if (out) {
586
- *ll = cl;
587
- } else {
588
- out = cl;
589
- }
595
+ if (cl->buf->recycled && prev_last_shadow) {
596
+ if (bsize + cl->buf->end - cl->buf->start > p->busy_size) {
597
+ flush = 1;
598
+ break;
590
599
  }
591
600
 
592
- flush = 1;
593
- break;
601
+ bsize += cl->buf->end - cl->buf->start;
594
602
  }
595
603
 
596
604
  prev_last_shadow = cl->buf->last_shadow;
@@ -601,10 +609,6 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
601
609
  break;
602
610
  }
603
611
 
604
- if (cl->buf->recycled) {
605
- bsize += cl->buf->last - cl->buf->pos;
606
- }
607
-
608
612
  cl->next = NULL;
609
613
 
610
614
  if (out) {
@@ -634,7 +638,7 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
634
638
 
635
639
  rc = p->output_filter(p->output_ctx, out);
636
640
 
637
- ngx_chain_update_chains(&p->free, &p->busy, &out, p->tag);
641
+ ngx_chain_update_chains(p->pool, &p->free, &p->busy, &out, p->tag);
638
642
 
639
643
  if (rc == NGX_ERROR) {
640
644
  p->downstream_error = 1;
@@ -678,9 +682,10 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
678
682
  static ngx_int_t
679
683
  ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p)
680
684
  {
681
- ssize_t size, bsize;
685
+ ssize_t size, bsize, n;
682
686
  ngx_buf_t *b;
683
- ngx_chain_t *cl, *tl, *next, *out, **ll, **last_free, fl;
687
+ ngx_uint_t prev_last_shadow;
688
+ ngx_chain_t *cl, *tl, *next, *out, **ll, **last_out, **last_free, fl;
684
689
 
685
690
  if (p->buf_to_file) {
686
691
  fl.buf = p->buf_to_file;
@@ -696,6 +701,7 @@ ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p)
696
701
  size = 0;
697
702
  cl = out;
698
703
  ll = NULL;
704
+ prev_last_shadow = 1;
699
705
 
700
706
  ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0,
701
707
  "pipe offset: %O", p->temp_file->offset);
@@ -703,16 +709,21 @@ ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p)
703
709
  do {
704
710
  bsize = cl->buf->last - cl->buf->pos;
705
711
 
706
- ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,
707
- "pipe buf %p, pos %p, size: %z",
708
- cl->buf->start, cl->buf->pos, bsize);
712
+ ngx_log_debug4(NGX_LOG_DEBUG_EVENT, p->log, 0,
713
+ "pipe buf ls:%d %p, pos %p, size: %z",
714
+ cl->buf->last_shadow, cl->buf->start,
715
+ cl->buf->pos, bsize);
709
716
 
710
- if ((size + bsize > p->temp_file_write_size)
711
- || (p->temp_file->offset + size + bsize > p->max_temp_file_size))
717
+ if (prev_last_shadow
718
+ && ((size + bsize > p->temp_file_write_size)
719
+ || (p->temp_file->offset + size + bsize
720
+ > p->max_temp_file_size)))
712
721
  {
713
722
  break;
714
723
  }
715
724
 
725
+ prev_last_shadow = cl->buf->last_shadow;
726
+
716
727
  size += bsize;
717
728
  ll = &cl->next;
718
729
  cl = cl->next;
@@ -739,42 +750,77 @@ ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p)
739
750
  p->last_in = &p->in;
740
751
  }
741
752
 
742
- if (ngx_write_chain_to_temp_file(p->temp_file, out) == NGX_ERROR) {
743
- return NGX_ABORT;
744
- }
753
+ n = ngx_write_chain_to_temp_file(p->temp_file, out);
745
754
 
746
- for (last_free = &p->free_raw_bufs;
747
- *last_free != NULL;
748
- last_free = &(*last_free)->next)
749
- {
750
- /* void */
755
+ if (n == NGX_ERROR) {
756
+ return NGX_ABORT;
751
757
  }
752
758
 
753
759
  if (p->buf_to_file) {
754
760
  p->temp_file->offset = p->buf_to_file->last - p->buf_to_file->pos;
761
+ n -= p->buf_to_file->last - p->buf_to_file->pos;
755
762
  p->buf_to_file = NULL;
756
763
  out = out->next;
757
764
  }
758
765
 
759
- for (cl = out; cl; cl = next) {
760
- next = cl->next;
761
- cl->next = NULL;
766
+ if (n > 0) {
767
+ /* update previous buffer or add new buffer */
768
+
769
+ if (p->out) {
770
+ for (cl = p->out; cl->next; cl = cl->next) { /* void */ }
771
+
772
+ b = cl->buf;
773
+
774
+ if (b->file_last == p->temp_file->offset) {
775
+ p->temp_file->offset += n;
776
+ b->file_last = p->temp_file->offset;
777
+ goto free;
778
+ }
779
+
780
+ last_out = &cl->next;
781
+
782
+ } else {
783
+ last_out = &p->out;
784
+ }
785
+
786
+ cl = ngx_chain_get_free_buf(p->pool, &p->free);
787
+ if (cl == NULL) {
788
+ return NGX_ABORT;
789
+ }
762
790
 
763
791
  b = cl->buf;
792
+
793
+ ngx_memzero(b, sizeof(ngx_buf_t));
794
+
795
+ b->tag = p->tag;
796
+
764
797
  b->file = &p->temp_file->file;
765
798
  b->file_pos = p->temp_file->offset;
766
- p->temp_file->offset += b->last - b->pos;
799
+ p->temp_file->offset += n;
767
800
  b->file_last = p->temp_file->offset;
768
801
 
769
802
  b->in_file = 1;
770
803
  b->temp_file = 1;
771
804
 
772
- if (p->out) {
773
- *p->last_out = cl;
774
- } else {
775
- p->out = cl;
776
- }
777
- p->last_out = &cl->next;
805
+ *last_out = cl;
806
+ }
807
+
808
+ free:
809
+
810
+ for (last_free = &p->free_raw_bufs;
811
+ *last_free != NULL;
812
+ last_free = &(*last_free)->next)
813
+ {
814
+ /* void */
815
+ }
816
+
817
+ for (cl = out; cl; cl = next) {
818
+ next = cl->next;
819
+
820
+ cl->next = p->free;
821
+ p->free = cl;
822
+
823
+ b = cl->buf;
778
824
 
779
825
  if (b->last_shadow) {
780
826
 
@@ -849,6 +895,12 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
849
895
  }
850
896
  p->last_in = &cl->next;
851
897
 
898
+ if (p->length == -1) {
899
+ return NGX_OK;
900
+ }
901
+
902
+ p->length -= b->last - b->pos;
903
+
852
904
  return NGX_OK;
853
905
  }
854
906
 
@@ -884,35 +936,6 @@ ngx_event_pipe_remove_shadow_links(ngx_buf_t *buf)
884
936
  }
885
937
 
886
938
 
887
- static ngx_inline void
888
- ngx_event_pipe_free_shadow_raw_buf(ngx_chain_t **free, ngx_buf_t *buf)
889
- {
890
- ngx_buf_t *s;
891
- ngx_chain_t *cl, **ll;
892
-
893
- if (buf->shadow == NULL) {
894
- return;
895
- }
896
-
897
- for (s = buf->shadow; !s->last_shadow; s = s->shadow) { /* void */ }
898
-
899
- ll = free;
900
-
901
- for (cl = *free; cl; cl = cl->next) {
902
- if (cl->buf == s) {
903
- *ll = cl->next;
904
- break;
905
- }
906
-
907
- if (cl->buf->shadow) {
908
- break;
909
- }
910
-
911
- ll = &cl->next;
912
- }
913
- }
914
-
915
-
916
939
  ngx_int_t
917
940
  ngx_event_pipe_add_free_buf(ngx_event_pipe_t *p, ngx_buf_t *b)
918
941
  {
@@ -31,8 +31,6 @@ struct ngx_event_pipe_s {
31
31
  ngx_chain_t **last_in;
32
32
 
33
33
  ngx_chain_t *out;
34
- ngx_chain_t **last_out;
35
-
36
34
  ngx_chain_t *free;
37
35
  ngx_chain_t *busy;
38
36
 
@@ -66,6 +64,7 @@ struct ngx_event_pipe_s {
66
64
  ssize_t busy_size;
67
65
 
68
66
  off_t read_length;
67
+ off_t length;
69
68
 
70
69
  off_t max_temp_file_size;
71
70
  ssize_t temp_file_write_size;
@@ -67,7 +67,7 @@ ngx_event_find_timer(void)
67
67
 
68
68
  ngx_mutex_unlock(ngx_event_timer_mutex);
69
69
 
70
- timer = (ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_msec;
70
+ timer = (ngx_msec_int_t) (node->key - ngx_current_msec);
71
71
 
72
72
  return (ngx_msec_t) (timer > 0 ? timer : 0);
73
73
  }
@@ -95,8 +95,7 @@ ngx_event_expire_timers(void)
95
95
 
96
96
  /* node->key <= ngx_current_time */
97
97
 
98
- if ((ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_msec <= 0)
99
- {
98
+ if ((ngx_msec_int_t) (node->key - ngx_current_msec) <= 0) {
100
99
  ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
101
100
 
102
101
  #if (NGX_THREADS)
@@ -351,14 +351,19 @@ ngx_http_access_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
351
351
  ngx_http_access_loc_conf_t *prev = parent;
352
352
  ngx_http_access_loc_conf_t *conf = child;
353
353
 
354
- if (conf->rules == NULL) {
354
+ #if (NGX_HAVE_INET6)
355
+
356
+ if (conf->rules == NULL && conf->rules6 == NULL) {
355
357
  conf->rules = prev->rules;
358
+ conf->rules6 = prev->rules6;
356
359
  }
357
360
 
358
- #if (NGX_HAVE_INET6)
359
- if (conf->rules6 == NULL) {
360
- conf->rules6 = prev->rules6;
361
+ #else
362
+
363
+ if (conf->rules == NULL) {
364
+ conf->rules = prev->rules;
361
365
  }
366
+
362
367
  #endif
363
368
 
364
369
  return NGX_CONF_OK;
@@ -458,10 +458,11 @@ ngx_http_browser_merge_conf(ngx_conf_t *cf, void *parent, void *child)
458
458
  * with a real skip value. The zero value means Opera.
459
459
  */
460
460
 
461
- if (conf->modern_browsers == NULL) {
461
+ if (conf->modern_browsers == NULL && conf->modern_unlisted_browsers == 0) {
462
462
  conf->modern_browsers = prev->modern_browsers;
463
+ conf->modern_unlisted_browsers = prev->modern_unlisted_browsers;
463
464
 
464
- } else {
465
+ } else if (conf->modern_browsers != NULL) {
465
466
  browsers = conf->modern_browsers->elts;
466
467
 
467
468
  for (i = 0; i < conf->modern_browsers->nelts; i++) {
@@ -501,8 +502,9 @@ found:
501
502
  }
502
503
  }
503
504
 
504
- if (conf->ancient_browsers == NULL) {
505
+ if (conf->ancient_browsers == NULL && conf->netscape4 == 0) {
505
506
  conf->ancient_browsers = prev->ancient_browsers;
507
+ conf->netscape4 = prev->netscape4;
506
508
  }
507
509
 
508
510
  if (conf->modern_browser_value == NULL) {
@@ -222,7 +222,7 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
222
222
 
223
223
  rc = ngx_http_next_body_filter(r, out);
224
224
 
225
- ngx_chain_update_chains(&ctx->free, &ctx->busy, &out,
225
+ ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
226
226
  (ngx_buf_tag_t) &ngx_http_chunked_filter_module);
227
227
 
228
228
  return rc;
@@ -126,7 +126,7 @@ ngx_http_degraded(ngx_http_request_t *r)
126
126
  * ELF/i386 is loaded at 0x08000000, 128M
127
127
  * ELF/amd64 is loaded at 0x00400000, 4M
128
128
  *
129
- * use a function address to substract the loading address
129
+ * use a function address to subtract the loading address
130
130
  */
131
131
 
132
132
  sbrk_size = (size_t) sbrk(0) - ((uintptr_t) ngx_palloc & ~0x3FFFFF);
@@ -27,6 +27,8 @@ typedef struct {
27
27
  ngx_hash_t headers_hash;
28
28
  ngx_uint_t header_params;
29
29
 
30
+ ngx_flag_t keep_conn;
31
+
30
32
  #if (NGX_HTTP_CACHE)
31
33
  ngx_http_complex_value_t cache_key;
32
34
  #endif
@@ -78,6 +80,8 @@ typedef struct {
78
80
 
79
81
  #define NGX_HTTP_FASTCGI_RESPONDER 1
80
82
 
83
+ #define NGX_HTTP_FASTCGI_KEEP_CONN 1
84
+
81
85
  #define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1
82
86
  #define NGX_HTTP_FASTCGI_ABORT_REQUEST 2
83
87
  #define NGX_HTTP_FASTCGI_END_REQUEST 3
@@ -131,6 +135,7 @@ static ngx_int_t ngx_http_fastcgi_create_key(ngx_http_request_t *r);
131
135
  static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r);
132
136
  static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
133
137
  static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
138
+ static ngx_int_t ngx_http_fastcgi_input_filter_init(void *data);
134
139
  static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
135
140
  ngx_buf_t *buf);
136
141
  static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
@@ -376,6 +381,20 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
376
381
  offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_methods),
377
382
  &ngx_http_upstream_cache_method_mask },
378
383
 
384
+ { ngx_string("fastcgi_cache_lock"),
385
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
386
+ ngx_conf_set_flag_slot,
387
+ NGX_HTTP_LOC_CONF_OFFSET,
388
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock),
389
+ NULL },
390
+
391
+ { ngx_string("fastcgi_cache_lock_timeout"),
392
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
393
+ ngx_conf_set_msec_slot,
394
+ NGX_HTTP_LOC_CONF_OFFSET,
395
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout),
396
+ NULL },
397
+
379
398
  #endif
380
399
 
381
400
  { ngx_string("fastcgi_temp_path"),
@@ -407,8 +426,8 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
407
426
  &ngx_http_fastcgi_next_upstream_masks },
408
427
 
409
428
  { ngx_string("fastcgi_param"),
410
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
411
- ngx_conf_set_keyval_slot,
429
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
430
+ ngx_http_upstream_param_set_slot,
412
431
  NGX_HTTP_LOC_CONF_OFFSET,
413
432
  offsetof(ngx_http_fastcgi_loc_conf_t, params_source),
414
433
  NULL },
@@ -441,6 +460,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
441
460
  offsetof(ngx_http_fastcgi_loc_conf_t, catch_stderr),
442
461
  NULL },
443
462
 
463
+ { ngx_string("fastcgi_keep_conn"),
464
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
465
+ ngx_conf_set_flag_slot,
466
+ NGX_HTTP_LOC_CONF_OFFSET,
467
+ offsetof(ngx_http_fastcgi_loc_conf_t, keep_conn),
468
+ NULL },
469
+
444
470
  ngx_null_command
445
471
  };
446
472
 
@@ -604,6 +630,8 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
604
630
  u->pipe->input_filter = ngx_http_fastcgi_input_filter;
605
631
  u->pipe->input_ctx = r;
606
632
 
633
+ u->input_filter_init = ngx_http_fastcgi_input_filter_init;
634
+
607
635
  rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
608
636
 
609
637
  if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -695,7 +723,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
695
723
  u_char ch, *pos, *lowcase_key;
696
724
  size_t size, len, key_len, val_len, padding,
697
725
  allocated;
698
- ngx_uint_t i, n, next, hash, header_params;
726
+ ngx_uint_t i, n, next, hash, skip_empty, header_params;
699
727
  ngx_buf_t *b;
700
728
  ngx_chain_t *cl, *body;
701
729
  ngx_list_part_t *part;
@@ -726,11 +754,18 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
726
754
  lcode = *(ngx_http_script_len_code_pt *) le.ip;
727
755
  key_len = lcode(&le);
728
756
 
757
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
758
+ skip_empty = lcode(&le);
759
+
729
760
  for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
730
761
  lcode = *(ngx_http_script_len_code_pt *) le.ip;
731
762
  }
732
763
  le.ip += sizeof(uintptr_t);
733
764
 
765
+ if (skip_empty && val_len == 0) {
766
+ continue;
767
+ }
768
+
734
769
  len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
735
770
  }
736
771
  }
@@ -845,6 +880,9 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
845
880
 
846
881
  cl->buf = b;
847
882
 
883
+ ngx_http_fastcgi_request_start.br.flags =
884
+ flcf->keep_conn ? NGX_HTTP_FASTCGI_KEEP_CONN : 0;
885
+
848
886
  ngx_memcpy(b->pos, &ngx_http_fastcgi_request_start,
849
887
  sizeof(ngx_http_fastcgi_request_start_t));
850
888
 
@@ -877,11 +915,28 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
877
915
  lcode = *(ngx_http_script_len_code_pt *) le.ip;
878
916
  key_len = (u_char) lcode(&le);
879
917
 
918
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
919
+ skip_empty = lcode(&le);
920
+
880
921
  for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
881
922
  lcode = *(ngx_http_script_len_code_pt *) le.ip;
882
923
  }
883
924
  le.ip += sizeof(uintptr_t);
884
925
 
926
+ if (skip_empty && val_len == 0) {
927
+ e.skip = 1;
928
+
929
+ while (*(uintptr_t *) e.ip) {
930
+ code = *(ngx_http_script_code_pt *) e.ip;
931
+ code((ngx_http_script_engine_t *) &e);
932
+ }
933
+ e.ip += sizeof(uintptr_t);
934
+
935
+ e.skip = 0;
936
+
937
+ continue;
938
+ }
939
+
885
940
  *e.pos++ = (u_char) key_len;
886
941
 
887
942
  if (val_len > 127) {
@@ -1199,7 +1254,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
1199
1254
 
1200
1255
  if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
1201
1256
  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1202
- "upstream closed prematurely FastCGI stdout");
1257
+ "upstream prematurely closed FastCGI stdout");
1203
1258
 
1204
1259
  return NGX_HTTP_UPSTREAM_INVALID_HEADER;
1205
1260
  }
@@ -1577,15 +1632,31 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
1577
1632
  }
1578
1633
 
1579
1634
 
1635
+ static ngx_int_t
1636
+ ngx_http_fastcgi_input_filter_init(void *data)
1637
+ {
1638
+ ngx_http_request_t *r = data;
1639
+ ngx_http_fastcgi_loc_conf_t *flcf;
1640
+
1641
+ flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
1642
+
1643
+ r->upstream->pipe->length = flcf->keep_conn ?
1644
+ (off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
1645
+
1646
+ return NGX_OK;
1647
+ }
1648
+
1649
+
1580
1650
  static ngx_int_t
1581
1651
  ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1582
1652
  {
1583
- u_char *m, *msg;
1584
- ngx_int_t rc;
1585
- ngx_buf_t *b, **prev;
1586
- ngx_chain_t *cl;
1587
- ngx_http_request_t *r;
1588
- ngx_http_fastcgi_ctx_t *f;
1653
+ u_char *m, *msg;
1654
+ ngx_int_t rc;
1655
+ ngx_buf_t *b, **prev;
1656
+ ngx_chain_t *cl;
1657
+ ngx_http_request_t *r;
1658
+ ngx_http_fastcgi_ctx_t *f;
1659
+ ngx_http_fastcgi_loc_conf_t *flcf;
1589
1660
 
1590
1661
  if (buf->pos == buf->last) {
1591
1662
  return NGX_OK;
@@ -1593,6 +1664,7 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1593
1664
 
1594
1665
  r = p->input_ctx;
1595
1666
  f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
1667
+ flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
1596
1668
 
1597
1669
  b = NULL;
1598
1670
  prev = &buf->shadow;
@@ -1615,7 +1687,10 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1615
1687
 
1616
1688
  if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
1617
1689
  f->state = ngx_http_fastcgi_st_version;
1618
- p->upstream_done = 1;
1690
+
1691
+ if (!flcf->keep_conn) {
1692
+ p->upstream_done = 1;
1693
+ }
1619
1694
 
1620
1695
  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
1621
1696
  "http fastcgi closed stdout");
@@ -1627,6 +1702,10 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1627
1702
  f->state = ngx_http_fastcgi_st_version;
1628
1703
  p->upstream_done = 1;
1629
1704
 
1705
+ if (flcf->keep_conn) {
1706
+ r->upstream->keepalive = 1;
1707
+ }
1708
+
1630
1709
  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
1631
1710
  "http fastcgi sent end request");
1632
1711
 
@@ -1787,6 +1866,23 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1787
1866
 
1788
1867
  }
1789
1868
 
1869
+ if (flcf->keep_conn) {
1870
+
1871
+ /* set p->length, minimal amount of data we want to see */
1872
+
1873
+ if (f->state < ngx_http_fastcgi_st_data) {
1874
+ p->length = 1;
1875
+
1876
+ } else if (f->state == ngx_http_fastcgi_st_padding) {
1877
+ p->length = f->padding;
1878
+
1879
+ } else {
1880
+ /* ngx_http_fastcgi_st_data */
1881
+
1882
+ p->length = f->length;
1883
+ }
1884
+ }
1885
+
1790
1886
  if (b) {
1791
1887
  b->shadow = buf;
1792
1888
  b->last_shadow = 1;
@@ -2005,6 +2101,8 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
2005
2101
  conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
2006
2102
  conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
2007
2103
  conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
2104
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
2105
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
2008
2106
  #endif
2009
2107
 
2010
2108
  conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -2017,6 +2115,8 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
2017
2115
 
2018
2116
  conf->catch_stderr = NGX_CONF_UNSET_PTR;
2019
2117
 
2118
+ conf->keep_conn = NGX_CONF_UNSET;
2119
+
2020
2120
  ngx_str_set(&conf->upstream.module, "fastcgi");
2021
2121
 
2022
2122
  return conf;
@@ -2098,8 +2198,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2098
2198
 
2099
2199
  if (conf->upstream.busy_buffers_size < size) {
2100
2200
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2101
- "\"fastcgi_busy_buffers_size\" must be equal or bigger than "
2102
- "maximum of the value of \"fastcgi_buffer_size\" and "
2201
+ "\"fastcgi_busy_buffers_size\" must be equal to or greater than "
2202
+ "the maximum of the value of \"fastcgi_buffer_size\" and "
2103
2203
  "one of the \"fastcgi_buffers\"");
2104
2204
 
2105
2205
  return NGX_CONF_ERROR;
@@ -2129,8 +2229,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2129
2229
 
2130
2230
  if (conf->upstream.temp_file_write_size < size) {
2131
2231
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2132
- "\"fastcgi_temp_file_write_size\" must be equal or bigger than "
2133
- "maximum of the value of \"fastcgi_buffer_size\" and "
2232
+ "\"fastcgi_temp_file_write_size\" must be equal to or greater "
2233
+ "than the maximum of the value of \"fastcgi_buffer_size\" and "
2134
2234
  "one of the \"fastcgi_buffers\"");
2135
2235
 
2136
2236
  return NGX_CONF_ERROR;
@@ -2153,8 +2253,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2153
2253
  {
2154
2254
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2155
2255
  "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
2156
- "the temporary files usage or must be equal or bigger than "
2157
- "maximum of the value of \"fastcgi_buffer_size\" and "
2256
+ "temporary files usage or must be equal to or greater than "
2257
+ "the maximum of the value of \"fastcgi_buffer_size\" and "
2158
2258
  "one of the \"fastcgi_buffers\"");
2159
2259
 
2160
2260
  return NGX_CONF_ERROR;
@@ -2244,6 +2344,12 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2244
2344
  conf->cache_key = prev->cache_key;
2245
2345
  }
2246
2346
 
2347
+ ngx_conf_merge_value(conf->upstream.cache_lock,
2348
+ prev->upstream.cache_lock, 0);
2349
+
2350
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
2351
+ prev->upstream.cache_lock_timeout, 5000);
2352
+
2247
2353
  #endif
2248
2354
 
2249
2355
  ngx_conf_merge_value(conf->upstream.pass_request_headers,
@@ -2256,6 +2362,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2256
2362
 
2257
2363
  ngx_conf_merge_ptr_value(conf->catch_stderr, prev->catch_stderr, NULL);
2258
2364
 
2365
+ ngx_conf_merge_value(conf->keep_conn, prev->keep_conn, 0);
2366
+
2259
2367
 
2260
2368
  ngx_conf_merge_str_value(conf->index, prev->index, "");
2261
2369
 
@@ -2313,9 +2421,9 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
2313
2421
  #if (NGX_HTTP_CACHE)
2314
2422
  ngx_array_t params_merged;
2315
2423
  #endif
2316
- ngx_keyval_t *src;
2317
2424
  ngx_hash_key_t *hk;
2318
2425
  ngx_hash_init_t hash;
2426
+ ngx_http_upstream_param_t *src;
2319
2427
  ngx_http_script_compile_t sc;
2320
2428
  ngx_http_script_copy_code_t *copy;
2321
2429
 
@@ -2324,7 +2432,8 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
2324
2432
 
2325
2433
  if (prev->headers_hash.buckets
2326
2434
  #if (NGX_HTTP_CACHE)
2327
- && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))
2435
+ && ((conf->upstream.cache == NULL)
2436
+ == (prev->upstream.cache == NULL))
2328
2437
  #endif
2329
2438
  )
2330
2439
  {
@@ -2376,9 +2485,11 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
2376
2485
  #if (NGX_HTTP_CACHE)
2377
2486
 
2378
2487
  if (conf->upstream.cache) {
2379
- ngx_keyval_t *h, *s;
2488
+ ngx_keyval_t *h;
2489
+ ngx_http_upstream_param_t *s;
2380
2490
 
2381
- if (ngx_array_init(&params_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
2491
+ if (ngx_array_init(&params_merged, cf->temp_pool, 4,
2492
+ sizeof(ngx_http_upstream_param_t))
2382
2493
  != NGX_OK)
2383
2494
  {
2384
2495
  return NGX_ERROR;
@@ -2412,7 +2523,9 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
2412
2523
  return NGX_ERROR;
2413
2524
  }
2414
2525
 
2415
- *s = *h;
2526
+ s->key = h->key;
2527
+ s->value = h->value;
2528
+ s->skip_empty = 0;
2416
2529
 
2417
2530
  next:
2418
2531
 
@@ -2454,6 +2567,15 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
2454
2567
  copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
2455
2568
  copy->len = src[i].key.len;
2456
2569
 
2570
+ copy = ngx_array_push_n(conf->params_len,
2571
+ sizeof(ngx_http_script_copy_code_t));
2572
+ if (copy == NULL) {
2573
+ return NGX_ERROR;
2574
+ }
2575
+
2576
+ copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
2577
+ copy->len = src[i].skip_empty;
2578
+
2457
2579
 
2458
2580
  size = (sizeof(ngx_http_script_copy_code_t)
2459
2581
  + src[i].key.len + sizeof(uintptr_t) - 1)