unicorn 4.9.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +5 -0
  3. data/.manifest +3 -10
  4. data/Application_Timeouts +3 -3
  5. data/DESIGN +2 -4
  6. data/Documentation/unicorn.1.txt +8 -5
  7. data/Documentation/unicorn_rails.1.txt +2 -2
  8. data/FAQ +17 -8
  9. data/GIT-VERSION-FILE +1 -1
  10. data/GIT-VERSION-GEN +1 -1
  11. data/GNUmakefile +6 -1
  12. data/ISSUES +20 -28
  13. data/KNOWN_ISSUES +9 -9
  14. data/LATEST +28 -29
  15. data/Links +14 -17
  16. data/NEWS +159 -0
  17. data/PHILOSOPHY +0 -6
  18. data/README +22 -17
  19. data/SIGNALS +1 -1
  20. data/Sandbox +4 -4
  21. data/TUNING +11 -8
  22. data/bin/unicorn +1 -1
  23. data/bin/unicorn_rails +1 -1
  24. data/examples/nginx.conf +10 -11
  25. data/examples/unicorn.conf.rb +1 -4
  26. data/examples/unicorn.socket +11 -0
  27. data/examples/unicorn@.service +26 -0
  28. data/ext/unicorn_http/extconf.rb +1 -0
  29. data/ext/unicorn_http/httpdate.c +1 -1
  30. data/ext/unicorn_http/unicorn_http.c +267 -334
  31. data/ext/unicorn_http/unicorn_http.rl +89 -156
  32. data/lib/unicorn/configurator.rb +17 -31
  33. data/lib/unicorn/const.rb +2 -25
  34. data/lib/unicorn/http_request.rb +22 -33
  35. data/lib/unicorn/http_response.rb +13 -31
  36. data/lib/unicorn/http_server.rb +129 -122
  37. data/lib/unicorn/socket_helper.rb +36 -72
  38. data/lib/unicorn/stream_input.rb +3 -3
  39. data/lib/unicorn/tmpio.rb +0 -5
  40. data/lib/unicorn/util.rb +2 -1
  41. data/lib/unicorn/version.rb +1 -1
  42. data/lib/unicorn/worker.rb +3 -15
  43. data/lib/unicorn.rb +10 -18
  44. data/man/man1/unicorn.1 +7 -5
  45. data/man/man1/unicorn_rails.1 +2 -2
  46. data/t/hijack.ru +2 -1
  47. data/t/t0200-rack-hijack.sh +5 -2
  48. data/test/exec/test_exec.rb +52 -0
  49. data/test/test_helper.rb +3 -2
  50. data/test/unit/test_http_parser_ng.rb +16 -114
  51. data/test/unit/test_response.rb +28 -16
  52. data/test/unit/test_socket_helper.rb +1 -1
  53. data/unicorn.gemspec +10 -1
  54. metadata +13 -23
  55. data/examples/git.ru +0 -13
  56. data/lib/unicorn/app/exec_cgi.rb +0 -154
  57. data/lib/unicorn/app/inetd.rb +0 -109
  58. data/lib/unicorn/ssl_client.rb +0 -11
  59. data/lib/unicorn/ssl_configurator.rb +0 -104
  60. data/lib/unicorn/ssl_server.rb +0 -42
  61. data/t/t0016-trust-x-forwarded-false.sh +0 -30
  62. data/t/t0017-trust-x-forwarded-true.sh +0 -30
  63. data/test/unit/test_http_parser_xftrust.rb +0 -38
  64. data/test/unit/test_sni_hostnames.rb +0 -47
@@ -25,86 +25,32 @@ void init_unicorn_httpdate(void);
25
25
  #define UH_FL_KAVERSION 0x80
26
26
  #define UH_FL_HASHEADER 0x100
27
27
  #define UH_FL_TO_CLEAR 0x200
28
+ #define UH_FL_RESSTART 0x400 /* for check_client_connection */
28
29
 
29
30
  /* all of these flags need to be set for keepalive to be supported */
30
31
  #define UH_FL_KEEPALIVE (UH_FL_KAVERSION | UH_FL_REQEOF | UH_FL_HASHEADER)
31
32
 
32
- /*
33
- * whether or not to trust X-Forwarded-Proto and X-Forwarded-SSL when
34
- * setting rack.url_scheme
35
- */
36
- static VALUE trust_x_forward = Qtrue;
37
-
38
- static unsigned long keepalive_requests = 100; /* same as nginx */
39
-
40
- /*
41
- * Returns the maximum number of keepalive requests a client may make
42
- * before the parser refuses to continue.
43
- */
44
- static VALUE ka_req(VALUE self)
45
- {
46
- return ULONG2NUM(keepalive_requests);
47
- }
48
-
49
- /*
50
- * Sets the maximum number of keepalive requests a client may make.
51
- * A special value of +nil+ causes this to be the maximum value
52
- * possible (this is architecture-dependent).
53
- */
54
- static VALUE set_ka_req(VALUE self, VALUE val)
55
- {
56
- keepalive_requests = NIL_P(val) ? ULONG_MAX : NUM2ULONG(val);
57
-
58
- return ka_req(self);
59
- }
60
-
61
- /*
62
- * Sets whether or not the parser will trust X-Forwarded-Proto and
63
- * X-Forwarded-SSL headers and set "rack.url_scheme" to "https" accordingly.
64
- * Rainbows!/Zbatery installations facing untrusted clients directly
65
- * should set this to +false+
66
- */
67
- static VALUE set_xftrust(VALUE self, VALUE val)
68
- {
69
- if (Qtrue == val || Qfalse == val)
70
- trust_x_forward = val;
71
- else
72
- rb_raise(rb_eTypeError, "must be true or false");
73
-
74
- return val;
75
- }
76
-
77
- /*
78
- * returns whether or not the parser will trust X-Forwarded-Proto and
79
- * X-Forwarded-SSL headers and set "rack.url_scheme" to "https" accordingly
80
- */
81
- static VALUE xftrust(VALUE self)
82
- {
83
- return trust_x_forward;
84
- }
85
-
86
- static size_t MAX_HEADER_LEN = 1024 * (80 + 32); /* same as Mongrel */
33
+ static unsigned int MAX_HEADER_LEN = 1024 * (80 + 32); /* same as Mongrel */
87
34
 
88
35
  /* this is only intended for use with Rainbows! */
89
36
  static VALUE set_maxhdrlen(VALUE self, VALUE len)
90
37
  {
91
- return SIZET2NUM(MAX_HEADER_LEN = NUM2SIZET(len));
38
+ return UINT2NUM(MAX_HEADER_LEN = NUM2UINT(len));
92
39
  }
93
40
 
94
- /* keep this small for Rainbows! since every client has one */
41
+ /* keep this small for other servers (e.g. yahns) since every client has one */
95
42
  struct http_parser {
96
43
  int cs; /* Ragel internal state */
97
44
  unsigned int flags;
98
- unsigned long nr_requests;
99
- size_t mark;
100
- size_t offset;
45
+ unsigned int mark;
46
+ unsigned int offset;
101
47
  union { /* these 2 fields don't nest */
102
- size_t field;
103
- size_t query;
48
+ unsigned int field;
49
+ unsigned int query;
104
50
  } start;
105
51
  union {
106
- size_t field_len; /* only used during header processing */
107
- size_t dest_offset; /* only used during body processing */
52
+ unsigned int field_len; /* only used during header processing */
53
+ unsigned int dest_offset; /* only used during body processing */
108
54
  } s;
109
55
  VALUE buf;
110
56
  VALUE env;
@@ -115,7 +61,19 @@ struct http_parser {
115
61
  } len;
116
62
  };
117
63
 
118
- static ID id_clear, id_set_backtrace, id_response_start_sent;
64
+ static ID id_set_backtrace;
65
+
66
+ #ifdef HAVE_RB_HASH_CLEAR /* Ruby >= 2.0 */
67
+ # define my_hash_clear(h) (void)rb_hash_clear(h)
68
+ #else /* !HAVE_RB_HASH_CLEAR - Ruby <= 1.9.3 */
69
+
70
+ static ID id_clear;
71
+
72
+ static void my_hash_clear(VALUE h)
73
+ {
74
+ rb_funcall(h, id_clear, 0);
75
+ }
76
+ #endif /* HAVE_RB_HASH_CLEAR */
119
77
 
120
78
  static void finalize_header(struct http_parser *hp);
121
79
 
@@ -124,13 +82,25 @@ static void parser_raise(VALUE klass, const char *msg)
124
82
  VALUE exc = rb_exc_new2(klass, msg);
125
83
  VALUE bt = rb_ary_new();
126
84
 
127
- rb_funcall(exc, id_set_backtrace, 1, bt);
128
- rb_exc_raise(exc);
85
+ rb_funcall(exc, id_set_backtrace, 1, bt);
86
+ rb_exc_raise(exc);
87
+ }
88
+
89
+ static inline unsigned int ulong2uint(unsigned long n)
90
+ {
91
+ unsigned int i = (unsigned int)n;
92
+
93
+ if (sizeof(unsigned int) != sizeof(unsigned long)) {
94
+ if ((unsigned long)i != n) {
95
+ rb_raise(rb_eRangeError, "too large to be 32-bit uint: %lu", n);
96
+ }
97
+ }
98
+ return i;
129
99
  }
130
100
 
131
101
  #define REMAINING (unsigned long)(pe - p)
132
- #define LEN(AT, FPC) (FPC - buffer - hp->AT)
133
- #define MARK(M,FPC) (hp->M = (FPC) - buffer)
102
+ #define LEN(AT, FPC) (ulong2uint(FPC - buffer) - hp->AT)
103
+ #define MARK(M,FPC) (hp->M = ulong2uint((FPC) - buffer))
134
104
  #define PTR_TO(F) (buffer + hp->F)
135
105
  #define STR_NEW(M,FPC) rb_str_new(PTR_TO(M), LEN(M, FPC))
136
106
  #define STRIPPED_STR_NEW(M,FPC) stripped_str_new(PTR_TO(M), LEN(M, FPC))
@@ -466,7 +436,7 @@ http_parser_execute(struct http_parser *hp, char *buffer, size_t len)
466
436
  post_exec: /* "_out:" also goes here */
467
437
  if (hp->cs != http_parser_error)
468
438
  hp->cs = cs;
469
- hp->offset = p - buffer;
439
+ hp->offset = ulong2uint(p - buffer);
470
440
 
471
441
  assert(p <= pe && "buffer overflow after parsing execute");
472
442
  assert(hp->offset <= len && "offset longer than length");
@@ -491,26 +461,29 @@ static void set_url_scheme(VALUE env, VALUE *server_port)
491
461
  VALUE scheme = rb_hash_aref(env, g_rack_url_scheme);
492
462
 
493
463
  if (NIL_P(scheme)) {
494
- if (trust_x_forward == Qfalse) {
495
- scheme = g_http;
464
+ /*
465
+ * would anybody be horribly opposed to removing the X-Forwarded-SSL
466
+ * and X-Forwarded-Proto handling from this parser? We've had it
467
+ * forever and nobody has said anything against it, either.
468
+ * Anyways, please send comments to our public mailing list:
469
+ * unicorn-public@bogomips.org (no HTML mail, no subscription necessary)
470
+ */
471
+ scheme = rb_hash_aref(env, g_http_x_forwarded_ssl);
472
+ if (!NIL_P(scheme) && STR_CSTR_EQ(scheme, "on")) {
473
+ *server_port = g_port_443;
474
+ scheme = g_https;
496
475
  } else {
497
- scheme = rb_hash_aref(env, g_http_x_forwarded_ssl);
498
- if (!NIL_P(scheme) && STR_CSTR_EQ(scheme, "on")) {
499
- *server_port = g_port_443;
500
- scheme = g_https;
476
+ scheme = rb_hash_aref(env, g_http_x_forwarded_proto);
477
+ if (NIL_P(scheme)) {
478
+ scheme = g_http;
501
479
  } else {
502
- scheme = rb_hash_aref(env, g_http_x_forwarded_proto);
503
- if (NIL_P(scheme)) {
504
- scheme = g_http;
480
+ long len = RSTRING_LEN(scheme);
481
+ if (len >= 5 && !memcmp(RSTRING_PTR(scheme), "https", 5)) {
482
+ if (len != 5)
483
+ scheme = g_https;
484
+ *server_port = g_port_443;
505
485
  } else {
506
- long len = RSTRING_LEN(scheme);
507
- if (len >= 5 && !memcmp(RSTRING_PTR(scheme), "https", 5)) {
508
- if (len != 5)
509
- scheme = g_https;
510
- *server_port = g_port_443;
511
- } else {
512
- scheme = g_http;
513
- }
486
+ scheme = g_http;
514
487
  }
515
488
  }
516
489
  }
@@ -608,7 +581,6 @@ static VALUE HttpParser_init(VALUE self)
608
581
  http_parser_init(hp);
609
582
  hp->buf = rb_str_new(NULL, 0);
610
583
  hp->env = rb_hash_new();
611
- hp->nr_requests = keepalive_requests;
612
584
 
613
585
  return self;
614
586
  }
@@ -625,61 +597,11 @@ static VALUE HttpParser_clear(VALUE self)
625
597
  struct http_parser *hp = data_get(self);
626
598
 
627
599
  http_parser_init(hp);
628
- rb_funcall(hp->env, id_clear, 0);
629
- rb_ivar_set(self, id_response_start_sent, Qfalse);
600
+ my_hash_clear(hp->env);
630
601
 
631
602
  return self;
632
603
  }
633
604
 
634
- /**
635
- * call-seq:
636
- * parser.dechunk! => parser
637
- *
638
- * Resets the parser to a state suitable for dechunking response bodies
639
- *
640
- */
641
- static VALUE HttpParser_dechunk_bang(VALUE self)
642
- {
643
- struct http_parser *hp = data_get(self);
644
-
645
- http_parser_init(hp);
646
-
647
- /*
648
- * we don't care about trailers in dechunk-only mode,
649
- * but if we did we'd set UH_FL_HASTRAILER and clear hp->env
650
- */
651
- if (0) {
652
- rb_funcall(hp->env, id_clear, 0);
653
- hp->flags = UH_FL_HASTRAILER;
654
- }
655
-
656
- hp->flags |= UH_FL_HASBODY | UH_FL_INBODY | UH_FL_CHUNKED;
657
- hp->cs = http_parser_en_ChunkedBody;
658
-
659
- return self;
660
- }
661
-
662
- /**
663
- * call-seq:
664
- * parser.reset => nil
665
- *
666
- * Resets the parser to it's initial state so that you can reuse it
667
- * rather than making new ones.
668
- *
669
- * This method is deprecated and to be removed in Unicorn 4.x
670
- */
671
- static VALUE HttpParser_reset(VALUE self)
672
- {
673
- static int warned;
674
-
675
- if (!warned) {
676
- rb_warn("Unicorn::HttpParser#reset is deprecated; "
677
- "use Unicorn::HttpParser#clear instead");
678
- }
679
- HttpParser_clear(self);
680
- return Qnil;
681
- }
682
-
683
605
  static void advance_str(VALUE str, off_t nr)
684
606
  {
685
607
  long len = RSTRING_LEN(str);
@@ -842,15 +764,13 @@ static VALUE HttpParser_keepalive(VALUE self)
842
764
  * parser.next? => true or false
843
765
  *
844
766
  * Exactly like HttpParser#keepalive?, except it will reset the internal
845
- * parser state on next parse if it returns true. It will also respect
846
- * the maximum *keepalive_requests* value and return false if that is
847
- * reached.
767
+ * parser state on next parse if it returns true.
848
768
  */
849
769
  static VALUE HttpParser_next(VALUE self)
850
770
  {
851
771
  struct http_parser *hp = data_get(self);
852
772
 
853
- if ((HP_FL_ALL(hp, KEEPALIVE)) && (hp->nr_requests-- != 0)) {
773
+ if (HP_FL_ALL(hp, KEEPALIVE)) {
854
774
  HP_FL_SET(hp, TO_CLEAR);
855
775
  return Qtrue;
856
776
  }
@@ -960,6 +880,25 @@ static VALUE HttpParser_filter_body(VALUE self, VALUE dst, VALUE src)
960
880
  return src;
961
881
  }
962
882
 
883
+ static VALUE HttpParser_rssset(VALUE self, VALUE boolean)
884
+ {
885
+ struct http_parser *hp = data_get(self);
886
+
887
+ if (RTEST(boolean))
888
+ HP_FL_SET(hp, RESSTART);
889
+ else
890
+ HP_FL_UNSET(hp, RESSTART);
891
+
892
+ return boolean; /* ignored by Ruby anyways */
893
+ }
894
+
895
+ static VALUE HttpParser_rssget(VALUE self)
896
+ {
897
+ struct http_parser *hp = data_get(self);
898
+
899
+ return HP_FL_TEST(hp, RESSTART) ? Qtrue : Qfalse;
900
+ }
901
+
963
902
  #define SET_GLOBAL(var,str) do { \
964
903
  var = find_common_field(str, sizeof(str) - 1); \
965
904
  assert(!NIL_P(var) && "missed global field"); \
@@ -969,7 +908,7 @@ void Init_unicorn_http(void)
969
908
  {
970
909
  VALUE mUnicorn, cHttpParser;
971
910
 
972
- mUnicorn = rb_const_get(rb_cObject, rb_intern("Unicorn"));
911
+ mUnicorn = rb_define_module("Unicorn");
973
912
  cHttpParser = rb_define_class_under(mUnicorn, "HttpParser", rb_cObject);
974
913
  eHttpParserError =
975
914
  rb_define_class_under(mUnicorn, "HttpParserError", rb_eIOError);
@@ -982,8 +921,6 @@ void Init_unicorn_http(void)
982
921
  rb_define_alloc_func(cHttpParser, HttpParser_alloc);
983
922
  rb_define_method(cHttpParser, "initialize", HttpParser_init, 0);
984
923
  rb_define_method(cHttpParser, "clear", HttpParser_clear, 0);
985
- rb_define_method(cHttpParser, "reset", HttpParser_reset, 0);
986
- rb_define_method(cHttpParser, "dechunk!", HttpParser_dechunk_bang, 0);
987
924
  rb_define_method(cHttpParser, "parse", HttpParser_parse, 0);
988
925
  rb_define_method(cHttpParser, "add_parse", HttpParser_add_parse, 1);
989
926
  rb_define_method(cHttpParser, "headers", HttpParser_headers, 2);
@@ -996,6 +933,8 @@ void Init_unicorn_http(void)
996
933
  rb_define_method(cHttpParser, "next?", HttpParser_next, 0);
997
934
  rb_define_method(cHttpParser, "buf", HttpParser_buf, 0);
998
935
  rb_define_method(cHttpParser, "env", HttpParser_env, 0);
936
+ rb_define_method(cHttpParser, "response_start_sent=", HttpParser_rssset, 1);
937
+ rb_define_method(cHttpParser, "response_start_sent", HttpParser_rssget, 0);
999
938
 
1000
939
  /*
1001
940
  * The maximum size a single chunk when using chunked transfer encoding.
@@ -1012,14 +951,6 @@ void Init_unicorn_http(void)
1012
951
  */
1013
952
  rb_define_const(cHttpParser, "LENGTH_MAX", OFFT2NUM(UH_OFF_T_MAX));
1014
953
 
1015
- /* default value for keepalive_requests */
1016
- rb_define_const(cHttpParser, "KEEPALIVE_REQUESTS_DEFAULT",
1017
- ULONG2NUM(keepalive_requests));
1018
-
1019
- rb_define_singleton_method(cHttpParser, "keepalive_requests", ka_req, 0);
1020
- rb_define_singleton_method(cHttpParser, "keepalive_requests=", set_ka_req, 1);
1021
- rb_define_singleton_method(cHttpParser, "trust_x_forwarded=", set_xftrust, 1);
1022
- rb_define_singleton_method(cHttpParser, "trust_x_forwarded?", xftrust, 0);
1023
954
  rb_define_singleton_method(cHttpParser, "max_header_len=", set_maxhdrlen, 1);
1024
955
 
1025
956
  init_common_fields();
@@ -1028,9 +959,11 @@ void Init_unicorn_http(void)
1028
959
  SET_GLOBAL(g_http_transfer_encoding, "TRANSFER_ENCODING");
1029
960
  SET_GLOBAL(g_content_length, "CONTENT_LENGTH");
1030
961
  SET_GLOBAL(g_http_connection, "CONNECTION");
1031
- id_clear = rb_intern("clear");
1032
962
  id_set_backtrace = rb_intern("set_backtrace");
1033
- id_response_start_sent = rb_intern("@response_start_sent");
1034
963
  init_unicorn_httpdate();
964
+
965
+ #ifndef HAVE_RB_HASH_CLEAR
966
+ id_clear = rb_intern("clear");
967
+ #endif
1035
968
  }
1036
969
  #undef SET_GLOBAL
@@ -1,8 +1,7 @@
1
1
  # -*- encoding: binary -*-
2
2
  require 'logger'
3
- require 'unicorn/ssl_configurator'
4
3
 
5
- # Implements a simple DSL for configuring a \Unicorn server.
4
+ # Implements a simple DSL for configuring a unicorn server.
6
5
  #
7
6
  # See http://unicorn.bogomips.org/examples/unicorn.conf.rb and
8
7
  # http://unicorn.bogomips.org/examples/unicorn.conf.minimal.rb
@@ -13,7 +12,6 @@ require 'unicorn/ssl_configurator'
13
12
  # See the link:/TUNING.html document for more information on tuning unicorn.
14
13
  class Unicorn::Configurator
15
14
  include Unicorn
16
- include Unicorn::SSLConfigurator
17
15
 
18
16
  # :stopdoc:
19
17
  attr_accessor :set, :config_file, :after_reload
@@ -48,7 +46,6 @@ class Unicorn::Configurator
48
46
  :check_client_connection => false,
49
47
  :rewindable_input => true, # for Rack 2.x: (Rack::VERSION[0] <= 1),
50
48
  :client_body_buffer_size => Unicorn::Const::MAX_BODY,
51
- :trust_x_forwarded => true,
52
49
  }
53
50
  #:startdoc:
54
51
 
@@ -257,6 +254,11 @@ class Unicorn::Configurator
257
254
  #
258
255
  # Default: 1024
259
256
  #
257
+ # Note: with the Linux kernel, the net.core.somaxconn sysctl defaults
258
+ # to 128, capping this value to 128. Raising the sysctl allows a
259
+ # larger backlog (which may not be desirable with multiple,
260
+ # load-balanced machines).
261
+ #
260
262
  # [:rcvbuf => bytes, :sndbuf => bytes]
261
263
  #
262
264
  # Maximum receive and send buffer sizes (in bytes) of sockets.
@@ -280,20 +282,19 @@ class Unicorn::Configurator
280
282
  # Setting this to +true+ can make streaming responses in Rails 3.1
281
283
  # appear more quickly at the cost of slightly higher bandwidth usage.
282
284
  # The effect of this option is most visible if nginx is not used,
283
- # but nginx remains highly recommended with \Unicorn.
285
+ # but nginx remains highly recommended with unicorn.
284
286
  #
285
287
  # This has no effect on UNIX sockets.
286
288
  #
287
- # Default: +true+ (Nagle's algorithm disabled) in \Unicorn,
288
- # +true+ in Rainbows! This defaulted to +false+ in \Unicorn
289
- # 3.x
289
+ # Default: +true+ (Nagle's algorithm disabled) in unicorn
290
+ # This defaulted to +false+ in unicorn 3.x
290
291
  #
291
292
  # [:tcp_nopush => true or false]
292
293
  #
293
294
  # Enables/disables TCP_CORK in Linux or TCP_NOPUSH in FreeBSD
294
295
  #
295
296
  # This prevents partial TCP frames from being sent out and reduces
296
- # wakeups in nginx if it is on a different machine. Since \Unicorn
297
+ # wakeups in nginx if it is on a different machine. Since unicorn
297
298
  # is only designed for applications that send the response body
298
299
  # quickly without keepalive, sockets will always be flushed on close
299
300
  # to prevent delays.
@@ -301,7 +302,7 @@ class Unicorn::Configurator
301
302
  # This has no effect on UNIX sockets.
302
303
  #
303
304
  # Default: +false+
304
- # This defaulted to +true+ in \Unicorn 3.4 - 3.7
305
+ # This defaulted to +true+ in unicorn 3.4 - 3.7
305
306
  #
306
307
  # [:ipv6only => true or false]
307
308
  #
@@ -385,12 +386,10 @@ class Unicorn::Configurator
385
386
  # and +false+ or +nil+ is synonymous for a value of zero.
386
387
  #
387
388
  # A value of +1+ is a good optimization for local networks
388
- # and trusted clients. For Rainbows! and Zbatery users, a higher
389
- # value (e.g. +60+) provides more protection against some
390
- # denial-of-service attacks. There is no good reason to ever
391
- # disable this with a +zero+ value when serving HTTP.
389
+ # and trusted clients. There is no good reason to ever
390
+ # disable this with a +zero+ value with unicorn.
392
391
  #
393
- # Default: 1 retransmit for \Unicorn, 60 for Rainbows! 0.95.0\+
392
+ # Default: 1
394
393
  #
395
394
  # [:accept_filter => String]
396
395
  #
@@ -399,8 +398,7 @@ class Unicorn::Configurator
399
398
  # This enables either the "dataready" or (default) "httpready"
400
399
  # accept() filter under FreeBSD. This is intended as an
401
400
  # optimization to reduce context switches with common GET/HEAD
402
- # requests. For Rainbows! and Zbatery users, this provides
403
- # some protection against certain denial-of-service attacks, too.
401
+ # requests.
404
402
  #
405
403
  # There is no good reason to change from the default.
406
404
  #
@@ -556,18 +554,6 @@ class Unicorn::Configurator
556
554
  set[:user] = [ user, group ]
557
555
  end
558
556
 
559
- # Sets whether or not the parser will trust X-Forwarded-Proto and
560
- # X-Forwarded-SSL headers and set "rack.url_scheme" to "https" accordingly.
561
- # Rainbows!/Zbatery installations facing untrusted clients directly
562
- # should set this to +false+. This is +true+ by default as Unicorn
563
- # is designed to only sit behind trusted nginx proxies.
564
- #
565
- # This has never been publically documented and is subject to removal
566
- # in future releases.
567
- def trust_x_forwarded(bool) # :nodoc:
568
- set_bool(:trust_x_forwarded, bool)
569
- end
570
-
571
557
  # expands "unix:path/to/foo" to a socket relative to the current path
572
558
  # expands pathnames of sockets if relative to "~" or "~username"
573
559
  # expands "*:port and ":port" to "0.0.0.0:port"
@@ -601,7 +587,7 @@ private
601
587
  def canonicalize_tcp(addr, port)
602
588
  packed = Socket.pack_sockaddr_in(port, addr)
603
589
  port, addr = Socket.unpack_sockaddr_in(packed)
604
- /:/ =~ addr ? "[#{addr}]:#{port}" : "#{addr}:#{port}"
590
+ addr.include?(':') ? "[#{addr}]:#{port}" : "#{addr}:#{port}"
605
591
  end
606
592
 
607
593
  def set_path(var, path) #:nodoc:
@@ -657,7 +643,7 @@ private
657
643
  raise ArgumentError, "rackup file (#{ru}) not readable"
658
644
 
659
645
  # it could be a .rb file, too, we don't parse those manually
660
- ru =~ /\.ru\z/ or return
646
+ ru.end_with?('.ru') or return
661
647
 
662
648
  /^#\\(.*)/ =~ File.read(ru) or return
663
649
  RACKUP[:optparse].parse!($1.split(/\s+/))
data/lib/unicorn/const.rb CHANGED
@@ -1,12 +1,6 @@
1
1
  # -*- encoding: binary -*-
2
2
 
3
- # :enddoc:
4
- # Frequently used constants when constructing requests or responses.
5
- # Many times the constant just refers to a string with the same
6
- # contents. Using these constants gave about a 3% to 10% performance
7
- # improvement over using the strings directly. Symbols did not really
8
- # improve things much compared to constants.
9
- module Unicorn::Const
3
+ module Unicorn::Const # :nodoc:
10
4
  # default TCP listen host address (0.0.0.0, all interfaces)
11
5
  DEFAULT_HOST = "0.0.0.0"
12
6
 
@@ -23,22 +17,5 @@ module Unicorn::Const
23
17
  # temporary file for reading (112 kilobytes). This is the default
24
18
  # value of client_body_buffer_size.
25
19
  MAX_BODY = 1024 * 112
26
-
27
- # :stopdoc:
28
- # common errors we'll send back
29
- # (N.B. these are not used by unicorn, but we won't drop them until
30
- # unicorn 5.x to avoid breaking Rainbows!).
31
- ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n"
32
- ERROR_414_RESPONSE = "HTTP/1.1 414 Request-URI Too Long\r\n\r\n"
33
- ERROR_413_RESPONSE = "HTTP/1.1 413 Request Entity Too Large\r\n\r\n"
34
- ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
35
-
36
- EXPECT_100_RESPONSE = "HTTP/1.1 100 Continue\r\n\r\n"
37
- EXPECT_100_RESPONSE_SUFFIXED = "100 Continue\r\n\r\nHTTP/1.1 "
38
-
39
- HTTP_RESPONSE_START = ['HTTP', '/1.1 ']
40
- HTTP_EXPECT = "HTTP_EXPECT"
41
-
42
- # :startdoc:
43
20
  end
44
- require 'unicorn/version'
21
+ require_relative 'version'
@@ -13,7 +13,8 @@ class Unicorn::HttpParser
13
13
  "rack.multiprocess" => true,
14
14
  "rack.multithread" => false,
15
15
  "rack.run_once" => false,
16
- "rack.version" => [1, 1],
16
+ "rack.version" => [1, 2],
17
+ "rack.hijack?" => true,
17
18
  "SCRIPT_NAME" => "",
18
19
 
19
20
  # this is not in the Rack spec, but some apps may rely on it
@@ -22,12 +23,11 @@ class Unicorn::HttpParser
22
23
 
23
24
  NULL_IO = StringIO.new("")
24
25
 
25
- attr_accessor :response_start_sent
26
-
27
26
  # :stopdoc:
28
27
  # A frozen format for this is about 15% faster
29
- REMOTE_ADDR = 'REMOTE_ADDR'.freeze
30
- RACK_INPUT = 'rack.input'.freeze
28
+ # Drop these frozen strings when Ruby 2.2 becomes more prevalent,
29
+ # 2.2+ optimizes hash assignments when used with literal string keys
30
+ HTTP_RESPONSE_START = [ 'HTTP', '/1.1 ']
31
31
  @@input_class = Unicorn::TeeInput
32
32
  @@check_client_connection = false
33
33
 
@@ -73,7 +73,7 @@ class Unicorn::HttpParser
73
73
  # identify the client for the immediate request to the server;
74
74
  # that client may be a proxy, gateway, or other intermediary
75
75
  # acting on behalf of the actual source client."
76
- e[REMOTE_ADDR] = socket.kgio_addr
76
+ e['REMOTE_ADDR'] = socket.kgio_addr
77
77
 
78
78
  # short circuit the common case with small GET requests first
79
79
  socket.kgio_read!(16384, buf)
@@ -85,38 +85,27 @@ class Unicorn::HttpParser
85
85
 
86
86
  # detect if the socket is valid by writing a partial response:
87
87
  if @@check_client_connection && headers?
88
- @response_start_sent = true
89
- Unicorn::Const::HTTP_RESPONSE_START.each { |c| socket.write(c) }
88
+ self.response_start_sent = true
89
+ HTTP_RESPONSE_START.each { |c| socket.write(c) }
90
90
  end
91
91
 
92
- e[RACK_INPUT] = 0 == content_length ?
93
- NULL_IO : @@input_class.new(socket, self)
94
- hijack_setup(e, socket)
95
- e.merge!(DEFAULTS)
96
- end
97
-
98
- # Rack 1.5.0 (protocol version 1.2) adds hijack request support
99
- if ((Rack::VERSION[0] << 8) | Rack::VERSION[1]) >= 0x0102
100
- DEFAULTS["rack.hijack?"] = true
101
- DEFAULTS["rack.version"] = [1, 2]
92
+ e['rack.input'] = 0 == content_length ?
93
+ NULL_IO : @@input_class.new(socket, self)
102
94
 
103
- RACK_HIJACK = "rack.hijack".freeze
104
- RACK_HIJACK_IO = "rack.hijack_io".freeze
95
+ # for Rack hijacking in Rack 1.5 and later
96
+ e['unicorn.socket'] = socket
97
+ e['rack.hijack'] = self
105
98
 
106
- def hijacked?
107
- env.include?(RACK_HIJACK_IO)
108
- end
99
+ e.merge!(DEFAULTS)
100
+ end
109
101
 
110
- def hijack_setup(e, socket)
111
- e[RACK_HIJACK] = proc { e[RACK_HIJACK_IO] = socket }
112
- end
113
- else
114
- # old Rack, do nothing.
115
- def hijack_setup(e, _)
116
- end
102
+ # for rack.hijack, we respond to this method so no extra allocation
103
+ # of a proc object
104
+ def call
105
+ env['rack.hijack_io'] = env['unicorn.socket']
106
+ end
117
107
 
118
- def hijacked?
119
- false
120
- end
108
+ def hijacked?
109
+ env.include?('rack.hijack_io'.freeze)
121
110
  end
122
111
  end