unicorn 3.3.1 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.wrongdoc.yml +2 -2
- data/GIT-VERSION-GEN +1 -1
- data/KNOWN_ISSUES +17 -7
- data/README +2 -2
- data/Rakefile +3 -2
- data/examples/nginx.conf +12 -8
- data/ext/unicorn_http/unicorn_http.rl +12 -1
- data/ext/unicorn_http/unicorn_http_common.rl +1 -1
- data/lib/unicorn/app/exec_cgi.rb +25 -22
- data/lib/unicorn/configurator.rb +17 -11
- data/lib/unicorn/const.rb +2 -2
- data/lib/unicorn/http_response.rb +1 -1
- data/lib/unicorn/http_server.rb +0 -1
- data/lib/unicorn/socket_helper.rb +33 -19
- data/lib/unicorn/tee_input.rb +1 -1
- data/script/isolate_for_tests +1 -1
- data/t/bin/unused_listen +2 -15
- data/test/exec/test_exec.rb +1 -2
- data/test/rails/test_rails.rb +1 -1
- data/test/test_helper.rb +3 -16
- data/test/unit/test_configurator.rb +8 -0
- data/test/unit/test_http_parser.rb +294 -130
- data/test/unit/test_http_parser_ng.rb +147 -126
- data/test/unit/test_request.rb +3 -3
- data/test/unit/test_response.rb +0 -12
- data/test/unit/test_server.rb +4 -7
- data/test/unit/test_tee_input.rb +25 -21
- data/test/unit/test_upload.rb +10 -2
- data/unicorn.gemspec +2 -2
- metadata +12 -12
data/test/unit/test_request.rb
CHANGED
@@ -121,7 +121,7 @@ class RequestTest < Test::Unit::TestCase
|
|
121
121
|
|
122
122
|
def test_no_content_stringio
|
123
123
|
client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
|
124
|
-
|
124
|
+
env = nil
|
125
125
|
assert_nothing_raised { env = @request.read(client) }
|
126
126
|
assert_equal StringIO, env['rack.input'].class
|
127
127
|
end
|
@@ -130,7 +130,7 @@ class RequestTest < Test::Unit::TestCase
|
|
130
130
|
client = MockRequest.new("PUT / HTTP/1.1\r\n" \
|
131
131
|
"Content-Length: 0\r\n" \
|
132
132
|
"Host: foo\r\n\r\n")
|
133
|
-
|
133
|
+
env = nil
|
134
134
|
assert_nothing_raised { env = @request.read(client) }
|
135
135
|
assert_equal StringIO, env['rack.input'].class
|
136
136
|
end
|
@@ -139,7 +139,7 @@ class RequestTest < Test::Unit::TestCase
|
|
139
139
|
client = MockRequest.new("PUT / HTTP/1.1\r\n" \
|
140
140
|
"Content-Length: 1\r\n" \
|
141
141
|
"Host: foo\r\n\r\n")
|
142
|
-
|
142
|
+
env = nil
|
143
143
|
assert_nothing_raised { env = @request.read(client) }
|
144
144
|
assert_equal Unicorn::TeeInput, env['rack.input'].class
|
145
145
|
end
|
data/test/unit/test_response.rb
CHANGED
@@ -73,18 +73,6 @@ class ResponseTest < Test::Unit::TestCase
|
|
73
73
|
assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size
|
74
74
|
end
|
75
75
|
|
76
|
-
# we always favor the code returned by the application, since "Status"
|
77
|
-
# in the header hash is not allowed by Rack (but not every app is
|
78
|
-
# fully Rack-compliant).
|
79
|
-
def test_status_header_ignores_app_hash
|
80
|
-
out = StringIO.new
|
81
|
-
header_hash = {"X-Whatever" => "stuff", 'StaTus' => "666" }
|
82
|
-
http_response_write(out,200, header_hash, [])
|
83
|
-
assert ! out.closed?
|
84
|
-
assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size
|
85
|
-
assert_equal 1, out.string.split(/\r\n/).grep(/^Status:/i).size
|
86
|
-
end
|
87
|
-
|
88
76
|
def test_body_closed
|
89
77
|
expect_body = %w(1 2 3 4).join("\n")
|
90
78
|
body = StringIO.new(expect_body)
|
data/test/unit/test_server.rb
CHANGED
@@ -10,7 +10,7 @@ require 'test/test_helper'
|
|
10
10
|
|
11
11
|
include Unicorn
|
12
12
|
|
13
|
-
class TestHandler
|
13
|
+
class TestHandler
|
14
14
|
|
15
15
|
def call(env)
|
16
16
|
while env['rack.input'].read(4096)
|
@@ -19,7 +19,7 @@ class TestHandler
|
|
19
19
|
rescue Unicorn::ClientShutdown, Unicorn::HttpParserError => e
|
20
20
|
$stderr.syswrite("#{e.class}: #{e.message} #{e.backtrace.empty?}\n")
|
21
21
|
raise e
|
22
|
-
|
22
|
+
end
|
23
23
|
end
|
24
24
|
|
25
25
|
|
@@ -169,7 +169,6 @@ class WebServerTest < Test::Unit::TestCase
|
|
169
169
|
|
170
170
|
def test_client_malformed_body
|
171
171
|
sock = nil
|
172
|
-
buf = nil
|
173
172
|
bs = 15653984
|
174
173
|
assert_nothing_raised do
|
175
174
|
sock = TCPSocket.new('127.0.0.1', @port)
|
@@ -271,7 +270,7 @@ class WebServerTest < Test::Unit::TestCase
|
|
271
270
|
def test_file_streamed_request
|
272
271
|
body = "a" * (Unicorn::Const::MAX_BODY * 2)
|
273
272
|
long = "PUT /test HTTP/1.1\r\nContent-length: #{body.length}\r\n\r\n" + body
|
274
|
-
do_test(long, Unicorn::Const::CHUNK_SIZE * 2 -400)
|
273
|
+
do_test(long, Unicorn::Const::CHUNK_SIZE * 2 - 400)
|
275
274
|
end
|
276
275
|
|
277
276
|
def test_file_streamed_request_bad_body
|
@@ -279,13 +278,11 @@ class WebServerTest < Test::Unit::TestCase
|
|
279
278
|
long = "GET /test HTTP/1.1\r\nContent-ength: #{body.length}\r\n\r\n" + body
|
280
279
|
assert_raises(EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::EINVAL,
|
281
280
|
Errno::EBADF) {
|
282
|
-
do_test(long, Unicorn::Const::CHUNK_SIZE * 2 -400)
|
281
|
+
do_test(long, Unicorn::Const::CHUNK_SIZE * 2 - 400)
|
283
282
|
}
|
284
283
|
end
|
285
284
|
|
286
285
|
def test_listener_names
|
287
286
|
assert_equal [ "127.0.0.1:#@port" ], Unicorn.listener_names
|
288
287
|
end
|
289
|
-
|
290
288
|
end
|
291
|
-
|
data/test/unit/test_tee_input.rb
CHANGED
@@ -12,7 +12,6 @@ class TestTeeInput < Test::Unit::TestCase
|
|
12
12
|
|
13
13
|
def setup
|
14
14
|
@rs = $/
|
15
|
-
@env = {}
|
16
15
|
@rd, @wr = Kgio::UNIXSocket.pair
|
17
16
|
@rd.sync = @wr.sync = true
|
18
17
|
@start_pid = $$
|
@@ -154,12 +153,12 @@ class TestTeeInput < Test::Unit::TestCase
|
|
154
153
|
|
155
154
|
def test_chunked
|
156
155
|
@parser = Unicorn::HttpParser.new
|
157
|
-
@buf
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
assert_equal "", @buf
|
156
|
+
@parser.buf << "POST / HTTP/1.1\r\n" \
|
157
|
+
"Host: localhost\r\n" \
|
158
|
+
"Transfer-Encoding: chunked\r\n" \
|
159
|
+
"\r\n"
|
160
|
+
assert @parser.parse
|
161
|
+
assert_equal "", @parser.buf
|
163
162
|
|
164
163
|
pid = fork {
|
165
164
|
@rd.close
|
@@ -189,12 +188,13 @@ class TestTeeInput < Test::Unit::TestCase
|
|
189
188
|
|
190
189
|
def test_chunked_ping_pong
|
191
190
|
@parser = Unicorn::HttpParser.new
|
192
|
-
|
191
|
+
buf = @parser.buf
|
192
|
+
buf << "POST / HTTP/1.1\r\n" \
|
193
193
|
"Host: localhost\r\n" \
|
194
194
|
"Transfer-Encoding: chunked\r\n" \
|
195
195
|
"\r\n"
|
196
|
-
|
197
|
-
assert_equal "",
|
196
|
+
assert @parser.parse
|
197
|
+
assert_equal "", buf
|
198
198
|
chunks = %w(aa bbb cccc dddd eeee)
|
199
199
|
rd, wr = IO.pipe
|
200
200
|
|
@@ -219,13 +219,14 @@ class TestTeeInput < Test::Unit::TestCase
|
|
219
219
|
|
220
220
|
def test_chunked_with_trailer
|
221
221
|
@parser = Unicorn::HttpParser.new
|
222
|
-
|
222
|
+
buf = @parser.buf
|
223
|
+
buf << "POST / HTTP/1.1\r\n" \
|
223
224
|
"Host: localhost\r\n" \
|
224
225
|
"Trailer: Hello\r\n" \
|
225
226
|
"Transfer-Encoding: chunked\r\n" \
|
226
227
|
"\r\n"
|
227
|
-
|
228
|
-
assert_equal "",
|
228
|
+
assert @parser.parse
|
229
|
+
assert_equal "", buf
|
229
230
|
|
230
231
|
pid = fork {
|
231
232
|
@rd.close
|
@@ -239,7 +240,7 @@ class TestTeeInput < Test::Unit::TestCase
|
|
239
240
|
assert_nil ti.len
|
240
241
|
assert ! @parser.body_eof?
|
241
242
|
assert_equal 25, ti.size
|
242
|
-
assert_equal "World", @env['HTTP_HELLO']
|
243
|
+
assert_equal "World", @parser.env['HTTP_HELLO']
|
243
244
|
status = nil
|
244
245
|
assert_nothing_raised { pid, status = Process.waitpid2(pid) }
|
245
246
|
assert status.success?
|
@@ -247,13 +248,14 @@ class TestTeeInput < Test::Unit::TestCase
|
|
247
248
|
|
248
249
|
def test_chunked_and_size_slow
|
249
250
|
@parser = Unicorn::HttpParser.new
|
250
|
-
|
251
|
+
buf = @parser.buf
|
252
|
+
buf << "POST / HTTP/1.1\r\n" \
|
251
253
|
"Host: localhost\r\n" \
|
252
254
|
"Trailer: Hello\r\n" \
|
253
255
|
"Transfer-Encoding: chunked\r\n" \
|
254
256
|
"\r\n"
|
255
|
-
|
256
|
-
assert_equal "",
|
257
|
+
assert @parser.parse
|
258
|
+
assert_equal "", buf
|
257
259
|
|
258
260
|
@wr.write("9\r\nabcde")
|
259
261
|
ti = TeeInput.new(@rd, @parser)
|
@@ -264,7 +266,7 @@ class TestTeeInput < Test::Unit::TestCase
|
|
264
266
|
assert_equal 9, ti.size
|
265
267
|
assert_equal "fghi", ti.read(9)
|
266
268
|
assert_equal nil, ti.read(9)
|
267
|
-
assert_equal "World", @env['HTTP_HELLO']
|
269
|
+
assert_equal "World", @parser.env['HTTP_HELLO']
|
268
270
|
end
|
269
271
|
|
270
272
|
def test_gets_read_mix
|
@@ -280,12 +282,14 @@ private
|
|
280
282
|
def init_request(body, size = nil)
|
281
283
|
@parser = Unicorn::HttpParser.new
|
282
284
|
body = body.to_s.freeze
|
283
|
-
|
285
|
+
buf = @parser.buf
|
286
|
+
buf << "POST / HTTP/1.1\r\n" \
|
284
287
|
"Host: localhost\r\n" \
|
285
288
|
"Content-Length: #{size || body.size}\r\n" \
|
286
289
|
"\r\n#{body}"
|
287
|
-
|
288
|
-
assert_equal body,
|
290
|
+
assert @parser.parse
|
291
|
+
assert_equal body, buf
|
292
|
+
@buf = buf
|
289
293
|
@parser
|
290
294
|
end
|
291
295
|
|
data/test/unit/test_upload.rb
CHANGED
@@ -145,8 +145,14 @@ class UploadTest < Test::Unit::TestCase
|
|
145
145
|
end
|
146
146
|
|
147
147
|
def test_put_excessive_overwrite_closed
|
148
|
+
tmp = Tempfile.new('overwrite_check')
|
149
|
+
tmp.sync = true
|
148
150
|
start_server(lambda { |env|
|
149
|
-
|
151
|
+
nr = 0
|
152
|
+
while buf = env['rack.input'].read(65536)
|
153
|
+
nr += buf.size
|
154
|
+
end
|
155
|
+
tmp.write(nr.to_s)
|
150
156
|
[ 200, @hdr, [] ]
|
151
157
|
})
|
152
158
|
sock = TCPSocket.new(@addr, @port)
|
@@ -157,7 +163,9 @@ class UploadTest < Test::Unit::TestCase
|
|
157
163
|
assert_raise(Errno::ECONNRESET, Errno::EPIPE) do
|
158
164
|
::Unicorn::Const::CHUNK_SIZE.times { sock.syswrite(buf) }
|
159
165
|
end
|
160
|
-
|
166
|
+
assert_nothing_raised { sock.gets }
|
167
|
+
tmp.rewind
|
168
|
+
assert_equal length, tmp.read.to_i
|
161
169
|
end
|
162
170
|
|
163
171
|
# Despite reading numerous articles and inspecting the 1.9.1-p0 C
|
data/unicorn.gemspec
CHANGED
@@ -35,10 +35,10 @@ Gem::Specification.new do |s|
|
|
35
35
|
# commented out. Nevertheless, upgrading to Rails 2.3.4 or later is
|
36
36
|
# *strongly* recommended for security reasons.
|
37
37
|
s.add_dependency(%q<rack>)
|
38
|
-
s.add_dependency(%q<kgio>, '~> 2.
|
38
|
+
s.add_dependency(%q<kgio>, '~> 2.2')
|
39
39
|
|
40
40
|
s.add_development_dependency('isolate', '~> 3.0.0')
|
41
|
-
s.add_development_dependency('wrongdoc', '~> 1.
|
41
|
+
s.add_development_dependency('wrongdoc', '~> 1.5')
|
42
42
|
|
43
43
|
# s.licenses = %w(GPLv2 Ruby) # licenses= method is not in older RubyGems
|
44
44
|
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:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 3.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 3.4.0
|
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: 2011-
|
18
|
+
date: 2011-02-04 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -40,11 +40,11 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
hash:
|
43
|
+
hash: 7
|
44
44
|
segments:
|
45
45
|
- 2
|
46
|
-
-
|
47
|
-
version: "2.
|
46
|
+
- 2
|
47
|
+
version: "2.2"
|
48
48
|
type: :runtime
|
49
49
|
version_requirements: *id002
|
50
50
|
- !ruby/object:Gem::Dependency
|
@@ -71,11 +71,11 @@ dependencies:
|
|
71
71
|
requirements:
|
72
72
|
- - ~>
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
hash:
|
74
|
+
hash: 5
|
75
75
|
segments:
|
76
76
|
- 1
|
77
|
-
-
|
78
|
-
version: "1.
|
77
|
+
- 5
|
78
|
+
version: "1.5"
|
79
79
|
type: :development
|
80
80
|
version_requirements: *id004
|
81
81
|
description: |-
|
@@ -389,7 +389,7 @@ rdoc_options:
|
|
389
389
|
- -t
|
390
390
|
- "Unicorn: Rack HTTP server for fast clients and Unix"
|
391
391
|
- -W
|
392
|
-
- http://
|
392
|
+
- http://bogomips.org/unicorn.git/tree/%s
|
393
393
|
require_paths:
|
394
394
|
- lib
|
395
395
|
- ext
|