unicorn 4.9.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Application_Timeouts +3 -3
  3. data/DESIGN +2 -4
  4. data/Documentation/unicorn.1.txt +8 -5
  5. data/Documentation/unicorn_rails.1.txt +2 -2
  6. data/FAQ +17 -8
  7. data/GIT-VERSION-GEN +1 -1
  8. data/GNUmakefile +6 -1
  9. data/ISSUES +20 -28
  10. data/KNOWN_ISSUES +9 -9
  11. data/Links +14 -17
  12. data/PHILOSOPHY +0 -6
  13. data/README +22 -17
  14. data/SIGNALS +1 -1
  15. data/Sandbox +4 -4
  16. data/TUNING +11 -8
  17. data/bin/unicorn +1 -1
  18. data/bin/unicorn_rails +1 -1
  19. data/examples/nginx.conf +10 -11
  20. data/examples/unicorn.conf.rb +1 -4
  21. data/ext/unicorn_http/extconf.rb +1 -0
  22. data/ext/unicorn_http/httpdate.c +1 -1
  23. data/ext/unicorn_http/unicorn_http.rl +89 -156
  24. data/lib/unicorn.rb +10 -18
  25. data/lib/unicorn/configurator.rb +17 -31
  26. data/lib/unicorn/const.rb +2 -25
  27. data/lib/unicorn/http_request.rb +22 -33
  28. data/lib/unicorn/http_response.rb +14 -32
  29. data/lib/unicorn/http_server.rb +129 -122
  30. data/lib/unicorn/socket_helper.rb +36 -72
  31. data/lib/unicorn/stream_input.rb +3 -3
  32. data/lib/unicorn/tmpio.rb +0 -5
  33. data/lib/unicorn/util.rb +2 -1
  34. data/lib/unicorn/worker.rb +3 -15
  35. data/t/hijack.ru +2 -1
  36. data/t/t0200-rack-hijack.sh +5 -2
  37. data/test/exec/test_exec.rb +52 -0
  38. data/test/test_helper.rb +3 -2
  39. data/test/unit/test_http_parser_ng.rb +16 -114
  40. data/test/unit/test_response.rb +19 -16
  41. data/test/unit/test_socket_helper.rb +1 -1
  42. data/unicorn.gemspec +10 -1
  43. metadata +10 -23
  44. data/examples/git.ru +0 -13
  45. data/lib/unicorn/app/exec_cgi.rb +0 -154
  46. data/lib/unicorn/app/inetd.rb +0 -109
  47. data/lib/unicorn/ssl_client.rb +0 -11
  48. data/lib/unicorn/ssl_configurator.rb +0 -104
  49. data/lib/unicorn/ssl_server.rb +0 -42
  50. data/t/t0016-trust-x-forwarded-false.sh +0 -30
  51. data/t/t0017-trust-x-forwarded-true.sh +0 -30
  52. data/test/unit/test_http_parser_xftrust.rb +0 -38
  53. 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.net/] so it
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 \Unicorn with Sandbox installation tools
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://gembundler.com/] or
7
- {Isolate}[http://github.com/jbarnette/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 http://gist.github.com/534668
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 \Unicorn
1
+ = Tuning unicorn
2
2
 
3
- \Unicorn performance is generally as good as a (mostly) Ruby web server
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
- == \Unicorn Configuration
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
- \Unicorn is NOT for serving slow clients, that is the job of nginx.
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. If your application has occasionally slow
21
- responses that are /not/ CPU-intensive, you may increase this to
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 \Unicorn settings
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
- # Unicorn or Rainbows! servers. Generally these configuration settings
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 neither
48
- # Unicorn nor Rainbows! is optimized for it at the moment
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 Unicorn/Rainbows!
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 Unicorn master nukes a
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 "proxy_buffering off" *only* for Rainbows! when doing
136
- # Comet/long-poll/streaming. It's also safe to set if you're using
137
- # only serving fast clients with Unicorn + nginx, but not slow
138
- # clients. You normally want nginx to buffer responses to slow
139
- # clients, even with Rails 3.1 streaming because otherwise a slow
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
@@ -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.0dev or REE with "preload_app true" for memory savings
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
@@ -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")
@@ -66,7 +66,7 @@ static VALUE httpdate(VALUE self)
66
66
 
67
67
  void init_unicorn_httpdate(void)
68
68
  {
69
- VALUE mod = rb_const_get(rb_cObject, rb_intern("Unicorn"));
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 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