unicorn 5.3.1 → 5.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +5 -0
- data/ISSUES +5 -0
- data/ext/unicorn_http/unicorn_http.rl +15 -0
- data/lib/unicorn.rb +4 -1
- data/lib/unicorn/configurator.rb +1 -1
- data/lib/unicorn/http_request.rb +1 -0
- data/lib/unicorn/http_response.rb +3 -2
- data/lib/unicorn/http_server.rb +2 -3
- data/lib/unicorn/socket_helper.rb +1 -1
- data/t/hijack.ru +12 -0
- data/t/t0200-rack-hijack.sh +22 -1
- data/test/unit/test_droplet.rb +1 -1
- data/test/unit/test_request.rb +10 -10
- data/unicorn.gemspec +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2a53c6f0287f74563b46ac07e96cbb709562e4f26bdbf46ae1cb904a3e345828
|
4
|
+
data.tar.gz: 0724bceedd3b964168081c4a12c8f9eb04611013f6ef72593d6db63bd31cccf1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0b91ca7dd6cc2e52f7eed8fdd30547dbcd3c81939c1df495e612ff94a544dc589cd3d3cd9e4c17206f135ac7e3ef763ecfa80bebacce42960df7f93a679d091
|
7
|
+
data.tar.gz: 9eba1d1fefa858d93524ff73c77b8a239b9e50abb6f8bac840d436afebd27608dcad6a8d7f49c35dd44f2577563fdbdc898541efa312b7f5953c155cf1eaf057
|
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -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
|
|
data/lib/unicorn.rb
CHANGED
@@ -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
|
-
|
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
|
|
data/lib/unicorn/configurator.rb
CHANGED
@@ -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
|
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" \
|
data/lib/unicorn/http_request.rb
CHANGED
@@ -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
|
-
|
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) }
|
data/lib/unicorn/http_server.rb
CHANGED
@@ -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
|
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
|
119
|
+
sock = if address.start_with?('/')
|
120
120
|
if File.exist?(address)
|
121
121
|
if File.socket?(address)
|
122
122
|
begin
|
data/t/hijack.ru
CHANGED
@@ -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
|
}
|
data/t/t0200-rack-hijack.sh
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
. ./test-lib.sh
|
3
|
-
t_plan
|
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
|
}
|
data/test/unit/test_droplet.rb
CHANGED
data/test/unit/test_request.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
180
|
+
assert_kind_of Array, @lint.call(env)
|
181
181
|
end
|
182
182
|
end
|
data/unicorn.gemspec
CHANGED
@@ -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.
|
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.
|
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-
|
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.
|
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
|