unicorn-camilo 4.8.2.5.19 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.document +0 -1
  3. data/.gitignore +2 -2
  4. data/{.wrongdoc.yml → .olddoc.yml} +7 -2
  5. data/Documentation/unicorn.1.txt +9 -2
  6. data/Documentation/unicorn_rails.1.txt +2 -2
  7. data/FAQ +9 -1
  8. data/GIT-VERSION-GEN +1 -1
  9. data/GNUmakefile +31 -46
  10. data/HACKING +13 -27
  11. data/ISSUES +80 -16
  12. data/KNOWN_ISSUES +10 -10
  13. data/Links +10 -7
  14. data/PHILOSOPHY +1 -1
  15. data/README +8 -13
  16. data/Rakefile +0 -44
  17. data/Sandbox +1 -1
  18. data/TUNING +6 -3
  19. data/archive/.gitignore +3 -0
  20. data/archive/slrnpull.conf +4 -0
  21. data/bin/unicorn +1 -1
  22. data/bin/unicorn_rails +1 -1
  23. data/examples/unicorn.conf.rb +11 -0
  24. data/ext/unicorn_http/httpdate.c +1 -1
  25. data/ext/unicorn_http/unicorn_http.rl +48 -150
  26. data/lib/unicorn.rb +9 -15
  27. data/lib/unicorn/configurator.rb +3 -20
  28. data/lib/unicorn/const.rb +2 -25
  29. data/lib/unicorn/http_request.rb +4 -1
  30. data/lib/unicorn/http_response.rb +1 -3
  31. data/lib/unicorn/http_server.rb +85 -86
  32. data/lib/unicorn/socket_helper.rb +33 -67
  33. data/lib/unicorn/tee_input.rb +8 -1
  34. data/lib/unicorn/tmpio.rb +2 -4
  35. data/lib/unicorn/util.rb +1 -0
  36. data/lib/unicorn/worker.rb +1 -13
  37. data/t/GNUmakefile +1 -5
  38. data/t/README +1 -1
  39. data/t/t0002-parser-error.sh +3 -3
  40. data/test/exec/test_exec.rb +1 -1
  41. data/test/test_helper.rb +2 -2
  42. data/test/unit/test_http_parser.rb +3 -3
  43. data/test/unit/test_http_parser_ng.rb +8 -117
  44. data/test/unit/test_request.rb +1 -1
  45. data/test/unit/test_response.rb +3 -9
  46. data/test/unit/test_server.rb +3 -3
  47. data/test/unit/test_signals.rb +1 -1
  48. data/test/unit/test_socket_helper.rb +5 -5
  49. data/test/unit/test_tee_input.rb +10 -0
  50. data/test/unit/test_upload.rb +1 -1
  51. data/test/unit/test_util.rb +1 -1
  52. data/unicorn.gemspec +7 -10
  53. metadata +15 -33
  54. data/examples/git.ru +0 -13
  55. data/lib/unicorn/app/exec_cgi.rb +0 -154
  56. data/lib/unicorn/app/inetd.rb +0 -109
  57. data/lib/unicorn/ssl_client.rb +0 -11
  58. data/lib/unicorn/ssl_configurator.rb +0 -104
  59. data/lib/unicorn/ssl_server.rb +0 -42
  60. data/local.mk.sample +0 -59
  61. data/script/isolate_for_tests +0 -31
  62. data/t/t0016-trust-x-forwarded-false.sh +0 -30
  63. data/t/t0017-trust-x-forwarded-true.sh +0 -30
  64. data/test/unit/test_http_parser_xftrust.rb +0 -38
  65. data/test/unit/test_sni_hostnames.rb +0 -47
@@ -4,7 +4,7 @@
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
5
  # the GPLv2+ (GPLv3+ preferred)
6
6
 
7
- require 'test/test_helper'
7
+ require './test/test_helper'
8
8
 
9
9
  include Unicorn
10
10
 
@@ -1,13 +1,13 @@
1
1
  # -*- encoding: binary -*-
2
2
 
3
- # Copyright (c) 2005 Zed A. Shaw
3
+ # Copyright (c) 2005 Zed A. Shaw
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
5
  # the GPLv2+ (GPLv3+ preferred)
6
6
  #
7
- # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
7
+ # Additional work donated by contributors. See git history
8
8
  # for more information.
9
9
 
10
- require 'test/test_helper'
10
+ require './test/test_helper'
11
11
  require 'time'
12
12
 
13
13
  include Unicorn
@@ -38,7 +38,6 @@ class ResponseTest < Test::Unit::TestCase
38
38
  http_response_write(out,'200', {}, [])
39
39
  assert ! out.closed?
40
40
  assert out.length > 0, "output didn't have data"
41
- assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/).size
42
41
  end
43
42
 
44
43
  def test_response_200
@@ -71,7 +70,6 @@ class ResponseTest < Test::Unit::TestCase
71
70
  out = StringIO.new
72
71
  http_response_write(out,200, {"X-Whatever" => "stuff"}, [])
73
72
  assert ! out.closed?
74
- assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size
75
73
  end
76
74
 
77
75
  def test_body_closed
@@ -91,9 +89,5 @@ class ResponseTest < Test::Unit::TestCase
91
89
  assert ! out.closed?
92
90
  headers = out.string.split(/\r\n\r\n/).first.split(/\r\n/)
93
91
  assert %r{\AHTTP/\d\.\d 666 I AM THE BEAST\z}.match(headers[0])
94
- status = headers.grep(/\AStatus:/i).first
95
- assert status
96
- assert_equal "Status: 666 I AM THE BEAST", status
97
92
  end
98
-
99
93
  end
@@ -1,13 +1,13 @@
1
1
  # -*- encoding: binary -*-
2
2
 
3
- # Copyright (c) 2005 Zed A. Shaw
3
+ # Copyright (c) 2005 Zed A. Shaw
4
4
  # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or
5
5
  # the GPLv2+ (GPLv3+ preferred)
6
6
  #
7
- # Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
7
+ # Additional work donated by contributors. See git history
8
8
  # for more information.
9
9
 
10
- require 'test/test_helper'
10
+ require './test/test_helper'
11
11
 
12
12
  include Unicorn
13
13
 
@@ -6,7 +6,7 @@
6
6
  #
7
7
  # Ensure we stay sane in the face of signals being sent to us
8
8
 
9
- require 'test/test_helper'
9
+ require './test/test_helper'
10
10
 
11
11
  include Unicorn
12
12
 
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: binary -*-
2
2
 
3
- require 'test/test_helper'
3
+ require './test/test_helper'
4
4
  require 'tempfile'
5
5
 
6
6
  class TestSocketHelper < Test::Unit::TestCase
@@ -182,16 +182,16 @@ class TestSocketHelper < Test::Unit::TestCase
182
182
  sock = bind_listen "[#@test6_addr]:#{port}", :ipv6only => true
183
183
  cur = sock.getsockopt(:IPPROTO_IPV6, :IPV6_V6ONLY).unpack('i')[0]
184
184
  assert_equal 1, cur
185
- rescue Errno::EAFNOSUPPORT
186
- end if RUBY_VERSION >= "1.9.2"
185
+ rescue Errno::EAFNOSUPPORT
186
+ end
187
187
 
188
188
  def test_reuseport
189
189
  port = unused_port @test_addr
190
190
  name = "#@test_addr:#{port}"
191
191
  sock = bind_listen(name, :reuseport => true)
192
- cur = sock.getsockopt(Socket::SOL_SOCKET, SO_REUSEPORT).unpack('i')[0]
192
+ cur = sock.getsockopt(:SOL_SOCKET, :SO_REUSEPORT).int
193
193
  assert_operator cur, :>, 0
194
194
  rescue Errno::ENOPROTOOPT
195
195
  # kernel does not support SO_REUSEPORT (older Linux)
196
- end
196
+ end if defined?(Socket::SO_REUSEPORT)
197
197
  end
@@ -29,6 +29,13 @@ class TestTeeInput < Test::Unit::TestCase
29
29
  end while true
30
30
  end
31
31
 
32
+ def check_tempfiles
33
+ tmp = @parser.env["rack.tempfiles"]
34
+ assert_instance_of Array, tmp
35
+ assert_operator tmp.size, :>=, 1
36
+ assert_instance_of Unicorn::TmpIO, tmp[0]
37
+ end
38
+
32
39
  def test_gets_long
33
40
  r = init_request("hello", 5 + (4096 * 4 * 3) + "#$/foo#$/".size)
34
41
  ti = TeeInput.new(@rd, r)
@@ -106,6 +113,7 @@ class TestTeeInput < Test::Unit::TestCase
106
113
  assert_kind_of File, ti.tmp
107
114
  assert_equal 0, ti.tmp.pos
108
115
  assert_equal Unicorn::Const::MAX_BODY + 1, ti.size
116
+ check_tempfiles
109
117
  end
110
118
 
111
119
  def test_read_in_full_if_content_length
@@ -148,6 +156,7 @@ class TestTeeInput < Test::Unit::TestCase
148
156
  assert_nil ti.read(1)
149
157
  pid, status = Process.waitpid2(pid)
150
158
  assert status.success?
159
+ check_tempfiles
151
160
  end
152
161
 
153
162
  def test_chunked
@@ -183,6 +192,7 @@ class TestTeeInput < Test::Unit::TestCase
183
192
  status = nil
184
193
  pid, status = Process.waitpid2(pid)
185
194
  assert status.success?
195
+ check_tempfiles
186
196
  end
187
197
 
188
198
  def test_chunked_ping_pong
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: binary -*-
2
2
 
3
3
  # Copyright (c) 2009 Eric Wong
4
- require 'test/test_helper'
4
+ require './test/test_helper'
5
5
  require 'digest/md5'
6
6
 
7
7
  include Unicorn
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: binary -*-
2
2
 
3
- require 'test/test_helper'
3
+ require './test/test_helper'
4
4
  require 'tempfile'
5
5
 
6
6
  class TestUtil < Test::Unit::TestCase
data/unicorn.gemspec CHANGED
@@ -1,8 +1,8 @@
1
1
  # -*- encoding: binary -*-
2
2
  ENV["VERSION"] or abort "VERSION= must be specified"
3
3
  manifest = File.readlines('.manifest').map! { |x| x.chomp! }
4
- require 'wrongdoc'
5
- extend Wrongdoc::Gemspec
4
+ require 'olddoc'
5
+ extend Olddoc::Gemspec
6
6
  name, summary, title = readme_metadata
7
7
 
8
8
  # don't bother with tests that fork, not worth our time to get working
@@ -14,19 +14,16 @@ end.compact
14
14
 
15
15
  Gem::Specification.new do |s|
16
16
  s.name = %q{unicorn-camilo}
17
- s.version = "4.8.2.5.19"
17
+ s.version = "5.0.0"
18
18
  s.authors = ["#{name} hackers"]
19
19
  s.summary = summary
20
- s.date = Time.now.utc.strftime('%Y-%m-%d')
21
20
  s.description = readme_description
22
- s.email = %q{mongrel-unicorn@rubyforge.org}
21
+ s.email = %q{unicorn-public@bogomips.org}
23
22
  s.executables = %w(unicorn unicorn_rails)
24
23
  s.extensions = %w(ext/unicorn_http/extconf.rb)
25
24
  s.extra_rdoc_files = extra_rdoc_files(manifest)
26
25
  s.files = manifest
27
- s.homepage = Wrongdoc.config[:rdoc_url]
28
- s.rdoc_options = rdoc_options
29
- s.rubyforge_project = %q{mongrel}
26
+ s.homepage = Olddoc.config['rdoc_url']
30
27
  s.test_files = test_files
31
28
 
32
29
  # for people that are absolutely stuck on Rails 2.3.2 and can't
@@ -37,8 +34,8 @@ Gem::Specification.new do |s|
37
34
  s.add_dependency(%q<kgio>, '~> 2.6')
38
35
  s.add_dependency(%q<raindrops>, '~> 0.7')
39
36
 
40
- s.add_development_dependency('isolate', '~> 3.2')
41
- s.add_development_dependency('wrongdoc', '~> 1.6.1')
37
+ s.add_development_dependency('test-unit', '~> 3.0')
38
+ s.add_development_dependency('olddoc', '~> 1.0')
42
39
 
43
40
  s.licenses = ["GPLv2+", "Ruby 1.8"]
44
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unicorn-camilo
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.2.5.19
4
+ version: 5.0.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: 2014-11-02 00:00:00.000000000 Z
11
+ date: 2015-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -53,40 +53,40 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.7'
55
55
  - !ruby/object:Gem::Dependency
56
- name: isolate
56
+ name: test-unit
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.2'
61
+ version: '3.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.2'
68
+ version: '3.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: wrongdoc
70
+ name: olddoc
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.6.1
75
+ version: '1.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.6.1
82
+ version: '1.0'
83
83
  description: |-
84
84
  \Unicorn is an HTTP server for Rack applications designed to only serve
85
85
  fast clients on low-latency, high-bandwidth connections and take
86
86
  advantage of features in Unix/Unix-like kernels. Slow clients should
87
87
  only be served by placing a reverse proxy capable of fully buffering
88
88
  both the the request and response in between \Unicorn and slow clients.
89
- email: mongrel-unicorn@rubyforge.org
89
+ email: unicorn-public@bogomips.org
90
90
  executables:
91
91
  - unicorn
92
92
  - unicorn_rails
@@ -105,7 +105,6 @@ extra_rdoc_files:
105
105
  - KNOWN_ISSUES
106
106
  - TODO
107
107
  - NEWS
108
- - ChangeLog
109
108
  - LATEST
110
109
  - lib/unicorn.rb
111
110
  - lib/unicorn/configurator.rb
@@ -126,11 +125,10 @@ files:
126
125
  - ".gitignore"
127
126
  - ".mailmap"
128
127
  - ".manifest"
129
- - ".wrongdoc.yml"
128
+ - ".olddoc.yml"
130
129
  - Application_Timeouts
131
130
  - CONTRIBUTORS
132
131
  - COPYING
133
- - ChangeLog
134
132
  - DESIGN
135
133
  - Documentation/.gitignore
136
134
  - Documentation/GNUmakefile
@@ -154,11 +152,12 @@ files:
154
152
  - Sandbox
155
153
  - TODO
156
154
  - TUNING
155
+ - archive/.gitignore
156
+ - archive/slrnpull.conf
157
157
  - bin/unicorn
158
158
  - bin/unicorn_rails
159
159
  - examples/big_app_gc.rb
160
160
  - examples/echo.ru
161
- - examples/git.ru
162
161
  - examples/init.sh
163
162
  - examples/logger_mp_safe.rb
164
163
  - examples/logrotate.conf
@@ -176,8 +175,6 @@ files:
176
175
  - ext/unicorn_http/unicorn_http.rl
177
176
  - ext/unicorn_http/unicorn_http_common.rl
178
177
  - lib/unicorn.rb
179
- - lib/unicorn/app/exec_cgi.rb
180
- - lib/unicorn/app/inetd.rb
181
178
  - lib/unicorn/app/old_rails.rb
182
179
  - lib/unicorn/app/old_rails/static.rb
183
180
  - lib/unicorn/cgi_wrapper.rb
@@ -190,19 +187,14 @@ files:
190
187
  - lib/unicorn/oob_gc.rb
191
188
  - lib/unicorn/preread_input.rb
192
189
  - lib/unicorn/socket_helper.rb
193
- - lib/unicorn/ssl_client.rb
194
- - lib/unicorn/ssl_configurator.rb
195
- - lib/unicorn/ssl_server.rb
196
190
  - lib/unicorn/stream_input.rb
197
191
  - lib/unicorn/tee_input.rb
198
192
  - lib/unicorn/tmpio.rb
199
193
  - lib/unicorn/util.rb
200
194
  - lib/unicorn/version.rb
201
195
  - lib/unicorn/worker.rb
202
- - local.mk.sample
203
196
  - man/man1/unicorn.1
204
197
  - man/man1/unicorn_rails.1
205
- - script/isolate_for_tests
206
198
  - setup.rb
207
199
  - t/.gitignore
208
200
  - t/GNUmakefile
@@ -245,8 +237,6 @@ files:
245
237
  - t/t0014-rewindable-input-true.sh
246
238
  - t/t0014.ru
247
239
  - t/t0015-configurator-internals.sh
248
- - t/t0016-trust-x-forwarded-false.sh
249
- - t/t0017-trust-x-forwarded-true.sh
250
240
  - t/t0018-write-on-close.sh
251
241
  - t/t0019-max_header_len.sh
252
242
  - t/t0020-at_exit-handler.sh
@@ -273,12 +263,10 @@ files:
273
263
  - test/unit/test_droplet.rb
274
264
  - test/unit/test_http_parser.rb
275
265
  - test/unit/test_http_parser_ng.rb
276
- - test/unit/test_http_parser_xftrust.rb
277
266
  - test/unit/test_request.rb
278
267
  - test/unit/test_response.rb
279
268
  - test/unit/test_server.rb
280
269
  - test/unit/test_signals.rb
281
- - test/unit/test_sni_hostnames.rb
282
270
  - test/unit/test_socket_helper.rb
283
271
  - test/unit/test_stream_input.rb
284
272
  - test/unit/test_tee_input.rb
@@ -291,11 +279,7 @@ licenses:
291
279
  - Ruby 1.8
292
280
  metadata: {}
293
281
  post_install_message:
294
- rdoc_options:
295
- - "-t"
296
- - 'Unicorn: Rack HTTP server for fast clients and Unix'
297
- - "-W"
298
- - http://bogomips.org/unicorn.git/tree/%s
282
+ rdoc_options: []
299
283
  require_paths:
300
284
  - lib
301
285
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -309,8 +293,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
309
293
  - !ruby/object:Gem::Version
310
294
  version: '0'
311
295
  requirements: []
312
- rubyforge_project: mongrel
313
- rubygems_version: 2.2.2
296
+ rubyforge_project:
297
+ rubygems_version: 2.2.3
314
298
  signing_key:
315
299
  specification_version: 4
316
300
  summary: Rack HTTP server for fast clients and Unix
@@ -318,9 +302,7 @@ test_files:
318
302
  - test/unit/test_configurator.rb
319
303
  - test/unit/test_http_parser.rb
320
304
  - test/unit/test_http_parser_ng.rb
321
- - test/unit/test_http_parser_xftrust.rb
322
305
  - test/unit/test_request.rb
323
306
  - test/unit/test_response.rb
324
307
  - test/unit/test_server.rb
325
- - test/unit/test_sni_hostnames.rb
326
308
  - test/unit/test_util.rb
data/examples/git.ru DELETED
@@ -1,13 +0,0 @@
1
- #\-E none
2
-
3
- # See http://thread.gmane.org/gmane.comp.web.curl.general/10473/raw on
4
- # how to setup git for this. A better version of the above patch was
5
- # accepted and committed on June 15, 2009, so you can pull the latest
6
- # curl CVS snapshot to try this out.
7
- require 'unicorn/app/inetd'
8
-
9
- use Rack::Lint
10
- use Rack::Chunked # important!
11
- run Unicorn::App::Inetd.new(
12
- *%w(git daemon --verbose --inetd --export-all --base-path=/home/ew/unicorn)
13
- )
@@ -1,154 +0,0 @@
1
- # -*- encoding: binary -*-
2
- # :enddoc:
3
- require 'unicorn'
4
-
5
- module Unicorn::App
6
-
7
- # This class is highly experimental (even more so than the rest of Unicorn)
8
- # and has never run anything other than cgit.
9
- class ExecCgi < Struct.new(:args)
10
-
11
- CHUNK_SIZE = 16384
12
- PASS_VARS = %w(
13
- CONTENT_LENGTH
14
- CONTENT_TYPE
15
- GATEWAY_INTERFACE
16
- AUTH_TYPE
17
- PATH_INFO
18
- PATH_TRANSLATED
19
- QUERY_STRING
20
- REMOTE_ADDR
21
- REMOTE_HOST
22
- REMOTE_IDENT
23
- REMOTE_USER
24
- REQUEST_METHOD
25
- SERVER_NAME
26
- SERVER_PORT
27
- SERVER_PROTOCOL
28
- SERVER_SOFTWARE
29
- ).map { |x| x.freeze } # frozen strings are faster for Hash assignments
30
-
31
- class Body < Unicorn::TmpIO
32
- def body_offset=(n)
33
- sysseek(@body_offset = n)
34
- end
35
-
36
- def each
37
- sysseek @body_offset
38
- # don't use a preallocated buffer for sysread since we can't
39
- # guarantee an actual socket is consuming the yielded string
40
- # (or if somebody is pushing to an array for eventual concatenation
41
- begin
42
- yield sysread(CHUNK_SIZE)
43
- rescue EOFError
44
- break
45
- end while true
46
- end
47
- end
48
-
49
- # Intializes the app, example of usage in a config.ru
50
- # map "/cgit" do
51
- # run Unicorn::App::ExecCgi.new("/path/to/cgit.cgi")
52
- # end
53
- def initialize(*args)
54
- self.args = args
55
- first = args[0] or
56
- raise ArgumentError, "need path to executable"
57
- first[0] == ?/ or args[0] = ::File.expand_path(first)
58
- File.executable?(args[0]) or
59
- raise ArgumentError, "#{args[0]} is not executable"
60
- end
61
-
62
- # Calls the app
63
- def call(env)
64
- out, err = Body.new, Unicorn::TmpIO.new
65
- inp = force_file_input(env)
66
- pid = fork { run_child(inp, out, err, env) }
67
- inp.close
68
- pid, status = Process.waitpid2(pid)
69
- write_errors(env, err, status) if err.stat.size > 0
70
- err.close
71
-
72
- return parse_output!(out) if status.success?
73
- out.close
74
- [ 500, { 'Content-Length' => '0', 'Content-Type' => 'text/plain' }, [] ]
75
- end
76
-
77
- private
78
-
79
- def run_child(inp, out, err, env)
80
- PASS_VARS.each do |key|
81
- val = env[key] or next
82
- ENV[key] = val
83
- end
84
- ENV['SCRIPT_NAME'] = args[0]
85
- ENV['GATEWAY_INTERFACE'] = 'CGI/1.1'
86
- env.keys.grep(/^HTTP_/) { |key| ENV[key] = env[key] }
87
-
88
- $stdin.reopen(inp)
89
- $stdout.reopen(out)
90
- $stderr.reopen(err)
91
- exec(*args)
92
- end
93
-
94
- # Extracts headers from CGI out, will change the offset of out.
95
- # This returns a standard Rack-compatible return value:
96
- # [ 200, HeadersHash, body ]
97
- def parse_output!(out)
98
- size = out.stat.size
99
- out.sysseek(0)
100
- head = out.sysread(CHUNK_SIZE)
101
- offset = 2
102
- head, body = head.split(/\n\n/, 2)
103
- if body.nil?
104
- head, body = head.split(/\r\n\r\n/, 2)
105
- offset = 4
106
- end
107
- offset += head.length
108
- out.body_offset = offset
109
- size -= offset
110
- prev = nil
111
- headers = Rack::Utils::HeaderHash.new
112
- head.split(/\r?\n/).each do |line|
113
- case line
114
- when /^([A-Za-z0-9-]+):\s*(.*)$/ then headers[prev = $1] = $2
115
- when /^[ \t]/ then headers[prev] << "\n#{line}" if prev
116
- end
117
- end
118
- status = headers.delete("Status") || 200
119
- headers['Content-Length'] = size.to_s
120
- [ status, headers, out ]
121
- end
122
-
123
- # ensures rack.input is a file handle that we can redirect stdin to
124
- def force_file_input(env)
125
- inp = env['rack.input']
126
- # inp could be a StringIO or StringIO-like object
127
- if inp.respond_to?(:size) && inp.size == 0
128
- ::File.open('/dev/null', 'rb')
129
- else
130
- tmp = Unicorn::TmpIO.new
131
-
132
- buf = inp.read(CHUNK_SIZE)
133
- begin
134
- tmp.syswrite(buf)
135
- end while inp.read(CHUNK_SIZE, buf)
136
- tmp.sysseek(0)
137
- tmp
138
- end
139
- end
140
-
141
- # rack.errors this may not be an IO object, so we couldn't
142
- # just redirect the CGI executable to that earlier.
143
- def write_errors(env, err, status)
144
- err.seek(0)
145
- dst = env['rack.errors']
146
- pid = status.pid
147
- dst.write("#{pid}: #{args.inspect} status=#{status} stderr:\n")
148
- err.each_line { |line| dst.write("#{pid}: #{line}") }
149
- dst.flush
150
- end
151
-
152
- end
153
-
154
- end