unicorn-camilo 4.8.2.5.19 → 5.0.0

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.
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