unicorn 4.7.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +0 -1
- data/.gitattributes +5 -0
- data/.gitignore +2 -2
- data/.manifest +14 -21
- data/.olddoc.yml +22 -0
- data/Application_Timeouts +7 -7
- data/DESIGN +2 -4
- data/Documentation/.gitignore +1 -3
- data/Documentation/unicorn.1 +222 -0
- data/Documentation/unicorn_rails.1 +207 -0
- data/FAQ +23 -6
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +139 -92
- data/HACKING +13 -28
- data/ISSUES +82 -19
- data/KNOWN_ISSUES +18 -18
- data/LATEST +22 -44
- data/LICENSE +2 -2
- data/Links +24 -22
- data/NEWS +729 -0
- data/PHILOSOPHY +0 -6
- data/README +50 -48
- data/Rakefile +0 -44
- data/SIGNALS +12 -3
- data/Sandbox +11 -10
- data/TODO +0 -2
- data/TUNING +30 -9
- data/archive/.gitignore +3 -0
- data/archive/slrnpull.conf +4 -0
- data/bin/unicorn +4 -2
- data/bin/unicorn_rails +3 -3
- data/examples/big_app_gc.rb +1 -1
- data/examples/init.sh +36 -8
- data/examples/logrotate.conf +17 -2
- data/examples/nginx.conf +14 -14
- data/examples/unicorn.conf.minimal.rb +2 -2
- data/examples/unicorn.conf.rb +14 -6
- data/examples/unicorn.socket +11 -0
- data/examples/unicorn@.service +40 -0
- data/ext/unicorn_http/common_field_optimization.h +23 -5
- data/ext/unicorn_http/ext_help.h +0 -20
- data/ext/unicorn_http/extconf.rb +37 -1
- data/ext/unicorn_http/global_variables.h +1 -1
- data/ext/unicorn_http/httpdate.c +2 -2
- data/ext/unicorn_http/unicorn_http.c +940 -644
- data/ext/unicorn_http/unicorn_http.rl +167 -170
- data/ext/unicorn_http/unicorn_http_common.rl +1 -1
- data/lib/unicorn/configurator.rb +110 -46
- data/lib/unicorn/const.rb +2 -25
- data/lib/unicorn/http_request.rb +110 -31
- data/lib/unicorn/http_response.rb +17 -31
- data/lib/unicorn/http_server.rb +292 -199
- data/lib/unicorn/launcher.rb +1 -1
- data/lib/unicorn/oob_gc.rb +16 -6
- data/lib/unicorn/socket_helper.rb +58 -78
- data/lib/unicorn/stream_input.rb +9 -11
- data/lib/unicorn/tee_input.rb +16 -11
- data/lib/unicorn/tmpio.rb +10 -6
- data/lib/unicorn/util.rb +5 -4
- data/lib/unicorn/version.rb +1 -1
- data/lib/unicorn/worker.rb +99 -22
- data/lib/unicorn.rb +69 -42
- data/man/man1/unicorn.1 +124 -122
- data/man/man1/unicorn_rails.1 +113 -127
- data/t/.gitignore +0 -1
- data/t/GNUmakefile +3 -80
- data/t/README +4 -4
- data/t/t0002-parser-error.sh +3 -3
- data/t/t0011-active-unix-socket.sh +1 -1
- data/t/t0012-reload-empty-config.sh +2 -1
- data/t/t0300-no-default-middleware.sh +6 -1
- data/t/t0301-no-default-middleware-ignored-in-config.sh +25 -0
- data/t/t0301.ru +13 -0
- data/t/test-lib.sh +2 -2
- data/test/benchmark/README +14 -4
- data/test/benchmark/ddstream.ru +50 -0
- data/test/benchmark/readinput.ru +40 -0
- data/test/benchmark/uconnect.perl +66 -0
- data/test/exec/test_exec.rb +74 -20
- data/test/test_helper.rb +42 -33
- data/test/unit/test_ccc.rb +91 -0
- data/test/unit/test_droplet.rb +1 -1
- data/test/unit/test_http_parser.rb +49 -19
- data/test/unit/test_http_parser_ng.rb +98 -115
- data/test/unit/test_request.rb +11 -11
- data/test/unit/test_response.rb +31 -19
- data/test/unit/test_server.rb +89 -15
- data/test/unit/test_signals.rb +9 -9
- data/test/unit/test_socket_helper.rb +20 -14
- data/test/unit/test_tee_input.rb +10 -0
- data/test/unit/test_upload.rb +10 -15
- data/test/unit/test_util.rb +28 -3
- data/unicorn.gemspec +28 -23
- data/unicorn_1 +1 -0
- data/unicorn_rails_1 +1 -0
- metadata +64 -134
- data/.wrongdoc.yml +0 -10
- data/ChangeLog +0 -4694
- data/Documentation/GNUmakefile +0 -30
- data/Documentation/unicorn.1.txt +0 -178
- data/Documentation/unicorn_rails.1.txt +0 -175
- 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/local.mk.sample +0 -59
- data/script/isolate_for_tests +0 -32
- data/t/hijack.ru +0 -42
- data/t/sslgen.sh +0 -71
- data/t/t0016-trust-x-forwarded-false.sh +0 -30
- data/t/t0017-trust-x-forwarded-true.sh +0 -30
- data/t/t0200-rack-hijack.sh +0 -27
- data/t/t0600-https-server-basic.sh +0 -48
- data/test/unit/test_http_parser_xftrust.rb +0 -38
- data/test/unit/test_sni_hostnames.rb +0 -47
@@ -25,86 +25,33 @@ 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 */
|
29
|
+
#define UH_FL_HIJACK 0x800
|
28
30
|
|
29
31
|
/* all of these flags need to be set for keepalive to be supported */
|
30
32
|
#define UH_FL_KEEPALIVE (UH_FL_KAVERSION | UH_FL_REQEOF | UH_FL_HASHEADER)
|
31
33
|
|
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 */
|
34
|
+
static unsigned int MAX_HEADER_LEN = 1024 * (80 + 32); /* same as Mongrel */
|
87
35
|
|
88
36
|
/* this is only intended for use with Rainbows! */
|
89
37
|
static VALUE set_maxhdrlen(VALUE self, VALUE len)
|
90
38
|
{
|
91
|
-
return
|
39
|
+
return UINT2NUM(MAX_HEADER_LEN = NUM2UINT(len));
|
92
40
|
}
|
93
41
|
|
94
|
-
/* keep this small for
|
42
|
+
/* keep this small for other servers (e.g. yahns) since every client has one */
|
95
43
|
struct http_parser {
|
96
44
|
int cs; /* Ragel internal state */
|
97
45
|
unsigned int flags;
|
98
|
-
unsigned
|
99
|
-
|
100
|
-
size_t offset;
|
46
|
+
unsigned int mark;
|
47
|
+
unsigned int offset;
|
101
48
|
union { /* these 2 fields don't nest */
|
102
|
-
|
103
|
-
|
49
|
+
unsigned int field;
|
50
|
+
unsigned int query;
|
104
51
|
} start;
|
105
52
|
union {
|
106
|
-
|
107
|
-
|
53
|
+
unsigned int field_len; /* only used during header processing */
|
54
|
+
unsigned int dest_offset; /* only used during body processing */
|
108
55
|
} s;
|
109
56
|
VALUE buf;
|
110
57
|
VALUE env;
|
@@ -115,7 +62,20 @@ struct http_parser {
|
|
115
62
|
} len;
|
116
63
|
};
|
117
64
|
|
118
|
-
static ID
|
65
|
+
static ID id_set_backtrace, id_is_chunked_p;
|
66
|
+
static VALUE cHttpParser;
|
67
|
+
|
68
|
+
#ifdef HAVE_RB_HASH_CLEAR /* Ruby >= 2.0 */
|
69
|
+
# define my_hash_clear(h) (void)rb_hash_clear(h)
|
70
|
+
#else /* !HAVE_RB_HASH_CLEAR - Ruby <= 1.9.3 */
|
71
|
+
|
72
|
+
static ID id_clear;
|
73
|
+
|
74
|
+
static void my_hash_clear(VALUE h)
|
75
|
+
{
|
76
|
+
rb_funcall(h, id_clear, 0);
|
77
|
+
}
|
78
|
+
#endif /* HAVE_RB_HASH_CLEAR */
|
119
79
|
|
120
80
|
static void finalize_header(struct http_parser *hp);
|
121
81
|
|
@@ -124,13 +84,25 @@ static void parser_raise(VALUE klass, const char *msg)
|
|
124
84
|
VALUE exc = rb_exc_new2(klass, msg);
|
125
85
|
VALUE bt = rb_ary_new();
|
126
86
|
|
127
|
-
|
128
|
-
|
87
|
+
rb_funcall(exc, id_set_backtrace, 1, bt);
|
88
|
+
rb_exc_raise(exc);
|
89
|
+
}
|
90
|
+
|
91
|
+
static inline unsigned int ulong2uint(unsigned long n)
|
92
|
+
{
|
93
|
+
unsigned int i = (unsigned int)n;
|
94
|
+
|
95
|
+
if (sizeof(unsigned int) != sizeof(unsigned long)) {
|
96
|
+
if ((unsigned long)i != n) {
|
97
|
+
rb_raise(rb_eRangeError, "too large to be 32-bit uint: %lu", n);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
return i;
|
129
101
|
}
|
130
102
|
|
131
103
|
#define REMAINING (unsigned long)(pe - p)
|
132
|
-
#define LEN(AT, FPC) (FPC - buffer - hp->AT)
|
133
|
-
#define MARK(M,FPC) (hp->M = (FPC) - buffer)
|
104
|
+
#define LEN(AT, FPC) (ulong2uint(FPC - buffer) - hp->AT)
|
105
|
+
#define MARK(M,FPC) (hp->M = ulong2uint((FPC) - buffer))
|
134
106
|
#define PTR_TO(F) (buffer + hp->F)
|
135
107
|
#define STR_NEW(M,FPC) rb_str_new(PTR_TO(M), LEN(M, FPC))
|
136
108
|
#define STRIPPED_STR_NEW(M,FPC) stripped_str_new(PTR_TO(M), LEN(M, FPC))
|
@@ -249,6 +221,19 @@ static void write_cont_value(struct http_parser *hp,
|
|
249
221
|
rb_str_buf_cat(hp->cont, vptr, end + 1);
|
250
222
|
}
|
251
223
|
|
224
|
+
static int is_chunked(VALUE v)
|
225
|
+
{
|
226
|
+
/* common case first */
|
227
|
+
if (STR_CSTR_CASE_EQ(v, "chunked"))
|
228
|
+
return 1;
|
229
|
+
|
230
|
+
/*
|
231
|
+
* call Ruby function in unicorn/http_request.rb to deal with unlikely
|
232
|
+
* comma-delimited case
|
233
|
+
*/
|
234
|
+
return rb_funcall(cHttpParser, id_is_chunked_p, 1, v) != Qfalse;
|
235
|
+
}
|
236
|
+
|
252
237
|
static void write_value(struct http_parser *hp,
|
253
238
|
const char *buffer, const char *p)
|
254
239
|
{
|
@@ -275,7 +260,9 @@ static void write_value(struct http_parser *hp,
|
|
275
260
|
f = uncommon_field(field, flen);
|
276
261
|
} else if (f == g_http_connection) {
|
277
262
|
hp_keepalive_connection(hp, v);
|
278
|
-
} else if (f == g_content_length) {
|
263
|
+
} else if (f == g_content_length && !HP_FL_TEST(hp, CHUNKED)) {
|
264
|
+
if (hp->len.content)
|
265
|
+
parser_raise(eHttpParserError, "Content-Length already set");
|
279
266
|
hp->len.content = parse_length(RSTRING_PTR(v), RSTRING_LEN(v));
|
280
267
|
if (hp->len.content < 0)
|
281
268
|
parser_raise(eHttpParserError, "invalid Content-Length");
|
@@ -283,9 +270,30 @@ static void write_value(struct http_parser *hp,
|
|
283
270
|
HP_FL_SET(hp, HASBODY);
|
284
271
|
hp_invalid_if_trailer(hp);
|
285
272
|
} else if (f == g_http_transfer_encoding) {
|
286
|
-
if (
|
273
|
+
if (is_chunked(v)) {
|
274
|
+
if (HP_FL_TEST(hp, CHUNKED))
|
275
|
+
/*
|
276
|
+
* RFC 7230 3.3.1:
|
277
|
+
* A sender MUST NOT apply chunked more than once to a message body
|
278
|
+
* (i.e., chunking an already chunked message is not allowed).
|
279
|
+
*/
|
280
|
+
parser_raise(eHttpParserError, "Transfer-Encoding double chunked");
|
281
|
+
|
287
282
|
HP_FL_SET(hp, CHUNKED);
|
288
283
|
HP_FL_SET(hp, HASBODY);
|
284
|
+
|
285
|
+
/* RFC 7230 3.3.3, 3: favor chunked if Content-Length exists */
|
286
|
+
hp->len.content = 0;
|
287
|
+
} else if (HP_FL_TEST(hp, CHUNKED)) {
|
288
|
+
/*
|
289
|
+
* RFC 7230 3.3.3, point 3 states:
|
290
|
+
* If a Transfer-Encoding header field is present in a request and
|
291
|
+
* the chunked transfer coding is not the final encoding, the
|
292
|
+
* message body length cannot be determined reliably; the server
|
293
|
+
* MUST respond with the 400 (Bad Request) status code and then
|
294
|
+
* close the connection.
|
295
|
+
*/
|
296
|
+
parser_raise(eHttpParserError, "invalid Transfer-Encoding");
|
289
297
|
}
|
290
298
|
hp_invalid_if_trailer(hp);
|
291
299
|
} else if (f == g_http_trailer) {
|
@@ -466,17 +474,37 @@ http_parser_execute(struct http_parser *hp, char *buffer, size_t len)
|
|
466
474
|
post_exec: /* "_out:" also goes here */
|
467
475
|
if (hp->cs != http_parser_error)
|
468
476
|
hp->cs = cs;
|
469
|
-
hp->offset = p - buffer;
|
477
|
+
hp->offset = ulong2uint(p - buffer);
|
470
478
|
|
471
479
|
assert(p <= pe && "buffer overflow after parsing execute");
|
472
480
|
assert(hp->offset <= len && "offset longer than length");
|
473
481
|
}
|
474
482
|
|
483
|
+
static void hp_mark(void *ptr)
|
484
|
+
{
|
485
|
+
struct http_parser *hp = ptr;
|
486
|
+
|
487
|
+
rb_gc_mark(hp->buf);
|
488
|
+
rb_gc_mark(hp->env);
|
489
|
+
rb_gc_mark(hp->cont);
|
490
|
+
}
|
491
|
+
|
492
|
+
static size_t hp_memsize(const void *ptr)
|
493
|
+
{
|
494
|
+
return sizeof(struct http_parser);
|
495
|
+
}
|
496
|
+
|
497
|
+
static const rb_data_type_t hp_type = {
|
498
|
+
"unicorn_http",
|
499
|
+
{ hp_mark, RUBY_TYPED_DEFAULT_FREE, hp_memsize, /* reserved */ },
|
500
|
+
/* parent, data, [ flags ] */
|
501
|
+
};
|
502
|
+
|
475
503
|
static struct http_parser *data_get(VALUE self)
|
476
504
|
{
|
477
505
|
struct http_parser *hp;
|
478
506
|
|
479
|
-
|
507
|
+
TypedData_Get_Struct(self, struct http_parser, &hp_type, hp);
|
480
508
|
assert(hp && "failed to extract http_parser struct");
|
481
509
|
return hp;
|
482
510
|
}
|
@@ -491,26 +519,29 @@ static void set_url_scheme(VALUE env, VALUE *server_port)
|
|
491
519
|
VALUE scheme = rb_hash_aref(env, g_rack_url_scheme);
|
492
520
|
|
493
521
|
if (NIL_P(scheme)) {
|
494
|
-
|
495
|
-
|
522
|
+
/*
|
523
|
+
* would anybody be horribly opposed to removing the X-Forwarded-SSL
|
524
|
+
* and X-Forwarded-Proto handling from this parser? We've had it
|
525
|
+
* forever and nobody has said anything against it, either.
|
526
|
+
* Anyways, please send comments to our public mailing list:
|
527
|
+
* unicorn-public@yhbt.net (no HTML mail, no subscription necessary)
|
528
|
+
*/
|
529
|
+
scheme = rb_hash_aref(env, g_http_x_forwarded_ssl);
|
530
|
+
if (!NIL_P(scheme) && STR_CSTR_EQ(scheme, "on")) {
|
531
|
+
*server_port = g_port_443;
|
532
|
+
scheme = g_https;
|
496
533
|
} else {
|
497
|
-
scheme = rb_hash_aref(env,
|
498
|
-
if (
|
499
|
-
|
500
|
-
scheme = g_https;
|
534
|
+
scheme = rb_hash_aref(env, g_http_x_forwarded_proto);
|
535
|
+
if (NIL_P(scheme)) {
|
536
|
+
scheme = g_http;
|
501
537
|
} else {
|
502
|
-
|
503
|
-
if (
|
504
|
-
|
538
|
+
long len = RSTRING_LEN(scheme);
|
539
|
+
if (len >= 5 && !memcmp(RSTRING_PTR(scheme), "https", 5)) {
|
540
|
+
if (len != 5)
|
541
|
+
scheme = g_https;
|
542
|
+
*server_port = g_port_443;
|
505
543
|
} 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
|
-
}
|
544
|
+
scheme = g_http;
|
514
545
|
}
|
515
546
|
}
|
516
547
|
}
|
@@ -579,21 +610,12 @@ static void finalize_header(struct http_parser *hp)
|
|
579
610
|
rb_hash_aset(hp->env, g_query_string, rb_str_new(NULL, 0));
|
580
611
|
}
|
581
612
|
|
582
|
-
static void hp_mark(void *ptr)
|
583
|
-
{
|
584
|
-
struct http_parser *hp = ptr;
|
585
|
-
|
586
|
-
rb_gc_mark(hp->buf);
|
587
|
-
rb_gc_mark(hp->env);
|
588
|
-
rb_gc_mark(hp->cont);
|
589
|
-
}
|
590
|
-
|
591
613
|
static VALUE HttpParser_alloc(VALUE klass)
|
592
614
|
{
|
593
615
|
struct http_parser *hp;
|
594
|
-
return Data_Make_Struct(klass, struct http_parser, hp_mark, -1, hp);
|
595
|
-
}
|
596
616
|
|
617
|
+
return TypedData_Make_Struct(klass, struct http_parser, &hp_type, hp);
|
618
|
+
}
|
597
619
|
|
598
620
|
/**
|
599
621
|
* call-seq:
|
@@ -608,7 +630,6 @@ static VALUE HttpParser_init(VALUE self)
|
|
608
630
|
http_parser_init(hp);
|
609
631
|
hp->buf = rb_str_new(NULL, 0);
|
610
632
|
hp->env = rb_hash_new();
|
611
|
-
hp->nr_requests = keepalive_requests;
|
612
633
|
|
613
634
|
return self;
|
614
635
|
}
|
@@ -624,62 +645,16 @@ static VALUE HttpParser_clear(VALUE self)
|
|
624
645
|
{
|
625
646
|
struct http_parser *hp = data_get(self);
|
626
647
|
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
return self;
|
632
|
-
}
|
633
|
-
|
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);
|
648
|
+
/* we can't safely reuse .buf and .env if hijacked */
|
649
|
+
if (HP_FL_TEST(hp, HIJACK))
|
650
|
+
return HttpParser_init(self);
|
644
651
|
|
645
652
|
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;
|
653
|
+
my_hash_clear(hp->env);
|
658
654
|
|
659
655
|
return self;
|
660
656
|
}
|
661
657
|
|
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
658
|
static void advance_str(VALUE str, off_t nr)
|
684
659
|
{
|
685
660
|
long len = RSTRING_LEN(str);
|
@@ -842,15 +817,13 @@ static VALUE HttpParser_keepalive(VALUE self)
|
|
842
817
|
* parser.next? => true or false
|
843
818
|
*
|
844
819
|
* 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.
|
820
|
+
* parser state on next parse if it returns true.
|
848
821
|
*/
|
849
822
|
static VALUE HttpParser_next(VALUE self)
|
850
823
|
{
|
851
824
|
struct http_parser *hp = data_get(self);
|
852
825
|
|
853
|
-
if (
|
826
|
+
if (HP_FL_ALL(hp, KEEPALIVE)) {
|
854
827
|
HP_FL_SET(hp, TO_CLEAR);
|
855
828
|
return Qtrue;
|
856
829
|
}
|
@@ -882,6 +855,15 @@ static VALUE HttpParser_env(VALUE self)
|
|
882
855
|
return data_get(self)->env;
|
883
856
|
}
|
884
857
|
|
858
|
+
static VALUE HttpParser_hijacked_bang(VALUE self)
|
859
|
+
{
|
860
|
+
struct http_parser *hp = data_get(self);
|
861
|
+
|
862
|
+
HP_FL_SET(hp, HIJACK);
|
863
|
+
|
864
|
+
return self;
|
865
|
+
}
|
866
|
+
|
885
867
|
/**
|
886
868
|
* call-seq:
|
887
869
|
* parser.filter_body(dst, src) => nil/src
|
@@ -960,6 +942,25 @@ static VALUE HttpParser_filter_body(VALUE self, VALUE dst, VALUE src)
|
|
960
942
|
return src;
|
961
943
|
}
|
962
944
|
|
945
|
+
static VALUE HttpParser_rssset(VALUE self, VALUE boolean)
|
946
|
+
{
|
947
|
+
struct http_parser *hp = data_get(self);
|
948
|
+
|
949
|
+
if (RTEST(boolean))
|
950
|
+
HP_FL_SET(hp, RESSTART);
|
951
|
+
else
|
952
|
+
HP_FL_UNSET(hp, RESSTART);
|
953
|
+
|
954
|
+
return boolean; /* ignored by Ruby anyways */
|
955
|
+
}
|
956
|
+
|
957
|
+
static VALUE HttpParser_rssget(VALUE self)
|
958
|
+
{
|
959
|
+
struct http_parser *hp = data_get(self);
|
960
|
+
|
961
|
+
return HP_FL_TEST(hp, RESSTART) ? Qtrue : Qfalse;
|
962
|
+
}
|
963
|
+
|
963
964
|
#define SET_GLOBAL(var,str) do { \
|
964
965
|
var = find_common_field(str, sizeof(str) - 1); \
|
965
966
|
assert(!NIL_P(var) && "missed global field"); \
|
@@ -967,9 +968,9 @@ static VALUE HttpParser_filter_body(VALUE self, VALUE dst, VALUE src)
|
|
967
968
|
|
968
969
|
void Init_unicorn_http(void)
|
969
970
|
{
|
970
|
-
VALUE mUnicorn
|
971
|
+
VALUE mUnicorn;
|
971
972
|
|
972
|
-
mUnicorn =
|
973
|
+
mUnicorn = rb_define_module("Unicorn");
|
973
974
|
cHttpParser = rb_define_class_under(mUnicorn, "HttpParser", rb_cObject);
|
974
975
|
eHttpParserError =
|
975
976
|
rb_define_class_under(mUnicorn, "HttpParserError", rb_eIOError);
|
@@ -982,8 +983,6 @@ void Init_unicorn_http(void)
|
|
982
983
|
rb_define_alloc_func(cHttpParser, HttpParser_alloc);
|
983
984
|
rb_define_method(cHttpParser, "initialize", HttpParser_init, 0);
|
984
985
|
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
986
|
rb_define_method(cHttpParser, "parse", HttpParser_parse, 0);
|
988
987
|
rb_define_method(cHttpParser, "add_parse", HttpParser_add_parse, 1);
|
989
988
|
rb_define_method(cHttpParser, "headers", HttpParser_headers, 2);
|
@@ -996,6 +995,9 @@ void Init_unicorn_http(void)
|
|
996
995
|
rb_define_method(cHttpParser, "next?", HttpParser_next, 0);
|
997
996
|
rb_define_method(cHttpParser, "buf", HttpParser_buf, 0);
|
998
997
|
rb_define_method(cHttpParser, "env", HttpParser_env, 0);
|
998
|
+
rb_define_method(cHttpParser, "hijacked!", HttpParser_hijacked_bang, 0);
|
999
|
+
rb_define_method(cHttpParser, "response_start_sent=", HttpParser_rssset, 1);
|
1000
|
+
rb_define_method(cHttpParser, "response_start_sent", HttpParser_rssget, 0);
|
999
1001
|
|
1000
1002
|
/*
|
1001
1003
|
* The maximum size a single chunk when using chunked transfer encoding.
|
@@ -1012,14 +1014,6 @@ void Init_unicorn_http(void)
|
|
1012
1014
|
*/
|
1013
1015
|
rb_define_const(cHttpParser, "LENGTH_MAX", OFFT2NUM(UH_OFF_T_MAX));
|
1014
1016
|
|
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
1017
|
rb_define_singleton_method(cHttpParser, "max_header_len=", set_maxhdrlen, 1);
|
1024
1018
|
|
1025
1019
|
init_common_fields();
|
@@ -1028,9 +1022,12 @@ void Init_unicorn_http(void)
|
|
1028
1022
|
SET_GLOBAL(g_http_transfer_encoding, "TRANSFER_ENCODING");
|
1029
1023
|
SET_GLOBAL(g_content_length, "CONTENT_LENGTH");
|
1030
1024
|
SET_GLOBAL(g_http_connection, "CONNECTION");
|
1031
|
-
id_clear = rb_intern("clear");
|
1032
1025
|
id_set_backtrace = rb_intern("set_backtrace");
|
1033
|
-
id_response_start_sent = rb_intern("@response_start_sent");
|
1034
1026
|
init_unicorn_httpdate();
|
1027
|
+
|
1028
|
+
#ifndef HAVE_RB_HASH_CLEAR
|
1029
|
+
id_clear = rb_intern("clear");
|
1030
|
+
#endif
|
1031
|
+
id_is_chunked_p = rb_intern("is_chunked?");
|
1035
1032
|
}
|
1036
1033
|
#undef SET_GLOBAL
|