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.
- checksums.yaml +4 -4
- data/.gitattributes +5 -0
- data/.manifest +3 -10
- data/Application_Timeouts +3 -3
- data/DESIGN +2 -4
- data/Documentation/unicorn.1.txt +8 -5
- data/Documentation/unicorn_rails.1.txt +2 -2
- data/FAQ +17 -8
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +6 -1
- data/ISSUES +20 -28
- data/KNOWN_ISSUES +9 -9
- data/LATEST +28 -29
- data/Links +14 -17
- data/NEWS +159 -0
- data/PHILOSOPHY +0 -6
- data/README +22 -17
- data/SIGNALS +1 -1
- data/Sandbox +4 -4
- data/TUNING +11 -8
- data/bin/unicorn +1 -1
- data/bin/unicorn_rails +1 -1
- data/examples/nginx.conf +10 -11
- data/examples/unicorn.conf.rb +1 -4
- data/examples/unicorn.socket +11 -0
- data/examples/unicorn@.service +26 -0
- data/ext/unicorn_http/extconf.rb +1 -0
- data/ext/unicorn_http/httpdate.c +1 -1
- data/ext/unicorn_http/unicorn_http.c +267 -334
- data/ext/unicorn_http/unicorn_http.rl +89 -156
- data/lib/unicorn/configurator.rb +17 -31
- data/lib/unicorn/const.rb +2 -25
- data/lib/unicorn/http_request.rb +22 -33
- data/lib/unicorn/http_response.rb +13 -31
- data/lib/unicorn/http_server.rb +129 -122
- data/lib/unicorn/socket_helper.rb +36 -72
- data/lib/unicorn/stream_input.rb +3 -3
- data/lib/unicorn/tmpio.rb +0 -5
- data/lib/unicorn/util.rb +2 -1
- data/lib/unicorn/version.rb +1 -1
- data/lib/unicorn/worker.rb +3 -15
- data/lib/unicorn.rb +10 -18
- data/man/man1/unicorn.1 +7 -5
- data/man/man1/unicorn_rails.1 +2 -2
- data/t/hijack.ru +2 -1
- data/t/t0200-rack-hijack.sh +5 -2
- data/test/exec/test_exec.rb +52 -0
- data/test/test_helper.rb +3 -2
- data/test/unit/test_http_parser_ng.rb +16 -114
- data/test/unit/test_response.rb +28 -16
- data/test/unit/test_socket_helper.rb +1 -1
- data/unicorn.gemspec +10 -1
- metadata +13 -23
- data/examples/git.ru +0 -13
- data/lib/unicorn/app/exec_cgi.rb +0 -154
- data/lib/unicorn/app/inetd.rb +0 -109
- data/lib/unicorn/ssl_client.rb +0 -11
- data/lib/unicorn/ssl_configurator.rb +0 -104
- data/lib/unicorn/ssl_server.rb +0 -42
- data/t/t0016-trust-x-forwarded-false.sh +0 -30
- data/t/t0017-trust-x-forwarded-true.sh +0 -30
- data/test/unit/test_http_parser_xftrust.rb +0 -38
- 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
|
|
38
|
+
return UINT2NUM(MAX_HEADER_LEN = NUM2UINT(len));
|
|
92
39
|
}
|
|
93
40
|
|
|
94
|
-
/* keep this small for
|
|
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
|
|
99
|
-
|
|
100
|
-
size_t offset;
|
|
45
|
+
unsigned int mark;
|
|
46
|
+
unsigned int offset;
|
|
101
47
|
union { /* these 2 fields don't nest */
|
|
102
|
-
|
|
103
|
-
|
|
48
|
+
unsigned int field;
|
|
49
|
+
unsigned int query;
|
|
104
50
|
} start;
|
|
105
51
|
union {
|
|
106
|
-
|
|
107
|
-
|
|
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
|
|
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
|
-
|
|
128
|
-
|
|
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
|
-
|
|
495
|
-
|
|
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,
|
|
498
|
-
if (
|
|
499
|
-
|
|
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
|
-
|
|
503
|
-
if (
|
|
504
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 (
|
|
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 =
|
|
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
|
data/lib/unicorn/configurator.rb
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
288
|
-
#
|
|
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
|
|
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
|
|
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.
|
|
389
|
-
#
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
# :
|
|
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
|
-
|
|
21
|
+
require_relative 'version'
|
data/lib/unicorn/http_request.rb
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
30
|
-
|
|
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
|
-
|
|
89
|
-
|
|
88
|
+
self.response_start_sent = true
|
|
89
|
+
HTTP_RESPONSE_START.each { |c| socket.write(c) }
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
e[
|
|
93
|
-
|
|
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
|
-
|
|
104
|
-
|
|
95
|
+
# for Rack hijacking in Rack 1.5 and later
|
|
96
|
+
e['unicorn.socket'] = socket
|
|
97
|
+
e['rack.hijack'] = self
|
|
105
98
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
end
|
|
99
|
+
e.merge!(DEFAULTS)
|
|
100
|
+
end
|
|
109
101
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
end
|
|
108
|
+
def hijacked?
|
|
109
|
+
env.include?('rack.hijack_io'.freeze)
|
|
121
110
|
end
|
|
122
111
|
end
|