rack 1.6.13 → 2.0.0.alpha

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (138) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.md +139 -18
  3. data/README.rdoc +17 -25
  4. data/Rakefile +6 -14
  5. data/SPEC +8 -9
  6. data/contrib/rack_logo.svg +164 -111
  7. data/lib/rack.rb +70 -21
  8. data/lib/rack/auth/digest/request.rb +1 -1
  9. data/lib/rack/body_proxy.rb +14 -9
  10. data/lib/rack/builder.rb +3 -3
  11. data/lib/rack/chunked.rb +5 -5
  12. data/lib/rack/{commonlogger.rb → common_logger.rb} +2 -2
  13. data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
  14. data/lib/rack/content_length.rb +2 -2
  15. data/lib/rack/deflater.rb +4 -4
  16. data/lib/rack/directory.rb +49 -55
  17. data/lib/rack/etag.rb +2 -1
  18. data/lib/rack/events.rb +154 -0
  19. data/lib/rack/file.rb +55 -40
  20. data/lib/rack/handler.rb +2 -24
  21. data/lib/rack/handler/cgi.rb +15 -16
  22. data/lib/rack/handler/fastcgi.rb +13 -14
  23. data/lib/rack/handler/lsws.rb +11 -11
  24. data/lib/rack/handler/scgi.rb +15 -15
  25. data/lib/rack/handler/thin.rb +3 -0
  26. data/lib/rack/handler/webrick.rb +22 -24
  27. data/lib/rack/head.rb +15 -17
  28. data/lib/rack/lint.rb +38 -38
  29. data/lib/rack/lobster.rb +1 -1
  30. data/lib/rack/lock.rb +6 -10
  31. data/lib/rack/logger.rb +2 -2
  32. data/lib/rack/media_type.rb +38 -0
  33. data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
  34. data/lib/rack/mime.rb +18 -5
  35. data/lib/rack/mock.rb +35 -52
  36. data/lib/rack/multipart.rb +35 -6
  37. data/lib/rack/multipart/generator.rb +4 -4
  38. data/lib/rack/multipart/parser.rb +273 -158
  39. data/lib/rack/multipart/uploaded_file.rb +1 -2
  40. data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
  41. data/lib/rack/query_parser.rb +174 -0
  42. data/lib/rack/recursive.rb +8 -8
  43. data/lib/rack/reloader.rb +1 -2
  44. data/lib/rack/request.rb +370 -304
  45. data/lib/rack/response.rb +129 -56
  46. data/lib/rack/rewindable_input.rb +1 -12
  47. data/lib/rack/runtime.rb +10 -18
  48. data/lib/rack/sendfile.rb +5 -7
  49. data/lib/rack/server.rb +31 -25
  50. data/lib/rack/session/abstract/id.rb +93 -135
  51. data/lib/rack/session/cookie.rb +26 -28
  52. data/lib/rack/session/memcache.rb +8 -14
  53. data/lib/rack/session/pool.rb +14 -21
  54. data/lib/rack/show_exceptions.rb +386 -0
  55. data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
  56. data/lib/rack/static.rb +30 -5
  57. data/lib/rack/tempfile_reaper.rb +2 -2
  58. data/lib/rack/urlmap.rb +13 -14
  59. data/lib/rack/utils.rb +128 -221
  60. data/rack.gemspec +9 -5
  61. data/test/builder/an_underscore_app.rb +5 -0
  62. data/test/builder/options.ru +1 -1
  63. data/test/cgi/test.fcgi +1 -0
  64. data/test/cgi/test.gz +0 -0
  65. data/test/helper.rb +31 -0
  66. data/test/multipart/filename_with_encoded_words +7 -0
  67. data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
  68. data/test/multipart/quoted +15 -0
  69. data/test/multipart/rack-logo.png +0 -0
  70. data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
  71. data/test/spec_auth_basic.rb +20 -19
  72. data/test/spec_auth_digest.rb +47 -46
  73. data/test/spec_body_proxy.rb +27 -27
  74. data/test/spec_builder.rb +51 -41
  75. data/test/spec_cascade.rb +24 -22
  76. data/test/spec_cgi.rb +49 -67
  77. data/test/spec_chunked.rb +36 -34
  78. data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
  79. data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
  80. data/test/spec_config.rb +3 -2
  81. data/test/spec_content_length.rb +18 -17
  82. data/test/spec_content_type.rb +13 -12
  83. data/test/spec_deflater.rb +66 -40
  84. data/test/spec_directory.rb +72 -27
  85. data/test/spec_etag.rb +32 -31
  86. data/test/spec_events.rb +133 -0
  87. data/test/spec_fastcgi.rb +50 -72
  88. data/test/spec_file.rb +96 -77
  89. data/test/spec_handler.rb +19 -34
  90. data/test/spec_head.rb +15 -14
  91. data/test/spec_lint.rb +162 -197
  92. data/test/spec_lobster.rb +24 -23
  93. data/test/spec_lock.rb +69 -39
  94. data/test/spec_logger.rb +4 -3
  95. data/test/spec_media_type.rb +42 -0
  96. data/test/spec_method_override.rb +83 -0
  97. data/test/spec_mime.rb +19 -19
  98. data/test/spec_mock.rb +196 -151
  99. data/test/spec_multipart.rb +310 -202
  100. data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
  101. data/test/spec_recursive.rb +17 -14
  102. data/test/spec_request.rb +763 -607
  103. data/test/spec_response.rb +209 -156
  104. data/test/spec_rewindable_input.rb +50 -40
  105. data/test/spec_runtime.rb +11 -10
  106. data/test/spec_sendfile.rb +30 -35
  107. data/test/spec_server.rb +78 -52
  108. data/test/spec_session_abstract_id.rb +11 -33
  109. data/test/spec_session_cookie.rb +97 -65
  110. data/test/spec_session_memcache.rb +63 -101
  111. data/test/spec_session_pool.rb +48 -84
  112. data/test/spec_show_exceptions.rb +80 -0
  113. data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
  114. data/test/spec_static.rb +71 -32
  115. data/test/spec_tempfile_reaper.rb +11 -10
  116. data/test/spec_thin.rb +55 -50
  117. data/test/spec_urlmap.rb +79 -78
  118. data/test/spec_utils.rb +417 -345
  119. data/test/spec_version.rb +2 -8
  120. data/test/spec_webrick.rb +77 -67
  121. data/test/static/foo.html +1 -0
  122. data/test/testrequest.rb +1 -1
  123. data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
  124. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
  125. metadata +116 -71
  126. data/KNOWN-ISSUES +0 -44
  127. data/lib/rack/backports/uri/common_18.rb +0 -56
  128. data/lib/rack/backports/uri/common_192.rb +0 -52
  129. data/lib/rack/backports/uri/common_193.rb +0 -29
  130. data/lib/rack/handler/evented_mongrel.rb +0 -8
  131. data/lib/rack/handler/mongrel.rb +0 -106
  132. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  133. data/lib/rack/showexceptions.rb +0 -387
  134. data/lib/rack/utils/okjson.rb +0 -600
  135. data/test/spec_methodoverride.rb +0 -111
  136. data/test/spec_mongrel.rb +0 -182
  137. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  138. data/test/spec_showexceptions.rb +0 -98
@@ -1,6 +1,7 @@
1
1
  require 'rack/request'
2
2
  require 'rack/utils'
3
3
  require 'rack/body_proxy'
4
+ require 'rack/media_type'
4
5
  require 'time'
5
6
 
6
7
  module Rack
@@ -8,7 +9,7 @@ module Rack
8
9
  # response.
9
10
  #
10
11
  # It allows setting of headers and cookies, and provides useful
11
- # defaults (a OK response containing HTML).
12
+ # defaults (an OK response with empty headers and body).
12
13
  #
13
14
  # You can use Response#write to iteratively generate your response,
14
15
  # but note that this is buffered by Rack::Response until you call
@@ -18,15 +19,16 @@ module Rack
18
19
  # Your application's +call+ should end returning Response#finish.
19
20
 
20
21
  class Response
21
- attr_accessor :length
22
+ attr_accessor :length, :status, :body
23
+ attr_reader :header
24
+ alias headers header
22
25
 
23
26
  CHUNKED = 'chunked'.freeze
24
- TRANSFER_ENCODING = 'Transfer-Encoding'.freeze
27
+
25
28
  def initialize(body=[], status=200, header={})
26
29
  @status = status.to_i
27
30
  @header = Utils::HeaderHash.new.merge(header)
28
31
 
29
- @chunked = CHUNKED == @header[TRANSFER_ENCODING]
30
32
  @writer = lambda { |x| @body << x }
31
33
  @block = nil
32
34
  @length = 0
@@ -46,36 +48,21 @@ module Rack
46
48
  yield self if block_given?
47
49
  end
48
50
 
49
- attr_reader :header
50
- attr_accessor :status, :body
51
-
52
- def [](key)
53
- header[key]
54
- end
55
-
56
- def []=(key, value)
57
- header[key] = value
58
- end
59
-
60
- def set_cookie(key, value)
61
- Utils.set_cookie_header!(header, key, value)
62
- end
63
-
64
- def delete_cookie(key, value={})
65
- Utils.delete_cookie_header!(header, key, value)
66
- end
67
-
68
51
  def redirect(target, status=302)
69
52
  self.status = status
70
- self["Location"] = target
53
+ self.location = target
54
+ end
55
+
56
+ def chunked?
57
+ CHUNKED == get_header(TRANSFER_ENCODING)
71
58
  end
72
59
 
73
60
  def finish(&block)
74
61
  @block = block
75
62
 
76
63
  if [204, 205, 304].include?(status.to_i)
77
- header.delete CONTENT_TYPE
78
- header.delete CONTENT_LENGTH
64
+ delete_header CONTENT_TYPE
65
+ delete_header CONTENT_LENGTH
79
66
  close
80
67
  [status.to_i, header, []]
81
68
  else
@@ -97,10 +84,10 @@ module Rack
97
84
  #
98
85
  def write(str)
99
86
  s = str.to_s
100
- @length += Rack::Utils.bytesize(s) unless @chunked
87
+ @length += s.bytesize unless chunked?
101
88
  @writer.call s
102
89
 
103
- header[CONTENT_LENGTH] = @length.to_s unless @chunked
90
+ set_header(CONTENT_LENGTH, @length.to_s) unless chunked?
104
91
  str
105
92
  end
106
93
 
@@ -112,51 +99,137 @@ module Rack
112
99
  @block == nil && @body.empty?
113
100
  end
114
101
 
115
- alias headers header
102
+ def has_header?(key); headers.key? key; end
103
+ def get_header(key); headers[key]; end
104
+ def set_header(key, v); headers[key] = v; end
105
+ def delete_header(key); headers.delete key; end
106
+
107
+ alias :[] :get_header
108
+ alias :[]= :set_header
116
109
 
117
110
  module Helpers
118
- def invalid?; status < 100 || status >= 600; end
119
-
120
- def informational?; status >= 100 && status < 200; end
121
- def successful?; status >= 200 && status < 300; end
122
- def redirection?; status >= 300 && status < 400; end
123
- def client_error?; status >= 400 && status < 500; end
124
- def server_error?; status >= 500 && status < 600; end
125
-
126
- def ok?; status == 200; end
127
- def created?; status == 201; end
128
- def accepted?; status == 202; end
129
- def bad_request?; status == 400; end
130
- def unauthorized?; status == 401; end
131
- def forbidden?; status == 403; end
132
- def not_found?; status == 404; end
133
- def method_not_allowed?; status == 405; end
134
- def i_m_a_teapot?; status == 418; end
135
- def unprocessable?; status == 422; end
136
-
137
- def redirect?; [301, 302, 303, 307].include? status; end
138
-
139
- # Headers
140
- attr_reader :headers, :original_headers
111
+ def invalid?; status < 100 || status >= 600; end
112
+
113
+ def informational?; status >= 100 && status < 200; end
114
+ def successful?; status >= 200 && status < 300; end
115
+ def redirection?; status >= 300 && status < 400; end
116
+ def client_error?; status >= 400 && status < 500; end
117
+ def server_error?; status >= 500 && status < 600; end
118
+
119
+ def ok?; status == 200; end
120
+ def created?; status == 201; end
121
+ def accepted?; status == 202; end
122
+ def no_content?; status == 204; end
123
+ def moved_permanently?; status == 301; end
124
+ def bad_request?; status == 400; end
125
+ def unauthorized?; status == 401; end
126
+ def forbidden?; status == 403; end
127
+ def not_found?; status == 404; end
128
+ def method_not_allowed?; status == 405; end
129
+ def precondition_failed?; status == 412; end
130
+ def unprocessable?; status == 422; end
131
+
132
+ def redirect?; [301, 302, 303, 307, 308].include? status; end
141
133
 
142
134
  def include?(header)
143
- !!headers[header]
135
+ has_header? header
136
+ end
137
+
138
+ # Add a header that may have multiple values.
139
+ #
140
+ # Example:
141
+ # response.add_header 'Vary', 'Accept-Encoding'
142
+ # response.add_header 'Vary', 'Cookie'
143
+ #
144
+ # assert_equal 'Accept-Encoding,Cookie', response.get_header('Vary')
145
+ #
146
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
147
+ def add_header key, v
148
+ if v.nil?
149
+ get_header key
150
+ elsif has_header? key
151
+ set_header key, "#{get_header key},#{v}"
152
+ else
153
+ set_header key, v
154
+ end
144
155
  end
145
156
 
146
157
  def content_type
147
- headers[CONTENT_TYPE]
158
+ get_header CONTENT_TYPE
159
+ end
160
+
161
+ def media_type
162
+ MediaType.type(content_type)
163
+ end
164
+
165
+ def media_type_params
166
+ MediaType.params(content_type)
148
167
  end
149
168
 
150
169
  def content_length
151
- cl = headers[CONTENT_LENGTH]
170
+ cl = get_header CONTENT_LENGTH
152
171
  cl ? cl.to_i : cl
153
172
  end
154
173
 
155
174
  def location
156
- headers["Location"]
175
+ get_header "Location"
176
+ end
177
+
178
+ def location=(location)
179
+ set_header "Location", location
180
+ end
181
+
182
+ def set_cookie(key, value)
183
+ cookie_header = get_header SET_COOKIE
184
+ set_header SET_COOKIE, ::Rack::Utils.add_cookie_to_header(cookie_header, key, value)
185
+ end
186
+
187
+ def delete_cookie(key, value={})
188
+ set_header SET_COOKIE, ::Rack::Utils.add_remove_cookie_to_header(get_header(SET_COOKIE), key, value)
189
+ end
190
+
191
+ def set_cookie_header
192
+ get_header SET_COOKIE
193
+ end
194
+
195
+ def set_cookie_header= v
196
+ set_header SET_COOKIE, v
197
+ end
198
+
199
+ def cache_control
200
+ get_header CACHE_CONTROL
201
+ end
202
+
203
+ def cache_control= v
204
+ set_header CACHE_CONTROL, v
205
+ end
206
+
207
+ def etag
208
+ get_header ETAG
209
+ end
210
+
211
+ def etag= v
212
+ set_header ETAG, v
157
213
  end
158
214
  end
159
215
 
160
216
  include Helpers
217
+
218
+ class Raw
219
+ include Helpers
220
+
221
+ attr_reader :headers
222
+ attr_accessor :status
223
+
224
+ def initialize status, headers
225
+ @status = status
226
+ @headers = headers
227
+ end
228
+
229
+ def has_header?(key); headers.key? key; end
230
+ def get_header(key); headers[key]; end
231
+ def set_header(key, v); headers[key] = v; end
232
+ def delete_header(key); headers.delete key; end
233
+ end
161
234
  end
162
235
  end
@@ -57,15 +57,6 @@ module Rack
57
57
 
58
58
  private
59
59
 
60
- # Ruby's Tempfile class has a bug. Subclass it and fix it.
61
- class Tempfile < ::Tempfile
62
- def _close
63
- @tmpfile.close if @tmpfile
64
- @data[1] = nil if @data
65
- @tmpfile = nil
66
- end
67
- end
68
-
69
60
  def make_rewindable
70
61
  # Buffer all data into a tempfile. Since this tempfile is private to this
71
62
  # RewindableInput object, we chmod it so that nobody else can read or write
@@ -77,8 +68,6 @@ module Rack
77
68
  @rewindable_io.set_encoding(Encoding::BINARY) if @rewindable_io.respond_to?(:set_encoding)
78
69
  @rewindable_io.binmode
79
70
  if filesystem_has_posix_semantics?
80
- # Use ::File.unlink as 1.9.1 Tempfile has a bug where unlink closes the file!
81
- ::File.unlink @rewindable_io.path
82
71
  raise 'Unlink failed. IO closed.' if @rewindable_io.closed?
83
72
  @unlinked = true
84
73
  end
@@ -88,7 +77,7 @@ module Rack
88
77
  entire_buffer_written_out = false
89
78
  while !entire_buffer_written_out
90
79
  written = @rewindable_io.write(buffer)
91
- entire_buffer_written_out = written == Rack::Utils.bytesize(buffer)
80
+ entire_buffer_written_out = written == buffer.bytesize
92
81
  if !entire_buffer_written_out
93
82
  buffer.slice!(0 .. written - 1)
94
83
  end
@@ -1,3 +1,5 @@
1
+ require 'rack/utils'
2
+
1
3
  module Rack
2
4
  # Sets an "X-Runtime" response header, indicating the response
3
5
  # time of the request, in seconds
@@ -6,35 +8,25 @@ module Rack
6
8
  # time, or before all the other middlewares to include time for them,
7
9
  # too.
8
10
  class Runtime
11
+ FORMAT_STRING = "%0.6f".freeze # :nodoc:
12
+ HEADER_NAME = "X-Runtime".freeze # :nodoc:
13
+
9
14
  def initialize(app, name = nil)
10
15
  @app = app
11
- @header_name = "X-Runtime"
12
- @header_name << "-#{name}" if name
16
+ @header_name = HEADER_NAME
17
+ @header_name += "-#{name}" if name
13
18
  end
14
19
 
15
- FORMAT_STRING = "%0.6f"
16
20
  def call(env)
17
- start_time = clock_time
21
+ start_time = Utils.clock_time
18
22
  status, headers, body = @app.call(env)
19
- request_time = clock_time - start_time
23
+ request_time = Utils.clock_time - start_time
20
24
 
21
- if !headers.has_key?(@header_name)
25
+ unless headers.has_key?(@header_name)
22
26
  headers[@header_name] = FORMAT_STRING % request_time
23
27
  end
24
28
 
25
29
  [status, headers, body]
26
30
  end
27
-
28
- private
29
-
30
- if defined?(Process::CLOCK_MONOTONIC)
31
- def clock_time
32
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
33
- end
34
- else
35
- def clock_time
36
- Time.now.to_f
37
- end
38
- end
39
31
  end
40
32
  end
@@ -99,8 +99,6 @@ module Rack
99
99
  # will be matched with case indifference.
100
100
 
101
101
  class Sendfile
102
- F = ::File
103
-
104
102
  def initialize(app, variation=nil, mappings=[])
105
103
  @app = app
106
104
  @variation = variation
@@ -114,7 +112,7 @@ module Rack
114
112
  if body.respond_to?(:to_path)
115
113
  case type = variation(env)
116
114
  when 'X-Accel-Redirect'
117
- path = F.expand_path(body.to_path)
115
+ path = ::File.expand_path(body.to_path)
118
116
  if url = map_accel_path(env, path)
119
117
  headers[CONTENT_LENGTH] = '0'
120
118
  headers[type] = url
@@ -123,10 +121,10 @@ module Rack
123
121
  obody.close if obody.respond_to?(:close)
124
122
  end
125
123
  else
126
- env['rack.errors'].puts "X-Accel-Mapping header missing"
124
+ env[RACK_ERRORS].puts "X-Accel-Mapping header missing"
127
125
  end
128
126
  when 'X-Sendfile', 'X-Lighttpd-Send-File'
129
- path = F.expand_path(body.to_path)
127
+ path = ::File.expand_path(body.to_path)
130
128
  headers[CONTENT_LENGTH] = '0'
131
129
  headers[type] = path
132
130
  obody = body
@@ -135,7 +133,7 @@ module Rack
135
133
  end
136
134
  when '', nil
137
135
  else
138
- env['rack.errors'].puts "Unknown x-sendfile variation: '#{type}'.\n"
136
+ env[RACK_ERRORS].puts "Unknown x-sendfile variation: '#{type}'.\n"
139
137
  end
140
138
  end
141
139
  [status, headers, body]
@@ -152,7 +150,7 @@ module Rack
152
150
  if mapping = @mappings.find { |internal,_| internal =~ path }
153
151
  path.sub(*mapping)
154
152
  elsif mapping = env['HTTP_X_ACCEL_MAPPING']
155
- internal, external = mapping.split('=', 2).map{ |p| p.strip }
153
+ internal, external = mapping.split('=', 2).map(&:strip)
156
154
  path.sub(/^#{internal}/i, external)
157
155
  end
158
156
  end
@@ -1,5 +1,4 @@
1
1
  require 'optparse'
2
- require 'fileutils'
3
2
 
4
3
 
5
4
  module Rack
@@ -100,14 +99,14 @@ module Rack
100
99
  abort opt_parser.to_s
101
100
  end
102
101
 
103
- options[:config] = args.last if args.last
102
+ options[:config] = args.last if args.last && !args.last.empty?
104
103
  options
105
104
  end
106
105
 
107
106
  def handler_opts(options)
108
107
  begin
109
108
  info = []
110
- server = Rack::Handler.get(options[:server]) || Rack::Handler.default(options)
109
+ server = Rack::Handler.get(options[:server]) || Rack::Handler.default
111
110
  if server && server.respond_to?(:valid_options)
112
111
  info << ""
113
112
  info << "Server-specific options for #{server.name}:"
@@ -183,12 +182,22 @@ module Rack
183
182
  # * :require
184
183
  # require the given libraries
185
184
  def initialize(options = nil)
186
- @options = options
187
- @app = options[:app] if options && options[:app]
185
+ @ignore_options = []
186
+
187
+ if options
188
+ @use_default_options = false
189
+ @options = options
190
+ @app = options[:app] if options[:app]
191
+ else
192
+ argv = defined?(SPEC_ARGV) ? SPEC_ARGV : ARGV
193
+ @use_default_options = true
194
+ @options = parse_options(argv)
195
+ end
188
196
  end
189
197
 
190
198
  def options
191
- @options ||= parse_options(ARGV)
199
+ merged_options = @use_default_options ? default_options.merge(@options) : @options
200
+ merged_options.reject { |k, v| @ignore_options.include?(k) }
192
201
  end
193
202
 
194
203
  def default_options
@@ -288,7 +297,16 @@ module Rack
288
297
  end
289
298
 
290
299
  def server
291
- @_server ||= Rack::Handler.get(options[:server]) || Rack::Handler.default(options)
300
+ @_server ||= Rack::Handler.get(options[:server])
301
+
302
+ unless @_server
303
+ @_server = Rack::Handler.default
304
+
305
+ # We already speak FastCGI
306
+ @ignore_options = [:File, :Port] if @_server.to_s == 'Rack::Handler::FastCGI'
307
+ end
308
+
309
+ @_server
292
310
  end
293
311
 
294
312
  private
@@ -298,7 +316,7 @@ module Rack
298
316
  end
299
317
 
300
318
  app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
301
- self.options.merge! options
319
+ @options.merge!(options) { |key, old, new| old }
302
320
  app
303
321
  end
304
322
 
@@ -307,16 +325,14 @@ module Rack
307
325
  end
308
326
 
309
327
  def parse_options(args)
310
- options = default_options
311
-
312
328
  # Don't evaluate CGI ISINDEX parameters.
313
329
  # http://www.meb.uni-bonn.de/docs/cgi/cl.html
314
330
  args.clear if ENV.include?(REQUEST_METHOD)
315
331
 
316
- options.merge! opt_parser.parse!(args)
317
- options[:config] = ::File.expand_path(options[:config])
332
+ @options = opt_parser.parse!(args)
333
+ @options[:config] = ::File.expand_path(options[:config])
318
334
  ENV["RACK_ENV"] = options[:environment]
319
- options
335
+ @options
320
336
  end
321
337
 
322
338
  def opt_parser
@@ -338,22 +354,12 @@ module Rack
338
354
  end
339
355
 
340
356
  def daemonize_app
341
- if RUBY_VERSION < "1.9"
342
- exit if fork
343
- Process.setsid
344
- exit if fork
345
- Dir.chdir "/"
346
- STDIN.reopen "/dev/null"
347
- STDOUT.reopen "/dev/null", "a"
348
- STDERR.reopen "/dev/null", "a"
349
- else
350
- Process.daemon
351
- end
357
+ Process.daemon
352
358
  end
353
359
 
354
360
  def write_pid
355
361
  ::File.open(options[:pid], ::File::CREAT | ::File::EXCL | ::File::WRONLY ){ |f| f.write("#{Process.pid}") }
356
- at_exit { ::FileUtils.rm_f(options[:pid]) }
362
+ at_exit { ::File.delete(options[:pid]) if ::File.exist?(options[:pid]) }
357
363
  rescue Errno::EEXIST
358
364
  check_pid!
359
365
  retry