unicorn 5.3.1 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cae827cc4674fdbfd9291caf3037f0fe4a5e67b7
4
- data.tar.gz: e6518f02407def59575f3efb01a54019e0fdcab9
2
+ SHA256:
3
+ metadata.gz: 2a53c6f0287f74563b46ac07e96cbb709562e4f26bdbf46ae1cb904a3e345828
4
+ data.tar.gz: 0724bceedd3b964168081c4a12c8f9eb04611013f6ef72593d6db63bd31cccf1
5
5
  SHA512:
6
- metadata.gz: 2a9bd5f4dacb2aa56002b9899d1725bdfc124def5b9287ff464b3ed0e47785db1aa14b52757173d990972ad5a3a4afc44e37f052f7ef8ac92ae7fac0daa3645d
7
- data.tar.gz: da9be558581cb34ee8b8c81bdcfcd659dc5e26d0cc42aa291ced5749ea07cbfe14fdce7a2fbfd43339990331e9c58e346d0129ea035c817ff59c8825d34f5645
6
+ metadata.gz: a0b91ca7dd6cc2e52f7eed8fdd30547dbcd3c81939c1df495e612ff94a544dc589cd3d3cd9e4c17206f135ac7e3ef763ecfa80bebacce42960df7f93a679d091
7
+ data.tar.gz: 9eba1d1fefa858d93524ff73c77b8a239b9e50abb6f8bac840d436afebd27608dcad6a8d7f49c35dd44f2577563fdbdc898541efa312b7f5953c155cf1eaf057
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- DEF_VER = "v5.3.1"
2
+ DEF_VER = "v5.4.0"
3
3
  CONSTANT = "Unicorn::Const::UNICORN_VERSION"
4
4
  RVF = "lib/unicorn/version.rb"
5
5
  GVF = "GIT-VERSION-FILE"
@@ -249,5 +249,10 @@ endif
249
249
  $(PLACEHOLDERS):
250
250
  echo olddoc_placeholder > $@
251
251
 
252
+ check-warnings:
253
+ @(for i in $$(git ls-files '*.rb' bin | grep -v '^setup\.rb$$'); \
254
+ do $(RUBY) --disable-gems -d -W2 -c \
255
+ $$i; done) | grep -v '^Syntax OK$$' || :
256
+
252
257
  .PHONY: .FORCE-GIT-VERSION-FILE doc $(T) $(slow_tests) man
253
258
  .PHONY: test-install
data/ISSUES CHANGED
@@ -15,6 +15,11 @@ submit patches and/or obtain support after you have searched the
15
15
  * The email submission port (587) is enabled on the bogomips.org MX:
16
16
  https://bogomips.org/unicorn-public/20141004232241.GA23908@dcvr.yhbt.net/t/
17
17
 
18
+ We will never have a centralized or formal bug tracker. Instead we
19
+ can interoperate with any bug tracker which can Cc: us plain-text to
20
+ mailto:unicorn-public@bogomips.org This includes the Debian BTS
21
+ at https://bugs.debian.org/unicorn and possibly others.
22
+
18
23
  If your issue is of a sensitive nature or you're just shy in public,
19
24
  use anonymity tools such as Tor or Mixmaster; and rely on the public
20
25
  mail archives for responses. Be sure to scrub sensitive log messages
@@ -26,6 +26,7 @@ void init_unicorn_httpdate(VALUE mark_ary);
26
26
  #define UH_FL_HASHEADER 0x100
27
27
  #define UH_FL_TO_CLEAR 0x200
28
28
  #define UH_FL_RESSTART 0x400 /* for check_client_connection */
29
+ #define UH_FL_HIJACK 0x800
29
30
 
30
31
  /* all of these flags need to be set for keepalive to be supported */
31
32
  #define UH_FL_KEEPALIVE (UH_FL_KAVERSION | UH_FL_REQEOF | UH_FL_HASHEADER)
@@ -607,6 +608,10 @@ static VALUE HttpParser_clear(VALUE self)
607
608
  {
608
609
  struct http_parser *hp = data_get(self);
609
610
 
611
+ /* we can't safely reuse .buf and .env if hijacked */
612
+ if (HP_FL_TEST(hp, HIJACK))
613
+ return HttpParser_init(self);
614
+
610
615
  http_parser_init(hp);
611
616
  my_hash_clear(hp->env);
612
617
 
@@ -813,6 +818,15 @@ static VALUE HttpParser_env(VALUE self)
813
818
  return data_get(self)->env;
814
819
  }
815
820
 
821
+ static VALUE HttpParser_hijacked_bang(VALUE self)
822
+ {
823
+ struct http_parser *hp = data_get(self);
824
+
825
+ HP_FL_SET(hp, HIJACK);
826
+
827
+ return self;
828
+ }
829
+
816
830
  /**
817
831
  * call-seq:
818
832
  * parser.filter_body(dst, src) => nil/src
@@ -947,6 +961,7 @@ void Init_unicorn_http(void)
947
961
  rb_define_method(cHttpParser, "next?", HttpParser_next, 0);
948
962
  rb_define_method(cHttpParser, "buf", HttpParser_buf, 0);
949
963
  rb_define_method(cHttpParser, "env", HttpParser_env, 0);
964
+ rb_define_method(cHttpParser, "hijacked!", HttpParser_hijacked_bang, 0);
950
965
  rb_define_method(cHttpParser, "response_start_sent=", HttpParser_rssset, 1);
951
966
  rb_define_method(cHttpParser, "response_start_sent", HttpParser_rssget, 0);
952
967
 
@@ -59,7 +59,10 @@ def self.builder(ru, op)
59
59
  Object.const_get(File.basename(ru, '.rb').capitalize)
60
60
  end
61
61
 
62
- pp({ :inner_app => inner_app }) if $DEBUG
62
+ if $DEBUG
63
+ require 'pp'
64
+ pp({ :inner_app => inner_app })
65
+ end
63
66
 
64
67
  return inner_app if no_default_middleware
65
68
 
@@ -587,7 +587,7 @@ def working_directory(path)
587
587
  # just let chdir raise errors
588
588
  path = File.expand_path(path)
589
589
  if config_file &&
590
- config_file[0] != ?/ &&
590
+ ! config_file.start_with?('/') &&
591
591
  ! File.readable?("#{path}/#{config_file}")
592
592
  raise ArgumentError,
593
593
  "config_file=#{config_file} would not be accessible in" \
@@ -98,6 +98,7 @@ def read(socket)
98
98
  # for rack.hijack, we respond to this method so no extra allocation
99
99
  # of a proc object
100
100
  def call
101
+ hijacked!
101
102
  env['rack.hijack_io'] = env['unicorn.socket']
102
103
  end
103
104
 
@@ -21,13 +21,13 @@ def err_response(code, response_start_sent)
21
21
 
22
22
  # writes the rack_response to socket as an HTTP response
23
23
  def http_response_write(socket, status, headers, body,
24
- response_start_sent=false)
24
+ req = Unicorn::HttpRequest.new)
25
25
  hijack = nil
26
26
 
27
27
  if headers
28
28
  code = status.to_i
29
29
  msg = STATUS_CODES[code]
30
- start = response_start_sent ? ''.freeze : 'HTTP/1.1 '.freeze
30
+ start = req.response_start_sent ? ''.freeze : 'HTTP/1.1 '.freeze
31
31
  buf = "#{start}#{msg ? %Q(#{code} #{msg}) : status}\r\n" \
32
32
  "Date: #{httpdate}\r\n" \
33
33
  "Connection: close\r\n"
@@ -52,6 +52,7 @@ def http_response_write(socket, status, headers, body,
52
52
  end
53
53
 
54
54
  if hijack
55
+ req.hijacked!
55
56
  hijack.call(socket)
56
57
  else
57
58
  body.each { |chunk| socket.write(chunk) }
@@ -148,7 +148,7 @@ def start
148
148
  def listeners=(listeners)
149
149
  cur_names, dead_names = [], []
150
150
  listener_names.each do |name|
151
- if ?/ == name[0]
151
+ if name.start_with?('/')
152
152
  # mark unlinked sockets as dead so we can rebind them
153
153
  (File.socket?(name) ? cur_names : dead_names) << name
154
154
  else
@@ -614,8 +614,7 @@ def process_client(client)
614
614
  return if @request.hijacked?
615
615
  end
616
616
  @request.headers? or headers = nil
617
- http_response_write(client, status, headers, body,
618
- @request.response_start_sent)
617
+ http_response_write(client, status, headers, body, @request)
619
618
  ensure
620
619
  body.respond_to?(:close) and body.close
621
620
  end
@@ -116,7 +116,7 @@ def log_buffer_sizes(sock, pfx = '')
116
116
  def bind_listen(address = '0.0.0.0:8080', opt = {})
117
117
  return address unless String === address
118
118
 
119
- sock = if address[0] == ?/
119
+ sock = if address.start_with?('/')
120
120
  if File.exist?(address)
121
121
  if File.socket?(address)
122
122
  begin
@@ -11,11 +11,15 @@ def close
11
11
  warn "closed DieIfUsed #{@@n += 1}\n"
12
12
  end
13
13
  end
14
+
15
+ envs = []
16
+
14
17
  run lambda { |env|
15
18
  case env["PATH_INFO"]
16
19
  when "/hijack_req"
17
20
  if env["rack.hijack?"]
18
21
  io = env["rack.hijack"].call
22
+ envs << env
19
23
  if io.respond_to?(:read_nonblock) &&
20
24
  env["rack.hijack_io"].respond_to?(:read_nonblock)
21
25
 
@@ -33,11 +37,19 @@ def close
33
37
  {
34
38
  "Content-Length" => r.bytesize.to_s,
35
39
  "rack.hijack" => proc do |io|
40
+ envs << env
36
41
  io.write(r)
37
42
  io.close
38
43
  end
39
44
  },
40
45
  DieIfUsed.new
41
46
  ]
47
+ when "/normal_env_id"
48
+ b = "#{env.object_id}\n"
49
+ h = {
50
+ 'Content-Type' => 'text/plain',
51
+ 'Content-Length' => b.bytesize.to_s,
52
+ }
53
+ [ 200, h, [ b ] ]
42
54
  end
43
55
  }
@@ -1,6 +1,6 @@
1
1
  #!/bin/sh
2
2
  . ./test-lib.sh
3
- t_plan 5 "rack.hijack tests (Rack 1.5+ (Rack::VERSION >= [ 1,2]))"
3
+ t_plan 9 "rack.hijack tests (Rack 1.5+ (Rack::VERSION >= [ 1,2]))"
4
4
 
5
5
  t_begin "setup and start" && {
6
6
  unicorn_setup
@@ -8,14 +8,35 @@ t_begin "setup and start" && {
8
8
  unicorn_wait_start
9
9
  }
10
10
 
11
+ t_begin "normal env reused between requests" && {
12
+ env_a="$(curl -sSf http://$listen/normal_env_id)"
13
+ b="$(curl -sSf http://$listen/normal_env_id)"
14
+ test x"$env_a" = x"$b"
15
+ }
16
+
11
17
  t_begin "check request hijack" && {
12
18
  test "xrequest.hijacked" = x"$(curl -sSfv http://$listen/hijack_req)"
13
19
  }
14
20
 
21
+ t_begin "env changed after request hijack" && {
22
+ env_b="$(curl -sSf http://$listen/normal_env_id)"
23
+ test x"$env_a" != x"$env_b"
24
+ }
25
+
15
26
  t_begin "check response hijack" && {
16
27
  test "xresponse.hijacked" = x"$(curl -sSfv http://$listen/hijack_res)"
17
28
  }
18
29
 
30
+ t_begin "env changed after response hijack" && {
31
+ env_c="$(curl -sSf http://$listen/normal_env_id)"
32
+ test x"$env_b" != x"$env_c"
33
+ }
34
+
35
+ t_begin "env continues to be reused between requests" && {
36
+ b="$(curl -sSf http://$listen/normal_env_id)"
37
+ test x"$env_c" = x"$b"
38
+ }
39
+
19
40
  t_begin "killing succeeds after hijack" && {
20
41
  kill $unicorn_pid
21
42
  }
@@ -4,7 +4,7 @@
4
4
  class TestDroplet < Test::Unit::TestCase
5
5
  def test_create_many_droplets
6
6
  now = Time.now.to_i
7
- tmp = (0..1024).map do |i|
7
+ (0..1024).each do |i|
8
8
  droplet = Unicorn::Worker.new(i)
9
9
  assert droplet.respond_to?(:tick)
10
10
  assert_equal 0, droplet.tick
@@ -34,7 +34,7 @@ def test_options
34
34
  assert_equal '', env['REQUEST_PATH']
35
35
  assert_equal '', env['PATH_INFO']
36
36
  assert_equal '*', env['REQUEST_URI']
37
- res = @lint.call(env)
37
+ assert_kind_of Array, @lint.call(env)
38
38
  end
39
39
 
40
40
  def test_absolute_uri_with_query
@@ -44,7 +44,7 @@ def test_absolute_uri_with_query
44
44
  assert_equal '/x', env['REQUEST_PATH']
45
45
  assert_equal '/x', env['PATH_INFO']
46
46
  assert_equal 'y=z', env['QUERY_STRING']
47
- res = @lint.call(env)
47
+ assert_kind_of Array, @lint.call(env)
48
48
  end
49
49
 
50
50
  def test_absolute_uri_with_fragment
@@ -55,7 +55,7 @@ def test_absolute_uri_with_fragment
55
55
  assert_equal '/x', env['PATH_INFO']
56
56
  assert_equal '', env['QUERY_STRING']
57
57
  assert_equal 'frag', env['FRAGMENT']
58
- res = @lint.call(env)
58
+ assert_kind_of Array, @lint.call(env)
59
59
  end
60
60
 
61
61
  def test_absolute_uri_with_query_and_fragment
@@ -66,7 +66,7 @@ def test_absolute_uri_with_query_and_fragment
66
66
  assert_equal '/x', env['PATH_INFO']
67
67
  assert_equal 'a=b', env['QUERY_STRING']
68
68
  assert_equal 'frag', env['FRAGMENT']
69
- res = @lint.call(env)
69
+ assert_kind_of Array, @lint.call(env)
70
70
  end
71
71
 
72
72
  def test_absolute_uri_unsupported_schemes
@@ -83,7 +83,7 @@ def test_x_forwarded_proto_https
83
83
  "Host: foo\r\n\r\n")
84
84
  env = @request.read(client)
85
85
  assert_equal "https", env['rack.url_scheme']
86
- res = @lint.call(env)
86
+ assert_kind_of Array, @lint.call(env)
87
87
  end
88
88
 
89
89
  def test_x_forwarded_proto_http
@@ -92,7 +92,7 @@ def test_x_forwarded_proto_http
92
92
  "Host: foo\r\n\r\n")
93
93
  env = @request.read(client)
94
94
  assert_equal "http", env['rack.url_scheme']
95
- res = @lint.call(env)
95
+ assert_kind_of Array, @lint.call(env)
96
96
  end
97
97
 
98
98
  def test_x_forwarded_proto_invalid
@@ -101,7 +101,7 @@ def test_x_forwarded_proto_invalid
101
101
  "Host: foo\r\n\r\n")
102
102
  env = @request.read(client)
103
103
  assert_equal "http", env['rack.url_scheme']
104
- res = @lint.call(env)
104
+ assert_kind_of Array, @lint.call(env)
105
105
  end
106
106
 
107
107
  def test_rack_lint_get
@@ -109,7 +109,7 @@ def test_rack_lint_get
109
109
  env = @request.read(client)
110
110
  assert_equal "http", env['rack.url_scheme']
111
111
  assert_equal '127.0.0.1', env['REMOTE_ADDR']
112
- res = @lint.call(env)
112
+ assert_kind_of Array, @lint.call(env)
113
113
  end
114
114
 
115
115
  def test_no_content_stringio
@@ -143,7 +143,7 @@ def test_rack_lint_put
143
143
  "abcde")
144
144
  env = @request.read(client)
145
145
  assert ! env.include?(:http_body)
146
- res = @lint.call(env)
146
+ assert_kind_of Array, @lint.call(env)
147
147
  end
148
148
 
149
149
  def test_rack_lint_big_put
@@ -177,6 +177,6 @@ def client.kgio_read!(*args)
177
177
  }
178
178
  assert_nil env['rack.input'].read(bs)
179
179
  env['rack.input'].rewind
180
- res = @lint.call(env)
180
+ assert_kind_of Array, @lint.call(env)
181
181
  end
182
182
  end
@@ -11,7 +11,7 @@
11
11
 
12
12
  Gem::Specification.new do |s|
13
13
  s.name = %q{unicorn}
14
- s.version = (ENV['VERSION'] || '5.3.1').dup
14
+ s.version = (ENV['VERSION'] || '5.4.0').dup
15
15
  s.authors = ['unicorn hackers']
16
16
  s.summary = 'Rack HTTP server for fast clients and Unix'
17
17
  s.description = File.read('README').split("\n\n")[1]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unicorn
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.1
4
+ version: 5.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - unicorn hackers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-03 00:00:00.000000000 Z
11
+ date: 2017-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -288,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
288
288
  version: '0'
289
289
  requirements: []
290
290
  rubyforge_project:
291
- rubygems_version: 2.6.13
291
+ rubygems_version: 2.7.3
292
292
  signing_key:
293
293
  specification_version: 4
294
294
  summary: Rack HTTP server for fast clients and Unix