unicorn 4.9.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- 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-GEN +1 -1
- data/GNUmakefile +6 -1
- data/ISSUES +20 -28
- data/KNOWN_ISSUES +9 -9
- data/Links +14 -17
- 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/ext/unicorn_http/extconf.rb +1 -0
- data/ext/unicorn_http/httpdate.c +1 -1
- data/ext/unicorn_http/unicorn_http.rl +89 -156
- data/lib/unicorn.rb +10 -18
- 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 +14 -32
- 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/worker.rb +3 -15
- 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 +19 -16
- data/test/unit/test_socket_helper.rb +1 -1
- data/unicorn.gemspec +10 -1
- metadata +10 -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
data/SIGNALS
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
In general, signals need only be sent to the master process. However,
|
4
4
|
the signals Unicorn uses internally to communicate with the worker
|
5
5
|
processes are documented here as well. With the exception of TTIN/TTOU,
|
6
|
-
signal handling matches the behavior of {nginx}[http://nginx.
|
6
|
+
signal handling matches the behavior of {nginx}[http://nginx.org/] so it
|
7
7
|
should be possible to easily share process management scripts between
|
8
8
|
Unicorn and nginx.
|
9
9
|
|
data/Sandbox
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
= Tips for using
|
1
|
+
= Tips for using unicorn with Sandbox installation tools
|
2
2
|
|
3
3
|
Since unicorn includes executables and is usually used to start a Ruby
|
4
4
|
process, there are certain caveats to using it with tools that sandbox
|
5
5
|
RubyGems installations such as
|
6
|
-
{Bundler}[http://
|
7
|
-
{Isolate}[
|
6
|
+
{Bundler}[http://bundler.io/] or
|
7
|
+
{Isolate}[https://github.com/jbarnette/isolate].
|
8
8
|
|
9
9
|
== General deployment
|
10
10
|
|
@@ -58,7 +58,7 @@ the before_exec hook:
|
|
58
58
|
|
59
59
|
If you're using an older Bundler version (0.9.x), you may need to set or
|
60
60
|
reset GEM_HOME, GEM_PATH and PATH environment variables in the
|
61
|
-
before_exec hook as illustrated by
|
61
|
+
before_exec hook as illustrated by https://gist.github.com/534668
|
62
62
|
|
63
63
|
=== Ruby 2.0.0 close-on-exec and SIGUSR2 incompatibility
|
64
64
|
|
data/TUNING
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
= Tuning
|
1
|
+
= Tuning unicorn
|
2
2
|
|
3
|
-
|
3
|
+
unicorn performance is generally as good as a (mostly) Ruby web server
|
4
4
|
can provide. Most often the performance bottleneck is in the web
|
5
5
|
application running on Unicorn rather than Unicorn itself.
|
6
6
|
|
7
|
-
==
|
7
|
+
== unicorn Configuration
|
8
8
|
|
9
9
|
See Unicorn::Configurator for details on the config file format.
|
10
10
|
+worker_processes+ is the most-commonly needed tuning parameter.
|
@@ -14,12 +14,15 @@ See Unicorn::Configurator for details on the config file format.
|
|
14
14
|
* worker_processes should be scaled to the number of processes your
|
15
15
|
backend system(s) can support. DO NOT scale it to the number of
|
16
16
|
external network clients your application expects to be serving.
|
17
|
-
|
17
|
+
unicorn is NOT for serving slow clients, that is the job of nginx.
|
18
18
|
|
19
19
|
* worker_processes should be *at* *least* the number of CPU cores on
|
20
|
-
a dedicated server
|
21
|
-
responses that are /not/
|
22
|
-
workaround those inefficiencies.
|
20
|
+
a dedicated server (unless you do not have enough memory).
|
21
|
+
If your application has occasionally slow responses that are /not/
|
22
|
+
CPU-intensive, you may increase this to workaround those inefficiencies.
|
23
|
+
|
24
|
+
* Under Ruby 2.2 or later, Etc.nprocessors may be used to determine
|
25
|
+
the number of CPU cores present.
|
23
26
|
|
24
27
|
* worker_processes may be increased for Unicorn::OobGC users to provide
|
25
28
|
more consistent response times.
|
@@ -55,7 +58,7 @@ See Unicorn::Configurator for details on the config file format.
|
|
55
58
|
* UNIX domain sockets are slightly faster than TCP sockets, but only
|
56
59
|
work if nginx is on the same machine.
|
57
60
|
|
58
|
-
== Other
|
61
|
+
== Other unicorn settings
|
59
62
|
|
60
63
|
* Setting "preload_app true" can allow copy-on-write-friendly GC to
|
61
64
|
be used to save memory. It will probably not work out of the box with
|
data/bin/unicorn
CHANGED
@@ -29,7 +29,7 @@ op = OptionParser.new("", 24, ' ') do |opts|
|
|
29
29
|
|
30
30
|
opts.on("-I", "--include PATH",
|
31
31
|
"specify $LOAD_PATH (may be used more than once)") do |path|
|
32
|
-
$LOAD_PATH.unshift(*path.split(
|
32
|
+
$LOAD_PATH.unshift(*path.split(':'))
|
33
33
|
end
|
34
34
|
|
35
35
|
opts.on("-r", "--require LIBRARY",
|
data/bin/unicorn_rails
CHANGED
@@ -30,7 +30,7 @@ op = OptionParser.new("", 24, ' ') do |opts|
|
|
30
30
|
|
31
31
|
opts.on("-I", "--include PATH",
|
32
32
|
"specify $LOAD_PATH (may be used more than once)") do |path|
|
33
|
-
$LOAD_PATH.unshift(*path.split(
|
33
|
+
$LOAD_PATH.unshift(*path.split(':'))
|
34
34
|
end
|
35
35
|
|
36
36
|
opts.on("-r", "--require LIBRARY",
|
data/examples/nginx.conf
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# This is example contains the bare mininum to get nginx going with
|
2
|
-
#
|
2
|
+
# unicorn servers. Generally these configuration settings
|
3
3
|
# are applicable to other HTTP application servers (and not just Ruby
|
4
4
|
# ones), so if you have one working well for proxying another app
|
5
5
|
# server, feel free to continue using it.
|
@@ -44,8 +44,8 @@ http {
|
|
44
44
|
# click tracking!
|
45
45
|
access_log /path/to/nginx.access.log combined;
|
46
46
|
|
47
|
-
# you generally want to serve static files with nginx since
|
48
|
-
#
|
47
|
+
# you generally want to serve static files with nginx since
|
48
|
+
# unicorn is not and will never be optimized for it
|
49
49
|
sendfile on;
|
50
50
|
|
51
51
|
tcp_nopush on; # off may be better for *some* Comet/long-poll stuff
|
@@ -67,10 +67,10 @@ http {
|
|
67
67
|
text/javascript application/x-javascript
|
68
68
|
application/atom+xml;
|
69
69
|
|
70
|
-
# this can be any application server, not just
|
70
|
+
# this can be any application server, not just unicorn
|
71
71
|
upstream app_server {
|
72
72
|
# fail_timeout=0 means we always retry an upstream even if it failed
|
73
|
-
# to return a good HTTP response (in case the
|
73
|
+
# to return a good HTTP response (in case the unicorn master nukes a
|
74
74
|
# single worker for timing out).
|
75
75
|
|
76
76
|
# for UNIX domain socket setups:
|
@@ -132,12 +132,11 @@ http {
|
|
132
132
|
# redirects, we set the Host: header above already.
|
133
133
|
proxy_redirect off;
|
134
134
|
|
135
|
-
# set
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
# client can become a bottleneck of Unicorn.
|
135
|
+
# It's also safe to set if you're using only serving fast clients
|
136
|
+
# with unicorn + nginx, but not slow clients. You normally want
|
137
|
+
# nginx to buffer responses to slow clients, even with Rails 3.1
|
138
|
+
# streaming because otherwise a slow client can become a bottleneck
|
139
|
+
# of unicorn.
|
141
140
|
#
|
142
141
|
# The Rack application may also set "X-Accel-Buffering (yes|no)"
|
143
142
|
# in the response headers do disable/enable buffering on a
|
data/examples/unicorn.conf.rb
CHANGED
@@ -40,11 +40,8 @@ pid "/path/to/app/shared/pids/unicorn.pid"
|
|
40
40
|
stderr_path "/path/to/app/shared/log/unicorn.stderr.log"
|
41
41
|
stdout_path "/path/to/app/shared/log/unicorn.stdout.log"
|
42
42
|
|
43
|
-
# combine Ruby 2.0.
|
44
|
-
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
43
|
+
# combine Ruby 2.0.0+ with "preload_app true" for memory savings
|
45
44
|
preload_app true
|
46
|
-
GC.respond_to?(:copy_on_write_friendly=) and
|
47
|
-
GC.copy_on_write_friendly = true
|
48
45
|
|
49
46
|
# Enable this flag to have unicorn test client connections by writing the
|
50
47
|
# beginning of the HTTP headers before calling the application. This
|
data/ext/unicorn_http/extconf.rb
CHANGED
@@ -5,6 +5,7 @@ have_macro("SIZEOF_OFF_T", "ruby.h") or check_sizeof("off_t", "sys/types.h")
|
|
5
5
|
have_macro("SIZEOF_SIZE_T", "ruby.h") or check_sizeof("size_t", "sys/types.h")
|
6
6
|
have_macro("SIZEOF_LONG", "ruby.h") or check_sizeof("long", "sys/types.h")
|
7
7
|
have_func("rb_str_set_len", "ruby.h")
|
8
|
+
have_func("rb_hash_clear", "ruby.h") # Ruby 2.0+
|
8
9
|
have_func("gmtime_r", "time.h")
|
9
10
|
|
10
11
|
create_makefile("unicorn_http")
|
data/ext/unicorn_http/httpdate.c
CHANGED
@@ -66,7 +66,7 @@ static VALUE httpdate(VALUE self)
|
|
66
66
|
|
67
67
|
void init_unicorn_httpdate(void)
|
68
68
|
{
|
69
|
-
VALUE mod =
|
69
|
+
VALUE mod = rb_define_module("Unicorn");
|
70
70
|
mod = rb_define_module_under(mod, "HttpResponse");
|
71
71
|
|
72
72
|
buf = rb_str_new(0, buf_capa - 1);
|
@@ -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
|