unicorn 4.9.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Application_Timeouts +3 -3
- data/DESIGN +2 -4
- data/Documentation/unicorn.1.txt +8 -5
- data/Documentation/unicorn_rails.1.txt +2 -2
- data/FAQ +17 -8
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +6 -1
- data/ISSUES +20 -28
- data/KNOWN_ISSUES +9 -9
- data/Links +14 -17
- data/PHILOSOPHY +0 -6
- data/README +22 -17
- data/SIGNALS +1 -1
- data/Sandbox +4 -4
- data/TUNING +11 -8
- data/bin/unicorn +1 -1
- data/bin/unicorn_rails +1 -1
- data/examples/nginx.conf +10 -11
- data/examples/unicorn.conf.rb +1 -4
- data/ext/unicorn_http/extconf.rb +1 -0
- data/ext/unicorn_http/httpdate.c +1 -1
- data/ext/unicorn_http/unicorn_http.rl +89 -156
- data/lib/unicorn.rb +10 -18
- data/lib/unicorn/configurator.rb +17 -31
- data/lib/unicorn/const.rb +2 -25
- data/lib/unicorn/http_request.rb +22 -33
- data/lib/unicorn/http_response.rb +14 -32
- data/lib/unicorn/http_server.rb +129 -122
- data/lib/unicorn/socket_helper.rb +36 -72
- data/lib/unicorn/stream_input.rb +3 -3
- data/lib/unicorn/tmpio.rb +0 -5
- data/lib/unicorn/util.rb +2 -1
- data/lib/unicorn/worker.rb +3 -15
- data/t/hijack.ru +2 -1
- data/t/t0200-rack-hijack.sh +5 -2
- data/test/exec/test_exec.rb +52 -0
- data/test/test_helper.rb +3 -2
- data/test/unit/test_http_parser_ng.rb +16 -114
- data/test/unit/test_response.rb +19 -16
- data/test/unit/test_socket_helper.rb +1 -1
- data/unicorn.gemspec +10 -1
- metadata +10 -23
- 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/t/t0016-trust-x-forwarded-false.sh +0 -30
- data/t/t0017-trust-x-forwarded-true.sh +0 -30
- data/test/unit/test_http_parser_xftrust.rb +0 -38
- data/test/unit/test_sni_hostnames.rb +0 -47
data/lib/unicorn/ssl_client.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
# :stopdoc:
|
3
|
-
class Unicorn::SSLClient < Kgio::SSL
|
4
|
-
alias write kgio_write
|
5
|
-
alias close kgio_close
|
6
|
-
|
7
|
-
# this is no-op for now, to be fixed in kgio-monkey if people care
|
8
|
-
# about SSL support...
|
9
|
-
def shutdown(how = nil)
|
10
|
-
end
|
11
|
-
end
|
@@ -1,104 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
# :stopdoc:
|
3
|
-
# This module is included in Unicorn::Configurator
|
4
|
-
# :startdoc:
|
5
|
-
#
|
6
|
-
module Unicorn::SSLConfigurator
|
7
|
-
def ssl(&block)
|
8
|
-
ssl_require!
|
9
|
-
before = @set[:listeners].dup
|
10
|
-
opts = @set[:ssl_opts] = {}
|
11
|
-
yield
|
12
|
-
(@set[:listeners] - before).each do |address|
|
13
|
-
(@set[:listener_opts][address] ||= {})[:ssl_opts] = opts
|
14
|
-
end
|
15
|
-
ensure
|
16
|
-
@set.delete(:ssl_opts)
|
17
|
-
end
|
18
|
-
|
19
|
-
def ssl_certificate(file)
|
20
|
-
ssl_set(:ssl_certificate, file)
|
21
|
-
end
|
22
|
-
|
23
|
-
def ssl_certificate_key(file)
|
24
|
-
ssl_set(:ssl_certificate_key, file)
|
25
|
-
end
|
26
|
-
|
27
|
-
def ssl_client_certificate(file)
|
28
|
-
ssl_set(:ssl_client_certificate, file)
|
29
|
-
end
|
30
|
-
|
31
|
-
def ssl_dhparam(file)
|
32
|
-
ssl_set(:ssl_dhparam, file)
|
33
|
-
end
|
34
|
-
|
35
|
-
def ssl_ciphers(openssl_cipherlist_spec)
|
36
|
-
ssl_set(:ssl_ciphers, openssl_cipherlist_spec)
|
37
|
-
end
|
38
|
-
|
39
|
-
def ssl_crl(file)
|
40
|
-
ssl_set(:ssl_crl, file)
|
41
|
-
end
|
42
|
-
|
43
|
-
def ssl_prefer_server_ciphers(bool)
|
44
|
-
ssl_set(:ssl_prefer_server_ciphers, check_bool(bool))
|
45
|
-
end
|
46
|
-
|
47
|
-
def ssl_protocols(list)
|
48
|
-
ssl_set(:ssl_protocols, list)
|
49
|
-
end
|
50
|
-
|
51
|
-
def ssl_verify_client(on_off_optional)
|
52
|
-
ssl_set(:ssl_verify_client, on_off_optional)
|
53
|
-
end
|
54
|
-
|
55
|
-
def ssl_session_timeout(seconds)
|
56
|
-
ssl_set(:ssl_session_timeout, seconds)
|
57
|
-
end
|
58
|
-
|
59
|
-
def ssl_verify_depth(depth)
|
60
|
-
ssl_set(:ssl_verify_depth, depth)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Allows specifying an engine for OpenSSL to use. We have not been
|
64
|
-
# able to successfully test this feature due to a lack of hardware,
|
65
|
-
# Reports of success or patches to unicorn-public@bogomips.org is
|
66
|
-
# greatly appreciated.
|
67
|
-
def ssl_engine(engine)
|
68
|
-
ssl_warn_global(:ssl_engine)
|
69
|
-
ssl_require!
|
70
|
-
OpenSSL::Engine.load
|
71
|
-
OpenSSL::Engine.by_id(engine)
|
72
|
-
@set[:ssl_engine] = engine
|
73
|
-
end
|
74
|
-
|
75
|
-
def ssl_compression(bool)
|
76
|
-
# OpenSSL uses the SSL_OP_NO_COMPRESSION flag, Flipper follows suit
|
77
|
-
# with :ssl_no_compression, but we negate it to avoid exposing double
|
78
|
-
# negatives to the user.
|
79
|
-
ssl_set(:ssl_no_compression, check_bool(:ssl_compression, ! bool))
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
def ssl_warn_global(func) # :nodoc:
|
85
|
-
Hash === @set[:ssl_opts] or return
|
86
|
-
warn("`#{func}' affects all SSL contexts in this process, " \
|
87
|
-
"not just this block")
|
88
|
-
end
|
89
|
-
|
90
|
-
def ssl_set(key, value) # :nodoc:
|
91
|
-
cur = @set[:ssl_opts]
|
92
|
-
Hash === cur or
|
93
|
-
raise ArgumentError, "#{key} must be called inside an `ssl' block"
|
94
|
-
cur[key] = value
|
95
|
-
end
|
96
|
-
|
97
|
-
def ssl_require! # :nodoc:
|
98
|
-
require "flipper"
|
99
|
-
require "unicorn/ssl_client"
|
100
|
-
rescue LoadError
|
101
|
-
warn "install 'kgio-monkey' for SSL support"
|
102
|
-
raise
|
103
|
-
end
|
104
|
-
end
|
data/lib/unicorn/ssl_server.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
# :stopdoc:
|
3
|
-
# this module is meant to be included in Unicorn::HttpServer
|
4
|
-
# It is an implementation detail and NOT meant for users.
|
5
|
-
module Unicorn::SSLServer
|
6
|
-
attr_accessor :ssl_engine
|
7
|
-
|
8
|
-
def ssl_enable!
|
9
|
-
sni_hostnames = rack_sni_hostnames(@app)
|
10
|
-
seen = {} # we map a single SSLContext to multiple listeners
|
11
|
-
listener_ctx = {}
|
12
|
-
@listener_opts.each do |address, address_opts|
|
13
|
-
ssl_opts = address_opts[:ssl_opts] or next
|
14
|
-
listener_ctx[address] = seen[ssl_opts.object_id] ||= begin
|
15
|
-
unless sni_hostnames.empty?
|
16
|
-
ssl_opts = ssl_opts.dup
|
17
|
-
ssl_opts[:sni_hostnames] = sni_hostnames
|
18
|
-
end
|
19
|
-
ctx = Flipper.ssl_context(ssl_opts)
|
20
|
-
# FIXME: make configurable
|
21
|
-
ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF
|
22
|
-
ctx
|
23
|
-
end
|
24
|
-
end
|
25
|
-
Unicorn::HttpServer::LISTENERS.each do |listener|
|
26
|
-
ctx = listener_ctx[sock_name(listener)] or next
|
27
|
-
listener.extend(Kgio::SSLServer)
|
28
|
-
listener.ssl_ctx = ctx
|
29
|
-
listener.kgio_ssl_class = Unicorn::SSLClient
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# ugh, this depends on Rack internals...
|
34
|
-
def rack_sni_hostnames(rack_app) # :nodoc:
|
35
|
-
hostnames = {}
|
36
|
-
if Rack::URLMap === rack_app
|
37
|
-
mapping = rack_app.instance_variable_get(:@mapping)
|
38
|
-
mapping.each { |hostname,_,_,_| hostnames[hostname] = true }
|
39
|
-
end
|
40
|
-
hostnames.keys
|
41
|
-
end
|
42
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
#!/bin/sh
|
2
|
-
. ./test-lib.sh
|
3
|
-
t_plan 5 "trust_x_forwarded=false configuration test"
|
4
|
-
|
5
|
-
t_begin "setup and start" && {
|
6
|
-
unicorn_setup
|
7
|
-
echo "trust_x_forwarded false" >> $unicorn_config
|
8
|
-
unicorn -D -c $unicorn_config env.ru
|
9
|
-
unicorn_wait_start
|
10
|
-
}
|
11
|
-
|
12
|
-
t_begin "spoofed request with X-Forwarded-Proto does not trigger" && {
|
13
|
-
curl -H 'X-Forwarded-Proto: https' http://$listen/ | \
|
14
|
-
grep -F '"rack.url_scheme"=>"http"'
|
15
|
-
}
|
16
|
-
|
17
|
-
t_begin "spoofed request with X-Forwarded-SSL does not trigger" && {
|
18
|
-
curl -H 'X-Forwarded-SSL: on' http://$listen/ | \
|
19
|
-
grep -F '"rack.url_scheme"=>"http"'
|
20
|
-
}
|
21
|
-
|
22
|
-
t_begin "killing succeeds" && {
|
23
|
-
kill $unicorn_pid
|
24
|
-
}
|
25
|
-
|
26
|
-
t_begin "check stderr has no errors" && {
|
27
|
-
check_stderr
|
28
|
-
}
|
29
|
-
|
30
|
-
t_done
|
@@ -1,30 +0,0 @@
|
|
1
|
-
#!/bin/sh
|
2
|
-
. ./test-lib.sh
|
3
|
-
t_plan 5 "trust_x_forwarded=true configuration test"
|
4
|
-
|
5
|
-
t_begin "setup and start" && {
|
6
|
-
unicorn_setup
|
7
|
-
echo "trust_x_forwarded true " >> $unicorn_config
|
8
|
-
unicorn -D -c $unicorn_config env.ru
|
9
|
-
unicorn_wait_start
|
10
|
-
}
|
11
|
-
|
12
|
-
t_begin "spoofed request with X-Forwarded-Proto sets 'https'" && {
|
13
|
-
curl -H 'X-Forwarded-Proto: https' http://$listen/ | \
|
14
|
-
grep -F '"rack.url_scheme"=>"https"'
|
15
|
-
}
|
16
|
-
|
17
|
-
t_begin "spoofed request with X-Forwarded-SSL sets 'https'" && {
|
18
|
-
curl -H 'X-Forwarded-SSL: on' http://$listen/ | \
|
19
|
-
grep -F '"rack.url_scheme"=>"https"'
|
20
|
-
}
|
21
|
-
|
22
|
-
t_begin "killing succeeds" && {
|
23
|
-
kill $unicorn_pid
|
24
|
-
}
|
25
|
-
|
26
|
-
t_begin "check stderr has no errors" && {
|
27
|
-
check_stderr
|
28
|
-
}
|
29
|
-
|
30
|
-
t_done
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
require './test/test_helper'
|
3
|
-
|
4
|
-
include Unicorn
|
5
|
-
|
6
|
-
class HttpParserXFTrustTest < Test::Unit::TestCase
|
7
|
-
def setup
|
8
|
-
assert HttpParser.trust_x_forwarded?
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_xf_trust_false_xfp
|
12
|
-
HttpParser.trust_x_forwarded = false
|
13
|
-
parser = HttpParser.new
|
14
|
-
parser.buf << "GET / HTTP/1.1\r\nHost: foo:\r\n" \
|
15
|
-
"X-Forwarded-Proto: https\r\n\r\n"
|
16
|
-
env = parser.parse
|
17
|
-
assert_kind_of Hash, env
|
18
|
-
assert_equal 'foo', env['SERVER_NAME']
|
19
|
-
assert_equal '80', env['SERVER_PORT']
|
20
|
-
assert_equal 'http', env['rack.url_scheme']
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_xf_trust_false_xfs
|
24
|
-
HttpParser.trust_x_forwarded = false
|
25
|
-
parser = HttpParser.new
|
26
|
-
parser.buf << "GET / HTTP/1.1\r\nHost: foo:\r\n" \
|
27
|
-
"X-Forwarded-SSL: on\r\n\r\n"
|
28
|
-
env = parser.parse
|
29
|
-
assert_kind_of Hash, env
|
30
|
-
assert_equal 'foo', env['SERVER_NAME']
|
31
|
-
assert_equal '80', env['SERVER_PORT']
|
32
|
-
assert_equal 'http', env['rack.url_scheme']
|
33
|
-
end
|
34
|
-
|
35
|
-
def teardown
|
36
|
-
HttpParser.trust_x_forwarded = true
|
37
|
-
end
|
38
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
require "test/unit"
|
3
|
-
require "unicorn"
|
4
|
-
|
5
|
-
# this tests an implementation detail, it may change so this test
|
6
|
-
# can be removed later.
|
7
|
-
class TestSniHostnames < Test::Unit::TestCase
|
8
|
-
include Unicorn::SSLServer
|
9
|
-
|
10
|
-
def setup
|
11
|
-
GC.start
|
12
|
-
end
|
13
|
-
|
14
|
-
def teardown
|
15
|
-
GC.start
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_host_name_detect_one
|
19
|
-
app = Rack::Builder.new do
|
20
|
-
map "http://sni1.example.com/" do
|
21
|
-
use Rack::ContentLength
|
22
|
-
use Rack::ContentType, "text/plain"
|
23
|
-
run lambda { |env| [ 200, {}, [] ] }
|
24
|
-
end
|
25
|
-
end.to_app
|
26
|
-
hostnames = rack_sni_hostnames(app)
|
27
|
-
assert hostnames.include?("sni1.example.com")
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_host_name_detect_multiple
|
31
|
-
app = Rack::Builder.new do
|
32
|
-
map "http://sni2.example.com/" do
|
33
|
-
use Rack::ContentLength
|
34
|
-
use Rack::ContentType, "text/plain"
|
35
|
-
run lambda { |env| [ 200, {}, [] ] }
|
36
|
-
end
|
37
|
-
map "http://sni3.example.com/" do
|
38
|
-
use Rack::ContentLength
|
39
|
-
use Rack::ContentType, "text/plain"
|
40
|
-
run lambda { |env| [ 200, {}, [] ] }
|
41
|
-
end
|
42
|
-
end.to_app
|
43
|
-
hostnames = rack_sni_hostnames(app)
|
44
|
-
assert hostnames.include?("sni2.example.com")
|
45
|
-
assert hostnames.include?("sni3.example.com")
|
46
|
-
end
|
47
|
-
end
|