unicorn 2.0.0pre1 → 2.0.0pre2

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.
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v2.0.0pre1.GIT
4
+ DEF_VER=v2.0.0pre2.GIT
5
5
 
6
6
  LF='
7
7
  '
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ def tags
15
15
  timefmt = '%Y-%m-%dT%H:%M:%SZ'
16
16
  @tags ||= `git tag -l`.split(/\n/).map do |tag|
17
17
  next if tag == "v0.0.0"
18
- if %r{\Av[\d\.]+\z} =~ tag
18
+ if %r{\Av[\d\.]+} =~ tag
19
19
  header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
20
20
  header = header.split(/\n/)
21
21
  tagger = header.grep(/\Atagger /).first
data/bin/unicorn CHANGED
@@ -53,8 +53,8 @@ opts = OptionParser.new("", 24, ' ') do |opts|
53
53
  rackup_opts[:set_listener] = true
54
54
  end
55
55
 
56
- opts.on("-E", "--env ENVIRONMENT",
57
- "use ENVIRONMENT for defaults (default: development)") do |e|
56
+ opts.on("-E", "--env RACK_ENV",
57
+ "use RACK_ENV for defaults (default: development)") do |e|
58
58
  ENV["RACK_ENV"] = e
59
59
  end
60
60
 
@@ -8,10 +8,6 @@
8
8
  #define RSTRING_LEN(s) (RSTRING(s)->len)
9
9
  #endif /* !defined(RSTRING_LEN) */
10
10
 
11
- #ifndef RUBINIUS
12
- # define rb_str_update(x) do {} while (0)
13
- #endif /* !RUBINIUS */
14
-
15
11
  #ifndef HAVE_RB_STR_SET_LEN
16
12
  # ifdef RUBINIUS
17
13
  # error we should never get here with current Rubinius (1.x)
@@ -39,6 +39,8 @@ struct http_parser {
39
39
  size_t field_len; /* only used during header processing */
40
40
  size_t dest_offset; /* only used during body processing */
41
41
  } s;
42
+ VALUE buf;
43
+ VALUE env;
42
44
  VALUE cont; /* Qfalse: unset, Qnil: ignored header, T_STRING: append */
43
45
  union {
44
46
  off_t content;
@@ -46,7 +48,9 @@ struct http_parser {
46
48
  } len;
47
49
  };
48
50
 
49
- static void finalize_header(struct http_parser *hp, VALUE req);
51
+ static ID id_clear;
52
+
53
+ static void finalize_header(struct http_parser *hp);
50
54
 
51
55
  static void parser_error(const char *msg)
52
56
  {
@@ -97,7 +101,7 @@ static void hp_keepalive_connection(struct http_parser *hp, VALUE val)
97
101
  }
98
102
 
99
103
  static void
100
- request_method(struct http_parser *hp, VALUE req, const char *ptr, size_t len)
104
+ request_method(struct http_parser *hp, const char *ptr, size_t len)
101
105
  {
102
106
  VALUE v;
103
107
 
@@ -115,11 +119,11 @@ request_method(struct http_parser *hp, VALUE req, const char *ptr, size_t len)
115
119
  } else {
116
120
  v = rb_str_new(ptr, len);
117
121
  }
118
- rb_hash_aset(req, g_request_method, v);
122
+ rb_hash_aset(hp->env, g_request_method, v);
119
123
  }
120
124
 
121
125
  static void
122
- http_version(struct http_parser *hp, VALUE req, const char *ptr, size_t len)
126
+ http_version(struct http_parser *hp, const char *ptr, size_t len)
123
127
  {
124
128
  VALUE v;
125
129
 
@@ -134,8 +138,8 @@ http_version(struct http_parser *hp, VALUE req, const char *ptr, size_t len)
134
138
  } else {
135
139
  v = rb_str_new(ptr, len);
136
140
  }
137
- rb_hash_aset(req, g_server_protocol, v);
138
- rb_hash_aset(req, g_http_version, v);
141
+ rb_hash_aset(hp->env, g_server_protocol, v);
142
+ rb_hash_aset(hp->env, g_http_version, v);
139
143
  }
140
144
 
141
145
  static inline void hp_invalid_if_trailer(struct http_parser *hp)
@@ -172,7 +176,7 @@ static void write_cont_value(struct http_parser *hp,
172
176
  rb_str_buf_cat(hp->cont, vptr, LEN(mark, p));
173
177
  }
174
178
 
175
- static void write_value(VALUE req, struct http_parser *hp,
179
+ static void write_value(struct http_parser *hp,
176
180
  const char *buffer, const char *p)
177
181
  {
178
182
  VALUE f = find_common_field(PTR_TO(start.field), hp->s.field_len);
@@ -218,9 +222,9 @@ static void write_value(VALUE req, struct http_parser *hp,
218
222
  assert_frozen(f);
219
223
  }
220
224
 
221
- e = rb_hash_aref(req, f);
225
+ e = rb_hash_aref(hp->env, f);
222
226
  if (NIL_P(e)) {
223
- hp->cont = rb_hash_aset(req, f, v);
227
+ hp->cont = rb_hash_aset(hp->env, f, v);
224
228
  } else if (f == g_http_host) {
225
229
  /*
226
230
  * ignored, absolute URLs in REQUEST_URI take precedence over
@@ -245,51 +249,47 @@ static void write_value(VALUE req, struct http_parser *hp,
245
249
  action downcase_char { downcase_char(deconst(fpc)); }
246
250
  action write_field { hp->s.field_len = LEN(start.field, fpc); }
247
251
  action start_value { MARK(mark, fpc); }
248
- action write_value { write_value(req, hp, buffer, fpc); }
252
+ action write_value { write_value(hp, buffer, fpc); }
249
253
  action write_cont_value { write_cont_value(hp, buffer, fpc); }
250
- action request_method {
251
- request_method(hp, req, PTR_TO(mark), LEN(mark, fpc));
252
- }
254
+ action request_method { request_method(hp, PTR_TO(mark), LEN(mark, fpc)); }
253
255
  action scheme {
254
- rb_hash_aset(req, g_rack_url_scheme, STR_NEW(mark, fpc));
255
- }
256
- action host {
257
- rb_hash_aset(req, g_http_host, STR_NEW(mark, fpc));
256
+ rb_hash_aset(hp->env, g_rack_url_scheme, STR_NEW(mark, fpc));
258
257
  }
258
+ action host { rb_hash_aset(hp->env, g_http_host, STR_NEW(mark, fpc)); }
259
259
  action request_uri {
260
260
  VALUE str;
261
261
 
262
262
  VALIDATE_MAX_LENGTH(LEN(mark, fpc), REQUEST_URI);
263
- str = rb_hash_aset(req, g_request_uri, STR_NEW(mark, fpc));
263
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, fpc));
264
264
  /*
265
265
  * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
266
266
  * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
267
267
  */
268
268
  if (STR_CSTR_EQ(str, "*")) {
269
269
  str = rb_str_new(NULL, 0);
270
- rb_hash_aset(req, g_path_info, str);
271
- rb_hash_aset(req, g_request_path, str);
270
+ rb_hash_aset(hp->env, g_path_info, str);
271
+ rb_hash_aset(hp->env, g_request_path, str);
272
272
  }
273
273
  }
274
274
  action fragment {
275
275
  VALIDATE_MAX_LENGTH(LEN(mark, fpc), FRAGMENT);
276
- rb_hash_aset(req, g_fragment, STR_NEW(mark, fpc));
276
+ rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, fpc));
277
277
  }
278
278
  action start_query {MARK(start.query, fpc); }
279
279
  action query_string {
280
280
  VALIDATE_MAX_LENGTH(LEN(start.query, fpc), QUERY_STRING);
281
- rb_hash_aset(req, g_query_string, STR_NEW(start.query, fpc));
281
+ rb_hash_aset(hp->env, g_query_string, STR_NEW(start.query, fpc));
282
282
  }
283
- action http_version { http_version(hp, req, PTR_TO(mark), LEN(mark, fpc)); }
283
+ action http_version { http_version(hp, PTR_TO(mark), LEN(mark, fpc)); }
284
284
  action request_path {
285
285
  VALUE val;
286
286
 
287
287
  VALIDATE_MAX_LENGTH(LEN(mark, fpc), REQUEST_PATH);
288
- val = rb_hash_aset(req, g_request_path, STR_NEW(mark, fpc));
288
+ val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, fpc));
289
289
 
290
290
  /* rack says PATH_INFO must start with "/" or be empty */
291
291
  if (!STR_CSTR_EQ(val, "*"))
292
- rb_hash_aset(req, g_path_info, val);
292
+ rb_hash_aset(hp->env, g_path_info, val);
293
293
  }
294
294
  action add_to_chunk_size {
295
295
  hp->len.chunk = step_incr(hp->len.chunk, fc, 16);
@@ -297,7 +297,7 @@ static void write_value(VALUE req, struct http_parser *hp,
297
297
  parser_error("invalid chunk size");
298
298
  }
299
299
  action header_done {
300
- finalize_header(hp, req);
300
+ finalize_header(hp);
301
301
 
302
302
  cs = http_parser_first_final;
303
303
  if (HP_FL_TEST(hp, HASBODY)) {
@@ -330,7 +330,7 @@ static void write_value(VALUE req, struct http_parser *hp,
330
330
  action skip_chunk_data {
331
331
  skip_chunk_data_hack: {
332
332
  size_t nr = MIN((size_t)hp->len.chunk, REMAINING);
333
- memcpy(RSTRING_PTR(req) + hp->s.dest_offset, fpc, nr);
333
+ memcpy(RSTRING_PTR(hp->cont) + hp->s.dest_offset, fpc, nr);
334
334
  hp->s.dest_offset += nr;
335
335
  hp->len.chunk -= nr;
336
336
  p += nr;
@@ -353,15 +353,20 @@ static void write_value(VALUE req, struct http_parser *hp,
353
353
  static void http_parser_init(struct http_parser *hp)
354
354
  {
355
355
  int cs = 0;
356
- memset(hp, 0, sizeof(struct http_parser));
356
+ hp->flags = 0;
357
+ hp->mark = 0;
358
+ hp->offset = 0;
359
+ hp->start.field = 0;
360
+ hp->s.field_len = 0;
361
+ hp->len.content = 0;
357
362
  hp->cont = Qfalse; /* zero on MRI, should be optimized away by above */
358
363
  %% write init;
359
364
  hp->cs = cs;
360
365
  }
361
366
 
362
367
  /** exec **/
363
- static void http_parser_execute(struct http_parser *hp,
364
- VALUE req, char *buffer, size_t len)
368
+ static void
369
+ http_parser_execute(struct http_parser *hp, char *buffer, size_t len)
365
370
  {
366
371
  const char *p, *pe;
367
372
  int cs = hp->cs;
@@ -401,20 +406,20 @@ static struct http_parser *data_get(VALUE self)
401
406
  return hp;
402
407
  }
403
408
 
404
- static void finalize_header(struct http_parser *hp, VALUE req)
409
+ static void finalize_header(struct http_parser *hp)
405
410
  {
406
- VALUE temp = rb_hash_aref(req, g_rack_url_scheme);
411
+ VALUE temp = rb_hash_aref(hp->env, g_rack_url_scheme);
407
412
  VALUE server_name = g_localhost;
408
413
  VALUE server_port = g_port_80;
409
414
 
410
415
  /* set rack.url_scheme to "https" or "http", no others are allowed by Rack */
411
416
  if (NIL_P(temp)) {
412
- temp = rb_hash_aref(req, g_http_x_forwarded_proto);
417
+ temp = rb_hash_aref(hp->env, g_http_x_forwarded_proto);
413
418
  if (!NIL_P(temp) && STR_CSTR_EQ(temp, "https"))
414
419
  server_port = g_port_443;
415
420
  else
416
421
  temp = g_http;
417
- rb_hash_aset(req, g_rack_url_scheme, temp);
422
+ rb_hash_aset(hp->env, g_rack_url_scheme, temp);
418
423
  } else if (STR_CSTR_EQ(temp, "https")) {
419
424
  server_port = g_port_443;
420
425
  } else {
@@ -422,7 +427,7 @@ static void finalize_header(struct http_parser *hp, VALUE req)
422
427
  }
423
428
 
424
429
  /* parse and set the SERVER_NAME and SERVER_PORT variables */
425
- temp = rb_hash_aref(req, g_http_host);
430
+ temp = rb_hash_aref(hp->env, g_http_host);
426
431
  if (!NIL_P(temp)) {
427
432
  char *colon = memchr(RSTRING_PTR(temp), ':', RSTRING_LEN(temp));
428
433
  if (colon) {
@@ -435,20 +440,22 @@ static void finalize_header(struct http_parser *hp, VALUE req)
435
440
  server_name = temp;
436
441
  }
437
442
  }
438
- rb_hash_aset(req, g_server_name, server_name);
439
- rb_hash_aset(req, g_server_port, server_port);
443
+ rb_hash_aset(hp->env, g_server_name, server_name);
444
+ rb_hash_aset(hp->env, g_server_port, server_port);
440
445
  if (!HP_FL_TEST(hp, HASHEADER))
441
- rb_hash_aset(req, g_server_protocol, g_http_09);
446
+ rb_hash_aset(hp->env, g_server_protocol, g_http_09);
442
447
 
443
448
  /* rack requires QUERY_STRING */
444
- if (NIL_P(rb_hash_aref(req, g_query_string)))
445
- rb_hash_aset(req, g_query_string, rb_str_new(NULL, 0));
449
+ if (NIL_P(rb_hash_aref(hp->env, g_query_string)))
450
+ rb_hash_aset(hp->env, g_query_string, rb_str_new(NULL, 0));
446
451
  }
447
452
 
448
453
  static void hp_mark(void *ptr)
449
454
  {
450
455
  struct http_parser *hp = ptr;
451
456
 
457
+ rb_gc_mark(hp->buf);
458
+ rb_gc_mark(hp->env);
452
459
  rb_gc_mark(hp->cont);
453
460
  }
454
461
 
@@ -467,7 +474,11 @@ static VALUE HttpParser_alloc(VALUE klass)
467
474
  */
468
475
  static VALUE HttpParser_init(VALUE self)
469
476
  {
470
- http_parser_init(data_get(self));
477
+ struct http_parser *hp = data_get(self);
478
+
479
+ http_parser_init(hp);
480
+ hp->buf = rb_str_new(NULL, 0);
481
+ hp->env = rb_hash_new();
471
482
 
472
483
  return self;
473
484
  }
@@ -481,7 +492,11 @@ static VALUE HttpParser_init(VALUE self)
481
492
  */
482
493
  static VALUE HttpParser_reset(VALUE self)
483
494
  {
484
- http_parser_init(data_get(self));
495
+ struct http_parser *hp = data_get(self);
496
+
497
+ http_parser_init(hp);
498
+ rb_funcall(hp->env, id_clear, 0);
499
+ rb_str_set_len(hp->buf, 0);
485
500
 
486
501
  return Qnil;
487
502
  }
@@ -522,32 +537,23 @@ static VALUE HttpParser_content_length(VALUE self)
522
537
  }
523
538
 
524
539
  /**
525
- * Document-method: trailers
526
- * call-seq:
527
- * parser.trailers(req, data) => req or nil
528
- *
529
- * This is an alias for HttpParser#headers
530
- */
531
-
532
- /**
533
- * Document-method: headers
540
+ * Document-method: parse
534
541
  * call-seq:
535
- * parser.headers(req, data) => req or nil
542
+ * parser.parse => env or nil
536
543
  *
537
544
  * Takes a Hash and a String of data, parses the String of data filling
538
545
  * in the Hash returning the Hash if parsing is finished, nil otherwise
539
- * When returning the req Hash, it may modify data to point to where
546
+ * When returning the env Hash, it may modify data to point to where
540
547
  * body processing should begin.
541
548
  *
542
549
  * Raises HttpParserError if there are parsing errors.
543
550
  */
544
- static VALUE HttpParser_headers(VALUE self, VALUE req, VALUE data)
551
+ static VALUE HttpParser_parse(VALUE self)
545
552
  {
546
553
  struct http_parser *hp = data_get(self);
554
+ VALUE data = hp->buf;
547
555
 
548
- rb_str_update(data);
549
-
550
- http_parser_execute(hp, req, RSTRING_PTR(data), RSTRING_LEN(data));
556
+ http_parser_execute(hp, RSTRING_PTR(data), RSTRING_LEN(data));
551
557
  VALIDATE_MAX_LENGTH(hp->offset, HEADER);
552
558
 
553
559
  if (hp->cs == http_parser_first_final ||
@@ -555,7 +561,7 @@ static VALUE HttpParser_headers(VALUE self, VALUE req, VALUE data)
555
561
  advance_str(data, hp->offset + 1);
556
562
  hp->offset = 0;
557
563
 
558
- return req;
564
+ return hp->env;
559
565
  }
560
566
 
561
567
  if (hp->cs == http_parser_error)
@@ -564,6 +570,27 @@ static VALUE HttpParser_headers(VALUE self, VALUE req, VALUE data)
564
570
  return Qnil;
565
571
  }
566
572
 
573
+ /**
574
+ * Document-method: trailers
575
+ * call-seq:
576
+ * parser.trailers(req, data) => req or nil
577
+ *
578
+ * This is an alias for HttpParser#headers
579
+ */
580
+
581
+ /**
582
+ * Document-method: headers
583
+ */
584
+ static VALUE HttpParser_headers(VALUE self, VALUE env, VALUE buf)
585
+ {
586
+ struct http_parser *hp = data_get(self);
587
+
588
+ hp->env = env;
589
+ hp->buf = buf;
590
+
591
+ return HttpParser_parse(self);
592
+ }
593
+
567
594
  static int chunked_eof(struct http_parser *hp)
568
595
  {
569
596
  return ((hp->cs == http_parser_first_final) || HP_FL_TEST(hp, INTRAILER));
@@ -619,6 +646,16 @@ static VALUE HttpParser_has_headers(VALUE self)
619
646
  return HP_FL_TEST(hp, HASHEADER) ? Qtrue : Qfalse;
620
647
  }
621
648
 
649
+ static VALUE HttpParser_buf(VALUE self)
650
+ {
651
+ return data_get(self)->buf;
652
+ }
653
+
654
+ static VALUE HttpParser_env(VALUE self)
655
+ {
656
+ return data_get(self)->env;
657
+ }
658
+
622
659
  /**
623
660
  * call-seq:
624
661
  * parser.filter_body(buf, data) => nil/data
@@ -639,7 +676,6 @@ static VALUE HttpParser_filter_body(VALUE self, VALUE buf, VALUE data)
639
676
  char *dptr;
640
677
  long dlen;
641
678
 
642
- rb_str_update(data);
643
679
  dptr = RSTRING_PTR(data);
644
680
  dlen = RSTRING_LEN(data);
645
681
 
@@ -650,7 +686,9 @@ static VALUE HttpParser_filter_body(VALUE self, VALUE buf, VALUE data)
650
686
  if (HP_FL_TEST(hp, CHUNKED)) {
651
687
  if (!chunked_eof(hp)) {
652
688
  hp->s.dest_offset = 0;
653
- http_parser_execute(hp, buf, dptr, dlen);
689
+ hp->cont = buf;
690
+ hp->buf = data;
691
+ http_parser_execute(hp, dptr, dlen);
654
692
  if (hp->cs == http_parser_error)
655
693
  parser_error("Invalid HTTP format, parsing fails.");
656
694
 
@@ -702,13 +740,16 @@ void Init_unicorn_http(void)
702
740
  rb_define_alloc_func(cHttpParser, HttpParser_alloc);
703
741
  rb_define_method(cHttpParser, "initialize", HttpParser_init,0);
704
742
  rb_define_method(cHttpParser, "reset", HttpParser_reset,0);
743
+ rb_define_method(cHttpParser, "parse", HttpParser_parse, 0);
705
744
  rb_define_method(cHttpParser, "headers", HttpParser_headers, 2);
706
- rb_define_method(cHttpParser, "filter_body", HttpParser_filter_body, 2);
707
745
  rb_define_method(cHttpParser, "trailers", HttpParser_headers, 2);
746
+ rb_define_method(cHttpParser, "filter_body", HttpParser_filter_body, 2);
708
747
  rb_define_method(cHttpParser, "content_length", HttpParser_content_length, 0);
709
748
  rb_define_method(cHttpParser, "body_eof?", HttpParser_body_eof, 0);
710
749
  rb_define_method(cHttpParser, "keepalive?", HttpParser_keepalive, 0);
711
750
  rb_define_method(cHttpParser, "headers?", HttpParser_has_headers, 0);
751
+ rb_define_method(cHttpParser, "buf", HttpParser_buf, 0);
752
+ rb_define_method(cHttpParser, "env", HttpParser_env, 0);
712
753
 
713
754
  /*
714
755
  * The maximum size a single chunk when using chunked transfer encoding.
@@ -731,5 +772,6 @@ void Init_unicorn_http(void)
731
772
  SET_GLOBAL(g_http_transfer_encoding, "TRANSFER_ENCODING");
732
773
  SET_GLOBAL(g_content_length, "CONTENT_LENGTH");
733
774
  SET_GLOBAL(g_http_connection, "CONNECTION");
775
+ id_clear = rb_intern("clear");
734
776
  }
735
777
  #undef SET_GLOBAL
data/lib/unicorn.rb CHANGED
@@ -73,11 +73,11 @@ class Unicorn::ClientShutdown < EOFError; end
73
73
 
74
74
  require 'unicorn/const'
75
75
  require 'unicorn/socket_helper'
76
+ require 'unicorn/tee_input'
76
77
  require 'unicorn/http_request'
77
78
  require 'unicorn/configurator'
78
79
  require 'unicorn/tmpio'
79
80
  require 'unicorn/util'
80
- require 'unicorn/tee_input'
81
81
  require 'unicorn/http_response'
82
82
  require 'unicorn/worker'
83
83
  require 'unicorn/http_server'
data/lib/unicorn/const.rb CHANGED
@@ -7,8 +7,8 @@
7
7
  # improve things much compared to constants.
8
8
  module Unicorn::Const
9
9
 
10
- # The current version of Unicorn, currently 2.0.0pre1
11
- UNICORN_VERSION = "2.0.0pre1"
10
+ # The current version of Unicorn, currently 2.0.0pre2
11
+ UNICORN_VERSION = "2.0.0pre2"
12
12
 
13
13
  # default TCP listen host address (0.0.0.0, all interfaces)
14
14
  DEFAULT_HOST = "0.0.0.0"
@@ -2,7 +2,9 @@
2
2
 
3
3
  require 'unicorn_http'
4
4
 
5
- class Unicorn::HttpRequest
5
+ # TODO: remove redundant names
6
+ Unicorn.const_set(:HttpRequest, Unicorn::HttpParser)
7
+ class Unicorn::HttpParser
6
8
 
7
9
  # default parameters we merge into the request env for Rack handlers
8
10
  DEFAULTS = {
@@ -23,20 +25,9 @@ class Unicorn::HttpRequest
23
25
  # A frozen format for this is about 15% faster
24
26
  REMOTE_ADDR = 'REMOTE_ADDR'.freeze
25
27
  RACK_INPUT = 'rack.input'.freeze
28
+ TeeInput = Unicorn::TeeInput
26
29
  # :startdoc:
27
30
 
28
- attr_reader :env, :parser, :buf
29
-
30
- def initialize
31
- @parser = Unicorn::HttpParser.new
32
- @buf = ""
33
- @env = {}
34
- end
35
-
36
- def response_headers?
37
- @parser.headers?
38
- end
39
-
40
31
  # Does the majority of the IO processing. It has been written in
41
32
  # Ruby using about 8 different IO processing strategies.
42
33
  #
@@ -51,8 +42,8 @@ class Unicorn::HttpRequest
51
42
  # This does minimal exception trapping and it is up to the caller
52
43
  # to handle any socket errors (e.g. user aborted upload).
53
44
  def read(socket)
54
- @env.clear
55
- @parser.reset
45
+ reset
46
+ e = env
56
47
 
57
48
  # From http://www.ietf.org/rfc/rfc3875:
58
49
  # "Script authors should be aware that the REMOTE_ADDR and
@@ -61,18 +52,18 @@ class Unicorn::HttpRequest
61
52
  # identify the client for the immediate request to the server;
62
53
  # that client may be a proxy, gateway, or other intermediary
63
54
  # acting on behalf of the actual source client."
64
- @env[REMOTE_ADDR] = socket.kgio_addr
55
+ e[REMOTE_ADDR] = socket.kgio_addr
65
56
 
66
57
  # short circuit the common case with small GET requests first
67
- if @parser.headers(@env, socket.kgio_read!(16384, @buf)).nil?
58
+ socket.kgio_read!(16384, buf)
59
+ if parse.nil?
68
60
  # Parser is not done, queue up more data to read and continue parsing
69
- # an Exception thrown from the PARSER will throw us out of the loop
61
+ # an Exception thrown from the parser will throw us out of the loop
70
62
  begin
71
- @buf << socket.kgio_read!(16384)
72
- end while @parser.headers(@env, @buf).nil?
63
+ buf << socket.kgio_read!(16384)
64
+ end while parse.nil?
73
65
  end
74
- @env[RACK_INPUT] = 0 == @parser.content_length ?
75
- NULL_IO : Unicorn::TeeInput.new(socket, self)
76
- @env.merge!(DEFAULTS)
66
+ e[RACK_INPUT] = 0 == content_length ? NULL_IO : TeeInput.new(socket, self)
67
+ e.merge!(DEFAULTS)
77
68
  end
78
69
  end
@@ -7,9 +7,10 @@
7
7
  class Unicorn::HttpServer
8
8
  attr_accessor :app, :request, :timeout, :worker_processes,
9
9
  :before_fork, :after_fork, :before_exec,
10
- :logger, :pid, :listener_opts, :preload_app,
10
+ :listener_opts, :preload_app,
11
11
  :reexec_pid, :orig_app, :init_listeners,
12
12
  :master_pid, :config, :ready_pipe, :user
13
+ attr_reader :pid, :logger
13
14
 
14
15
  # :stopdoc:
15
16
  include Unicorn::SocketHelper
@@ -520,7 +521,7 @@ class Unicorn::HttpServer
520
521
  r = @app.call(env)
521
522
  end
522
523
  # r may be frozen or const, so don't modify it
523
- @request.response_headers? or r = [ r[0], nil, r[2] ]
524
+ @request.headers? or r = [ r[0], nil, r[2] ]
524
525
  http_response_write(client, r)
525
526
  rescue => e
526
527
  handle_error(client, e)
@@ -11,8 +11,8 @@
11
11
  #
12
12
  # When processing uploads, Unicorn exposes a TeeInput object under
13
13
  # "rack.input" of the Rack environment.
14
- class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
15
- :buf, :len, :tmp, :buf2)
14
+ class Unicorn::TeeInput
15
+ attr_accessor :tmp, :socket, :parser, :env, :buf, :len, :buf2
16
16
 
17
17
  # The maximum size (in +bytes+) to buffer in memory before
18
18
  # resorting to a temporary file. Default is 112 kilobytes.
@@ -26,18 +26,18 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
26
26
  # Initializes a new TeeInput object. You normally do not have to call
27
27
  # this unless you are writing an HTTP server.
28
28
  def initialize(socket, request)
29
- self.socket = socket
30
- self.req = request.env
31
- self.parser = request.parser
32
- self.buf = request.buf
33
- self.len = parser.content_length
34
- self.tmp = len && len < @@client_body_buffer_size ?
35
- StringIO.new("") : Unicorn::TmpIO.new
36
- self.buf2 = ""
37
- if buf.size > 0
38
- parser.filter_body(buf2, buf) and finalize_input
39
- tmp.write(buf2)
40
- tmp.rewind
29
+ @socket = socket
30
+ @parser = request
31
+ @buf = request.buf
32
+ @env = request.env
33
+ @len = request.content_length
34
+ @tmp = @len && @len < @@client_body_buffer_size ?
35
+ StringIO.new("") : Unicorn::TmpIO.new
36
+ @buf2 = ""
37
+ if @buf.size > 0
38
+ @parser.filter_body(@buf2, @buf) and finalize_input
39
+ @tmp.write(@buf2)
40
+ @tmp.rewind
41
41
  end
42
42
  end
43
43
 
@@ -58,16 +58,16 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
58
58
  # earlier. Most applications should only need to call +read+ with a
59
59
  # specified +length+ in a loop until it returns +nil+.
60
60
  def size
61
- len and return len
61
+ @len and return @len
62
62
 
63
63
  if socket
64
- pos = tmp.pos
65
- while tee(@@io_chunk_size, buf2)
64
+ pos = @tmp.pos
65
+ while tee(@@io_chunk_size, @buf2)
66
66
  end
67
- tmp.seek(pos)
67
+ @tmp.seek(pos)
68
68
  end
69
69
 
70
- self.len = tmp.size
70
+ @len = @tmp.size
71
71
  end
72
72
 
73
73
  # :call-seq:
@@ -90,22 +90,22 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
90
90
  # any data and only block when nothing is available (providing
91
91
  # IO#readpartial semantics).
92
92
  def read(*args)
93
- socket or return tmp.read(*args)
93
+ @socket or return @tmp.read(*args)
94
94
 
95
95
  length = args.shift
96
96
  if nil == length
97
- rv = tmp.read || ""
98
- while tee(@@io_chunk_size, buf2)
99
- rv << buf2
97
+ rv = @tmp.read || ""
98
+ while tee(@@io_chunk_size, @buf2)
99
+ rv << @buf2
100
100
  end
101
101
  rv
102
102
  else
103
103
  rv = args.shift || ""
104
- diff = tmp.size - tmp.pos
104
+ diff = @tmp.size - @tmp.pos
105
105
  if 0 == diff
106
106
  ensure_length(tee(length, rv), length)
107
107
  else
108
- ensure_length(tmp.read(diff > length ? length : diff, rv), length)
108
+ ensure_length(@tmp.read(diff > length ? length : diff, rv), length)
109
109
  end
110
110
  end
111
111
  end
@@ -120,27 +120,27 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
120
120
  # This takes zero arguments for strict Rack::Lint compatibility,
121
121
  # unlike IO#gets.
122
122
  def gets
123
- socket or return tmp.gets
123
+ @socket or return @tmp.gets
124
124
  sep = $/ or return read
125
125
 
126
- orig_size = tmp.size
127
- if tmp.pos == orig_size
128
- tee(@@io_chunk_size, buf2) or return nil
129
- tmp.seek(orig_size)
126
+ orig_size = @tmp.size
127
+ if @tmp.pos == orig_size
128
+ tee(@@io_chunk_size, @buf2) or return nil
129
+ @tmp.seek(orig_size)
130
130
  end
131
131
 
132
132
  sep_size = Rack::Utils.bytesize(sep)
133
- line = tmp.gets # cannot be nil here since size > pos
133
+ line = @tmp.gets # cannot be nil here since size > pos
134
134
  sep == line[-sep_size, sep_size] and return line
135
135
 
136
- # unlikely, if we got here, then tmp is at EOF
136
+ # unlikely, if we got here, then @tmp is at EOF
137
137
  begin
138
- orig_size = tmp.pos
139
- tee(@@io_chunk_size, buf2) or break
140
- tmp.seek(orig_size)
141
- line << tmp.gets
138
+ orig_size = @tmp.pos
139
+ tee(@@io_chunk_size, @buf2) or break
140
+ @tmp.seek(orig_size)
141
+ line << @tmp.gets
142
142
  sep == line[-sep_size, sep_size] and return line
143
- # tmp is at EOF again here, retry the loop
143
+ # @tmp is at EOF again here, retry the loop
144
144
  end while true
145
145
 
146
146
  line
@@ -166,7 +166,7 @@ class Unicorn::TeeInput < Struct.new(:socket, :req, :parser,
166
166
  # the offset (zero) of the +ios+ pointer. Subsequent reads will
167
167
  # start from the beginning of the previously-buffered input.
168
168
  def rewind
169
- tmp.rewind # Rack does not specify what the return value is here
169
+ @tmp.rewind # Rack does not specify what the return value is here
170
170
  end
171
171
 
172
172
  private
@@ -175,11 +175,11 @@ private
175
175
  # backing store as well as returning it. +dst+ must be specified.
176
176
  # returns nil if reading from the input returns nil
177
177
  def tee(length, dst)
178
- unless parser.body_eof?
179
- r = socket.kgio_read(length, buf) or eof!
180
- unless parser.filter_body(dst, r)
181
- tmp.write(dst)
182
- tmp.seek(0, IO::SEEK_END) # workaround FreeBSD/OSX + MRI 1.8.x bug
178
+ unless @parser.body_eof?
179
+ r = @socket.kgio_read(length, @buf) or eof!
180
+ unless @parser.filter_body(dst, @buf)
181
+ @tmp.write(dst)
182
+ @tmp.seek(0, IO::SEEK_END) # workaround FreeBSD/OSX + MRI 1.8.x bug
183
183
  return dst
184
184
  end
185
185
  end
@@ -187,11 +187,11 @@ private
187
187
  end
188
188
 
189
189
  def finalize_input
190
- while parser.trailers(req, buf).nil?
191
- r = socket.kgio_read(@@io_chunk_size) or eof!
192
- buf << r
190
+ while @parser.trailers(@env, @buf).nil?
191
+ r = @socket.kgio_read(@@io_chunk_size) or eof!
192
+ @buf << r
193
193
  end
194
- self.socket = nil
194
+ @socket = nil
195
195
  end
196
196
 
197
197
  # tee()s into +dst+ until it is of +length+ bytes (or until
@@ -204,10 +204,10 @@ private
204
204
  # len is nil for chunked bodies, so we can't ensure length for those
205
205
  # since they could be streaming bidirectionally and we don't want to
206
206
  # block the caller in that case.
207
- return dst if dst.nil? || len.nil?
207
+ return dst if dst.nil? || @len.nil?
208
208
 
209
- while dst.size < length && tee(length - dst.size, buf2)
210
- dst << buf2
209
+ while dst.size < length && tee(length - dst.size, @buf2)
210
+ dst << @buf2
211
211
  end
212
212
 
213
213
  dst
@@ -218,7 +218,7 @@ private
218
218
  # we do support clients that shutdown(SHUT_WR) after the
219
219
  # _entire_ request has been sent, and those will not have
220
220
  # raised EOFError on us.
221
- socket.close if socket
222
- raise Unicorn::ClientShutdown, "bytes_read=#{tmp.size}", []
221
+ @socket.close if @socket
222
+ raise Unicorn::ClientShutdown, "bytes_read=#{@tmp.size}", []
223
223
  end
224
224
  end
@@ -388,6 +388,7 @@ class HttpParserNgTest < Test::Unit::TestCase
388
388
  "*" => { qs => "", pi => "" },
389
389
  }.each do |uri,expect|
390
390
  assert_equal req, @parser.headers(req.clear, str % [ uri ])
391
+ req = req.dup
391
392
  @parser.reset
392
393
  assert_equal uri, req["REQUEST_URI"], "REQUEST_URI mismatch"
393
394
  assert_equal expect[qs], req[qs], "#{qs} mismatch"
@@ -412,6 +413,7 @@ class HttpParserNgTest < Test::Unit::TestCase
412
413
  "/1?a=b;c=d&e=f" => { qs => "a=b;c=d&e=f", pi => "/1" },
413
414
  }.each do |uri,expect|
414
415
  assert_equal req, @parser.headers(req.clear, str % [ uri ])
416
+ req = req.dup
415
417
  @parser.reset
416
418
  assert_equal uri, req["REQUEST_URI"], "REQUEST_URI mismatch"
417
419
  assert_equal "example.com", req["HTTP_HOST"], "Host: mismatch"
@@ -5,7 +5,6 @@ require 'digest/sha1'
5
5
  require 'unicorn'
6
6
 
7
7
  class TestTeeInput < Test::Unit::TestCase
8
- MockRequest = Struct.new(:env, :parser, :buf)
9
8
 
10
9
  def setup
11
10
  @rs = $/
@@ -164,7 +163,7 @@ class TestTeeInput < Test::Unit::TestCase
164
163
  @wr.write("0\r\n\r\n")
165
164
  }
166
165
  @wr.close
167
- ti = Unicorn::TeeInput.new(@rd, MockRequest.new(@env, @parser, @buf))
166
+ ti = Unicorn::TeeInput.new(@rd, @parser)
168
167
  assert_nil @parser.content_length
169
168
  assert_nil ti.len
170
169
  assert ! @parser.body_eof?
@@ -202,7 +201,7 @@ class TestTeeInput < Test::Unit::TestCase
202
201
  end
203
202
  @wr.write("0\r\n\r\n")
204
203
  }
205
- ti = Unicorn::TeeInput.new(@rd, MockRequest.new(@env, @parser, @buf))
204
+ ti = Unicorn::TeeInput.new(@rd, @parser)
206
205
  assert_nil @parser.content_length
207
206
  assert_nil ti.len
208
207
  assert ! @parser.body_eof?
@@ -231,7 +230,7 @@ class TestTeeInput < Test::Unit::TestCase
231
230
  @wr.write("Hello: World\r\n\r\n")
232
231
  }
233
232
  @wr.close
234
- ti = Unicorn::TeeInput.new(@rd, MockRequest.new(@env, @parser, @buf))
233
+ ti = Unicorn::TeeInput.new(@rd, @parser)
235
234
  assert_nil @parser.content_length
236
235
  assert_nil ti.len
237
236
  assert ! @parser.body_eof?
@@ -253,7 +252,7 @@ private
253
252
  "\r\n#{body}"
254
253
  assert_equal @env, @parser.headers(@env, @buf)
255
254
  assert_equal body, @buf
256
- MockRequest.new(@env, @parser, @buf)
255
+ @parser
257
256
  end
258
257
 
259
258
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unicorn
3
3
  version: !ruby/object:Gem::Version
4
- hash: -766259887
4
+ hash: -766259858
5
5
  prerelease: true
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 0pre1
10
- version: 2.0.0pre1
9
+ - 0pre2
10
+ version: 2.0.0pre2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Unicorn hackers
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-06 00:00:00 +00:00
18
+ date: 2010-10-07 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency