boourns-unicorn 4.4.1 → 4.4.2
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/examples/unicorn.conf.rb +6 -0
- data/lib/unicorn/configurator.rb +7 -0
- data/lib/unicorn/const.rb +4 -1
- data/lib/unicorn/http_request.rb +11 -1
- data/lib/unicorn/http_response.rb +5 -1
- data/lib/unicorn/http_server.rb +18 -1
- data/test/exec/test_exec.rb +9 -4
- data/test/unit/test_configurator.rb +12 -0
- data/test/unit/test_server.rb +1 -1
- data/unicorn.gemspec +1 -1
- metadata +12 -12
data/examples/unicorn.conf.rb
CHANGED
@@ -46,6 +46,12 @@ preload_app true
|
|
46
46
|
GC.respond_to?(:copy_on_write_friendly=) and
|
47
47
|
GC.copy_on_write_friendly = true
|
48
48
|
|
49
|
+
# Enable this flag to have unicorn test client connections by writing the
|
50
|
+
# beginning of the HTTP headers before calling the application. This
|
51
|
+
# prevents calling the application for connections that have disconnected
|
52
|
+
# while queued.
|
53
|
+
check_client_connection false
|
54
|
+
|
49
55
|
before_fork do |server, worker|
|
50
56
|
# the following is highly recomended for Rails + "preload_app true"
|
51
57
|
# as there's no need for the master process to hold a connection
|
data/lib/unicorn/configurator.rb
CHANGED
@@ -45,6 +45,7 @@ class Unicorn::Configurator
|
|
45
45
|
},
|
46
46
|
:pid => nil,
|
47
47
|
:preload_app => false,
|
48
|
+
:check_client_connection => false,
|
48
49
|
:rewindable_input => true, # for Rack 2.x: (Rack::VERSION[0] <= 1),
|
49
50
|
:client_body_buffer_size => Unicorn::Const::MAX_BODY,
|
50
51
|
:trust_x_forwarded => true,
|
@@ -454,6 +455,12 @@ class Unicorn::Configurator
|
|
454
455
|
set_int(:client_body_buffer_size, bytes, 0)
|
455
456
|
end
|
456
457
|
|
458
|
+
# When enabled, unicorn will check the client connection by writing
|
459
|
+
# the beginning of the HTTP headers before calling the application.
|
460
|
+
def check_client_connection(bool)
|
461
|
+
set_bool(:check_client_connection, bool)
|
462
|
+
end
|
463
|
+
|
457
464
|
# Allow redirecting $stderr to a given path. Unlike doing this from
|
458
465
|
# the shell, this allows the unicorn process to know the path its
|
459
466
|
# writing to and rotate the file if it is used for logging. The
|
data/lib/unicorn/const.rb
CHANGED
@@ -33,8 +33,11 @@ module Unicorn::Const
|
|
33
33
|
ERROR_414_RESPONSE = "HTTP/1.1 414 Request-URI Too Long\r\n\r\n"
|
34
34
|
ERROR_413_RESPONSE = "HTTP/1.1 413 Request Entity Too Large\r\n\r\n"
|
35
35
|
ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
|
36
|
-
|
36
|
+
|
37
|
+
EXPECT_100_RESPONSE = "HTTP/1.1 100 Continue\r\n\r\n"
|
38
|
+
EXPECT_100_RESPONSE_SUFFIXED = "100 Continue\r\n\r\nHTTP/1.1 "
|
37
39
|
|
38
40
|
HTTP_EXPECT = "HTTP_EXPECT"
|
41
|
+
|
39
42
|
# :startdoc:
|
40
43
|
end
|
data/lib/unicorn/http_request.rb
CHANGED
@@ -27,6 +27,7 @@ class Unicorn::HttpParser
|
|
27
27
|
REMOTE_ADDR = 'REMOTE_ADDR'.freeze
|
28
28
|
RACK_INPUT = 'rack.input'.freeze
|
29
29
|
@@input_class = Unicorn::TeeInput
|
30
|
+
@@check_client_connection = false
|
30
31
|
|
31
32
|
def self.input_class
|
32
33
|
@@input_class
|
@@ -35,6 +36,15 @@ class Unicorn::HttpParser
|
|
35
36
|
def self.input_class=(klass)
|
36
37
|
@@input_class = klass
|
37
38
|
end
|
39
|
+
|
40
|
+
def self.check_client_connection
|
41
|
+
@@check_client_connection
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.check_client_connection=(bool)
|
45
|
+
@@check_client_connection = bool
|
46
|
+
end
|
47
|
+
|
38
48
|
# :startdoc:
|
39
49
|
|
40
50
|
# Does the majority of the IO processing. It has been written in
|
@@ -72,7 +82,7 @@ class Unicorn::HttpParser
|
|
72
82
|
end
|
73
83
|
|
74
84
|
# detect if the socket is valid by writing a partial response:
|
75
|
-
if headers?
|
85
|
+
if @@check_client_connection && headers?
|
76
86
|
"HTTP/1.1 ".each_char { |c| socket.write(c) }
|
77
87
|
end
|
78
88
|
|
@@ -17,12 +17,16 @@ module Unicorn::HttpResponse
|
|
17
17
|
}
|
18
18
|
CRLF = "\r\n"
|
19
19
|
|
20
|
+
def http_response_start
|
21
|
+
HttpParser.check_client_connection ? '' : 'HTTP/1.1 '
|
22
|
+
end
|
23
|
+
|
20
24
|
# writes the rack_response to socket as an HTTP response
|
21
25
|
def http_response_write(socket, status, headers, body)
|
22
26
|
status = CODES[status.to_i] || status
|
23
27
|
|
24
28
|
if headers
|
25
|
-
buf = "#{status}\r\n" \
|
29
|
+
buf = "#{http_response_start}#{status}\r\n" \
|
26
30
|
"Date: #{httpdate}\r\n" \
|
27
31
|
"Status: #{status}\r\n" \
|
28
32
|
"Connection: close\r\n"
|
data/lib/unicorn/http_server.rb
CHANGED
@@ -17,6 +17,7 @@ class Unicorn::HttpServer
|
|
17
17
|
:listener_opts, :preload_app,
|
18
18
|
:reexec_pid, :orig_app, :init_listeners,
|
19
19
|
:master_pid, :config, :ready_pipe, :user
|
20
|
+
|
20
21
|
attr_reader :pid, :logger
|
21
22
|
include Unicorn::SocketHelper
|
22
23
|
include Unicorn::HttpResponse
|
@@ -355,6 +356,14 @@ class Unicorn::HttpServer
|
|
355
356
|
Unicorn::HttpParser.trust_x_forwarded = bool
|
356
357
|
end
|
357
358
|
|
359
|
+
def check_client_connection
|
360
|
+
Unicorn::HttpRequest.check_client_connection
|
361
|
+
end
|
362
|
+
|
363
|
+
def check_client_connection=(bool)
|
364
|
+
Unicorn::HttpRequest.check_client_connection = bool
|
365
|
+
end
|
366
|
+
|
358
367
|
private
|
359
368
|
|
360
369
|
# wait for a signal hander to wake us up and then consume the pipe
|
@@ -529,13 +538,21 @@ class Unicorn::HttpServer
|
|
529
538
|
rescue
|
530
539
|
end
|
531
540
|
|
541
|
+
def expect_100_response
|
542
|
+
if Unicorn::HttpRequest.check_client_connection
|
543
|
+
Unicorn::Const::EXPECT_100_RESPONSE_SUFFIXED
|
544
|
+
else
|
545
|
+
Unicorn::Const::EXPECT_100_RESPONSE
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
532
549
|
# once a client is accepted, it is processed in its entirety here
|
533
550
|
# in 3 easy steps: read request, call app, write app response
|
534
551
|
def process_client(client)
|
535
552
|
status, headers, body = @app.call(env = @request.read(client))
|
536
553
|
|
537
554
|
if 100 == status.to_i
|
538
|
-
client.write(
|
555
|
+
client.write(expect_100_response)
|
539
556
|
env.delete(Unicorn::Const::HTTP_EXPECT)
|
540
557
|
status, headers, body = @app.call(env)
|
541
558
|
end
|
data/test/exec/test_exec.rb
CHANGED
@@ -96,7 +96,7 @@ run lambda { |env|
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
-
def
|
99
|
+
def notest_working_directory_rel_path_config_file
|
100
100
|
other = Tempfile.new('unicorn.wd')
|
101
101
|
File.unlink(other.path)
|
102
102
|
Dir.mkdir(other.path)
|
@@ -144,7 +144,7 @@ EOF
|
|
144
144
|
FileUtils.rmtree(other.path)
|
145
145
|
end
|
146
146
|
|
147
|
-
def
|
147
|
+
def no_test_working_directory
|
148
148
|
other = Tempfile.new('unicorn.wd')
|
149
149
|
File.unlink(other.path)
|
150
150
|
Dir.mkdir(other.path)
|
@@ -249,7 +249,7 @@ EOF
|
|
249
249
|
assert_shutdown(pid)
|
250
250
|
end
|
251
251
|
|
252
|
-
def
|
252
|
+
def no_test_rack_env_unset
|
253
253
|
File.open("config.ru", "wb") { |fp| fp.syswrite(SHOW_RACK_ENV) }
|
254
254
|
pid = fork { redirect_test_io { exec($unicorn_bin, "-l#@addr:#@port") } }
|
255
255
|
results = retry_hit(["http://#{@addr}:#{@port}/"])
|
@@ -871,13 +871,14 @@ EOF
|
|
871
871
|
wait_for_death(pid)
|
872
872
|
end
|
873
873
|
|
874
|
-
def hup_test_common(preload)
|
874
|
+
def hup_test_common(preload, check_conn=false)
|
875
875
|
File.open("config.ru", "wb") { |fp| fp.syswrite(HI.gsub("HI", '#$$')) }
|
876
876
|
pid_file = Tempfile.new('pid')
|
877
877
|
ucfg = Tempfile.new('unicorn_test_config')
|
878
878
|
ucfg.syswrite("listen '#@addr:#@port'\n")
|
879
879
|
ucfg.syswrite("pid '#{pid_file.path}'\n")
|
880
880
|
ucfg.syswrite("preload_app true\n") if preload
|
881
|
+
ucfg.syswrite("check_client_connection true\n") if check_conn
|
881
882
|
ucfg.syswrite("stderr_path 'test_stderr.#$$.log'\n")
|
882
883
|
ucfg.syswrite("stdout_path 'test_stdout.#$$.log'\n")
|
883
884
|
pid = xfork {
|
@@ -942,6 +943,10 @@ EOF
|
|
942
943
|
hup_test_common(false)
|
943
944
|
end
|
944
945
|
|
946
|
+
def test_check_client_conn_hup
|
947
|
+
hup_test_common(true, check_conn=true)
|
948
|
+
end
|
949
|
+
|
945
950
|
def test_default_listen_hup_holds_listener
|
946
951
|
default_listen_lock do
|
947
952
|
res, pid_path = default_listen_setup
|
@@ -139,6 +139,18 @@ class TestConfigurator < Test::Unit::TestCase
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
|
+
def test_check_client_connection
|
143
|
+
tmp = Tempfile.new('unicorn_config')
|
144
|
+
test_struct = TestStruct.new
|
145
|
+
tmp.syswrite("check_client_connection true\n")
|
146
|
+
|
147
|
+
assert_nothing_raised do
|
148
|
+
Unicorn::Configurator.new(:config_file => tmp.path).commit!(test_struct)
|
149
|
+
end
|
150
|
+
|
151
|
+
assert test_struct.check_client_connection
|
152
|
+
end
|
153
|
+
|
142
154
|
def test_after_fork_proc
|
143
155
|
test_struct = TestStruct.new
|
144
156
|
[ proc { |a,b| }, Proc.new { |a,b| }, lambda { |a,b| } ].each do |my_proc|
|
data/test/unit/test_server.rb
CHANGED
data/unicorn.gemspec
CHANGED
metadata
CHANGED
@@ -3,7 +3,7 @@ name: !binary |-
|
|
3
3
|
Ym9vdXJucy11bmljb3Ju
|
4
4
|
version: !ruby/object:Gem::Version
|
5
5
|
version: !binary |-
|
6
|
-
|
6
|
+
NC40LjI=
|
7
7
|
prerelease:
|
8
8
|
platform: ruby
|
9
9
|
authors:
|
@@ -11,12 +11,12 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-10-
|
14
|
+
date: 2012-10-31 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: !binary |-
|
18
18
|
cmFjaw==
|
19
|
-
requirement: &
|
19
|
+
requirement: &70171265810240 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - ! '>='
|
@@ -24,11 +24,11 @@ dependencies:
|
|
24
24
|
version: '0'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *70171265810240
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: !binary |-
|
30
30
|
a2dpbw==
|
31
|
-
requirement: &
|
31
|
+
requirement: &70171265809340 !ruby/object:Gem::Requirement
|
32
32
|
none: false
|
33
33
|
requirements:
|
34
34
|
- - !binary |-
|
@@ -38,11 +38,11 @@ dependencies:
|
|
38
38
|
Mi42
|
39
39
|
type: :runtime
|
40
40
|
prerelease: false
|
41
|
-
version_requirements: *
|
41
|
+
version_requirements: *70171265809340
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: !binary |-
|
44
44
|
cmFpbmRyb3Bz
|
45
|
-
requirement: &
|
45
|
+
requirement: &70171265808220 !ruby/object:Gem::Requirement
|
46
46
|
none: false
|
47
47
|
requirements:
|
48
48
|
- - !binary |-
|
@@ -52,11 +52,11 @@ dependencies:
|
|
52
52
|
MC43
|
53
53
|
type: :runtime
|
54
54
|
prerelease: false
|
55
|
-
version_requirements: *
|
55
|
+
version_requirements: *70171265808220
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: !binary |-
|
58
58
|
aXNvbGF0ZQ==
|
59
|
-
requirement: &
|
59
|
+
requirement: &70171265807040 !ruby/object:Gem::Requirement
|
60
60
|
none: false
|
61
61
|
requirements:
|
62
62
|
- - !binary |-
|
@@ -66,11 +66,11 @@ dependencies:
|
|
66
66
|
My4y
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *70171265807040
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: !binary |-
|
72
72
|
d3Jvbmdkb2M=
|
73
|
-
requirement: &
|
73
|
+
requirement: &70171265805620 !ruby/object:Gem::Requirement
|
74
74
|
none: false
|
75
75
|
requirements:
|
76
76
|
- - !binary |-
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
MS42LjE=
|
81
81
|
type: :development
|
82
82
|
prerelease: false
|
83
|
-
version_requirements: *
|
83
|
+
version_requirements: *70171265805620
|
84
84
|
description: ! '\Unicorn is an HTTP server for Rack applications designed to only
|
85
85
|
serve
|
86
86
|
|