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.
- checksums.yaml +5 -5
- data/HISTORY.md +139 -18
- data/README.rdoc +17 -25
- data/Rakefile +6 -14
- data/SPEC +8 -9
- data/contrib/rack_logo.svg +164 -111
- data/lib/rack.rb +70 -21
- data/lib/rack/auth/digest/request.rb +1 -1
- data/lib/rack/body_proxy.rb +14 -9
- data/lib/rack/builder.rb +3 -3
- data/lib/rack/chunked.rb +5 -5
- data/lib/rack/{commonlogger.rb → common_logger.rb} +2 -2
- data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
- data/lib/rack/content_length.rb +2 -2
- data/lib/rack/deflater.rb +4 -4
- data/lib/rack/directory.rb +49 -55
- data/lib/rack/etag.rb +2 -1
- data/lib/rack/events.rb +154 -0
- data/lib/rack/file.rb +55 -40
- data/lib/rack/handler.rb +2 -24
- data/lib/rack/handler/cgi.rb +15 -16
- data/lib/rack/handler/fastcgi.rb +13 -14
- data/lib/rack/handler/lsws.rb +11 -11
- data/lib/rack/handler/scgi.rb +15 -15
- data/lib/rack/handler/thin.rb +3 -0
- data/lib/rack/handler/webrick.rb +22 -24
- data/lib/rack/head.rb +15 -17
- data/lib/rack/lint.rb +38 -38
- data/lib/rack/lobster.rb +1 -1
- data/lib/rack/lock.rb +6 -10
- data/lib/rack/logger.rb +2 -2
- data/lib/rack/media_type.rb +38 -0
- data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
- data/lib/rack/mime.rb +18 -5
- data/lib/rack/mock.rb +35 -52
- data/lib/rack/multipart.rb +35 -6
- data/lib/rack/multipart/generator.rb +4 -4
- data/lib/rack/multipart/parser.rb +273 -158
- data/lib/rack/multipart/uploaded_file.rb +1 -2
- data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
- data/lib/rack/query_parser.rb +174 -0
- data/lib/rack/recursive.rb +8 -8
- data/lib/rack/reloader.rb +1 -2
- data/lib/rack/request.rb +370 -304
- data/lib/rack/response.rb +129 -56
- data/lib/rack/rewindable_input.rb +1 -12
- data/lib/rack/runtime.rb +10 -18
- data/lib/rack/sendfile.rb +5 -7
- data/lib/rack/server.rb +31 -25
- data/lib/rack/session/abstract/id.rb +93 -135
- data/lib/rack/session/cookie.rb +26 -28
- data/lib/rack/session/memcache.rb +8 -14
- data/lib/rack/session/pool.rb +14 -21
- data/lib/rack/show_exceptions.rb +386 -0
- data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
- data/lib/rack/static.rb +30 -5
- data/lib/rack/tempfile_reaper.rb +2 -2
- data/lib/rack/urlmap.rb +13 -14
- data/lib/rack/utils.rb +128 -221
- data/rack.gemspec +9 -5
- data/test/builder/an_underscore_app.rb +5 -0
- data/test/builder/options.ru +1 -1
- data/test/cgi/test.fcgi +1 -0
- data/test/cgi/test.gz +0 -0
- data/test/helper.rb +31 -0
- data/test/multipart/filename_with_encoded_words +7 -0
- data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
- data/test/multipart/quoted +15 -0
- data/test/multipart/rack-logo.png +0 -0
- data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
- data/test/spec_auth_basic.rb +20 -19
- data/test/spec_auth_digest.rb +47 -46
- data/test/spec_body_proxy.rb +27 -27
- data/test/spec_builder.rb +51 -41
- data/test/spec_cascade.rb +24 -22
- data/test/spec_cgi.rb +49 -67
- data/test/spec_chunked.rb +36 -34
- data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
- data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
- data/test/spec_config.rb +3 -2
- data/test/spec_content_length.rb +18 -17
- data/test/spec_content_type.rb +13 -12
- data/test/spec_deflater.rb +66 -40
- data/test/spec_directory.rb +72 -27
- data/test/spec_etag.rb +32 -31
- data/test/spec_events.rb +133 -0
- data/test/spec_fastcgi.rb +50 -72
- data/test/spec_file.rb +96 -77
- data/test/spec_handler.rb +19 -34
- data/test/spec_head.rb +15 -14
- data/test/spec_lint.rb +162 -197
- data/test/spec_lobster.rb +24 -23
- data/test/spec_lock.rb +69 -39
- data/test/spec_logger.rb +4 -3
- data/test/spec_media_type.rb +42 -0
- data/test/spec_method_override.rb +83 -0
- data/test/spec_mime.rb +19 -19
- data/test/spec_mock.rb +196 -151
- data/test/spec_multipart.rb +310 -202
- data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
- data/test/spec_recursive.rb +17 -14
- data/test/spec_request.rb +763 -607
- data/test/spec_response.rb +209 -156
- data/test/spec_rewindable_input.rb +50 -40
- data/test/spec_runtime.rb +11 -10
- data/test/spec_sendfile.rb +30 -35
- data/test/spec_server.rb +78 -52
- data/test/spec_session_abstract_id.rb +11 -33
- data/test/spec_session_cookie.rb +97 -65
- data/test/spec_session_memcache.rb +63 -101
- data/test/spec_session_pool.rb +48 -84
- data/test/spec_show_exceptions.rb +80 -0
- data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
- data/test/spec_static.rb +71 -32
- data/test/spec_tempfile_reaper.rb +11 -10
- data/test/spec_thin.rb +55 -50
- data/test/spec_urlmap.rb +79 -78
- data/test/spec_utils.rb +417 -345
- data/test/spec_version.rb +2 -8
- data/test/spec_webrick.rb +77 -67
- data/test/static/foo.html +1 -0
- data/test/testrequest.rb +1 -1
- data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
- metadata +116 -71
- data/KNOWN-ISSUES +0 -44
- data/lib/rack/backports/uri/common_18.rb +0 -56
- data/lib/rack/backports/uri/common_192.rb +0 -52
- data/lib/rack/backports/uri/common_193.rb +0 -29
- data/lib/rack/handler/evented_mongrel.rb +0 -8
- data/lib/rack/handler/mongrel.rb +0 -106
- data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
- data/lib/rack/showexceptions.rb +0 -387
- data/lib/rack/utils/okjson.rb +0 -600
- data/test/spec_methodoverride.rb +0 -111
- data/test/spec_mongrel.rb +0 -182
- data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
- data/test/spec_showexceptions.rb +0 -98
data/lib/rack/response.rb
CHANGED
@@ -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 (
|
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
|
-
|
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
|
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
|
-
|
78
|
-
|
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 +=
|
87
|
+
@length += s.bytesize unless chunked?
|
101
88
|
@writer.call s
|
102
89
|
|
103
|
-
|
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
|
-
|
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?;
|
119
|
-
|
120
|
-
def informational?;
|
121
|
-
def successful?;
|
122
|
-
def redirection?;
|
123
|
-
def client_error?;
|
124
|
-
def server_error?;
|
125
|
-
|
126
|
-
def ok?;
|
127
|
-
def created?;
|
128
|
-
def accepted?;
|
129
|
-
def
|
130
|
-
def
|
131
|
-
def
|
132
|
-
def
|
133
|
-
def
|
134
|
-
def
|
135
|
-
def
|
136
|
-
|
137
|
-
def
|
138
|
-
|
139
|
-
|
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
|
-
|
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
|
-
|
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 =
|
170
|
+
cl = get_header CONTENT_LENGTH
|
152
171
|
cl ? cl.to_i : cl
|
153
172
|
end
|
154
173
|
|
155
174
|
def location
|
156
|
-
|
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 ==
|
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
|
data/lib/rack/runtime.rb
CHANGED
@@ -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 =
|
12
|
-
@header_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
|
-
|
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
|
data/lib/rack/sendfile.rb
CHANGED
@@ -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 =
|
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[
|
124
|
+
env[RACK_ERRORS].puts "X-Accel-Mapping header missing"
|
127
125
|
end
|
128
126
|
when 'X-Sendfile', 'X-Lighttpd-Send-File'
|
129
|
-
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[
|
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
|
153
|
+
internal, external = mapping.split('=', 2).map(&:strip)
|
156
154
|
path.sub(/^#{internal}/i, external)
|
157
155
|
end
|
158
156
|
end
|
data/lib/rack/server.rb
CHANGED
@@ -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
|
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
|
-
@
|
187
|
-
|
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
|
-
@
|
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])
|
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
|
-
|
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
|
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
|
-
|
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 { ::
|
362
|
+
at_exit { ::File.delete(options[:pid]) if ::File.exist?(options[:pid]) }
|
357
363
|
rescue Errno::EEXIST
|
358
364
|
check_pid!
|
359
365
|
retry
|