rack 1.6.13 → 2.0.1
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/COPYING +1 -1
- data/HISTORY.md +138 -8
- data/README.rdoc +17 -25
- data/Rakefile +6 -14
- data/SPEC +8 -9
- data/contrib/rack_logo.svg +164 -111
- data/example/protectedlobster.rb +1 -1
- data/example/protectedlobster.ru +1 -1
- data/lib/rack/auth/abstract/request.rb +5 -1
- data/lib/rack/auth/digest/params.rb +2 -3
- 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} +3 -3
- 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 +66 -54
- data/lib/rack/etag.rb +4 -3
- data/lib/rack/events.rb +154 -0
- data/lib/rack/file.rb +63 -39
- 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/handler.rb +3 -25
- 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 -53
- data/lib/rack/multipart/generator.rb +5 -5
- data/lib/rack/multipart/parser.rb +272 -158
- data/lib/rack/multipart/uploaded_file.rb +1 -2
- data/lib/rack/multipart.rb +35 -6
- data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
- data/lib/rack/query_parser.rb +192 -0
- data/lib/rack/recursive.rb +8 -8
- data/lib/rack/request.rb +383 -307
- 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 +95 -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 +15 -14
- data/lib/rack/utils.rb +135 -210
- data/lib/rack.rb +70 -21
- data/rack.gemspec +7 -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 +34 -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/multipart/unity3d_wwwform +11 -0
- data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
- data/test/spec_auth_basic.rb +27 -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 +87 -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 +107 -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 +317 -201
- data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
- data/test/spec_recursive.rb +17 -14
- data/test/spec_request.rb +768 -607
- data/test/spec_response.rb +214 -111
- 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_abstract_session_hash.rb +28 -0
- 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 +441 -346
- data/test/spec_version.rb +2 -8
- data/test/spec_webrick.rb +91 -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 +103 -69
- 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
@@ -0,0 +1,192 @@
|
|
1
|
+
module Rack
|
2
|
+
class QueryParser
|
3
|
+
DEFAULT_SEP = /[&;] */n
|
4
|
+
COMMON_SEP = { ";" => /[;] */n, ";," => /[;,] */n, "&" => /[&] */n }
|
5
|
+
|
6
|
+
# ParameterTypeError is the error that is raised when incoming structural
|
7
|
+
# parameters (parsed by parse_nested_query) contain conflicting types.
|
8
|
+
class ParameterTypeError < TypeError; end
|
9
|
+
|
10
|
+
# InvalidParameterError is the error that is raised when incoming structural
|
11
|
+
# parameters (parsed by parse_nested_query) contain invalid format or byte
|
12
|
+
# sequence.
|
13
|
+
class InvalidParameterError < ArgumentError; end
|
14
|
+
|
15
|
+
def self.make_default(key_space_limit, param_depth_limit)
|
16
|
+
new Params, key_space_limit, param_depth_limit
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :key_space_limit, :param_depth_limit
|
20
|
+
|
21
|
+
def initialize(params_class, key_space_limit, param_depth_limit)
|
22
|
+
@params_class = params_class
|
23
|
+
@key_space_limit = key_space_limit
|
24
|
+
@param_depth_limit = param_depth_limit
|
25
|
+
end
|
26
|
+
|
27
|
+
# Stolen from Mongrel, with some small modifications:
|
28
|
+
# Parses a query string by breaking it up at the '&'
|
29
|
+
# and ';' characters. You can also use this to parse
|
30
|
+
# cookies by changing the characters used in the second
|
31
|
+
# parameter (which defaults to '&;').
|
32
|
+
def parse_query(qs, d = nil, &unescaper)
|
33
|
+
unescaper ||= method(:unescape)
|
34
|
+
|
35
|
+
params = make_params
|
36
|
+
|
37
|
+
(qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
|
38
|
+
next if p.empty?
|
39
|
+
k, v = p.split('='.freeze, 2).map!(&unescaper)
|
40
|
+
|
41
|
+
if cur = params[k]
|
42
|
+
if cur.class == Array
|
43
|
+
params[k] << v
|
44
|
+
else
|
45
|
+
params[k] = [cur, v]
|
46
|
+
end
|
47
|
+
else
|
48
|
+
params[k] = v
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
return params.to_params_hash
|
53
|
+
end
|
54
|
+
|
55
|
+
# parse_nested_query expands a query string into structural types. Supported
|
56
|
+
# types are Arrays, Hashes and basic value types. It is possible to supply
|
57
|
+
# query strings with parameters of conflicting types, in this case a
|
58
|
+
# ParameterTypeError is raised. Users are encouraged to return a 400 in this
|
59
|
+
# case.
|
60
|
+
def parse_nested_query(qs, d = nil)
|
61
|
+
return {} if qs.nil? || qs.empty?
|
62
|
+
params = make_params
|
63
|
+
|
64
|
+
(qs || '').split(d ? (COMMON_SEP[d] || /[#{d}] */n) : DEFAULT_SEP).each do |p|
|
65
|
+
k, v = p.split('='.freeze, 2).map! { |s| unescape(s) }
|
66
|
+
|
67
|
+
normalize_params(params, k, v, param_depth_limit)
|
68
|
+
end
|
69
|
+
|
70
|
+
return params.to_params_hash
|
71
|
+
rescue ArgumentError => e
|
72
|
+
raise InvalidParameterError, e.message
|
73
|
+
end
|
74
|
+
|
75
|
+
# normalize_params recursively expands parameters into structural types. If
|
76
|
+
# the structural types represented by two different parameter names are in
|
77
|
+
# conflict, a ParameterTypeError is raised.
|
78
|
+
def normalize_params(params, name, v, depth)
|
79
|
+
raise RangeError if depth <= 0
|
80
|
+
|
81
|
+
name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
|
82
|
+
k = $1 || ''.freeze
|
83
|
+
after = $' || ''.freeze
|
84
|
+
|
85
|
+
if k.empty?
|
86
|
+
if !v.nil? && name == "[]".freeze
|
87
|
+
return Array(v)
|
88
|
+
else
|
89
|
+
return
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
if after == ''.freeze
|
94
|
+
params[k] = v
|
95
|
+
elsif after == "[".freeze
|
96
|
+
params[name] = v
|
97
|
+
elsif after == "[]".freeze
|
98
|
+
params[k] ||= []
|
99
|
+
raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
|
100
|
+
params[k] << v
|
101
|
+
elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
|
102
|
+
child_key = $1
|
103
|
+
params[k] ||= []
|
104
|
+
raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
|
105
|
+
if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
|
106
|
+
normalize_params(params[k].last, child_key, v, depth - 1)
|
107
|
+
else
|
108
|
+
params[k] << normalize_params(make_params, child_key, v, depth - 1)
|
109
|
+
end
|
110
|
+
else
|
111
|
+
params[k] ||= make_params
|
112
|
+
raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k])
|
113
|
+
params[k] = normalize_params(params[k], after, v, depth - 1)
|
114
|
+
end
|
115
|
+
|
116
|
+
params
|
117
|
+
end
|
118
|
+
|
119
|
+
def make_params
|
120
|
+
@params_class.new @key_space_limit
|
121
|
+
end
|
122
|
+
|
123
|
+
def new_space_limit(key_space_limit)
|
124
|
+
self.class.new @params_class, key_space_limit, param_depth_limit
|
125
|
+
end
|
126
|
+
|
127
|
+
def new_depth_limit(param_depth_limit)
|
128
|
+
self.class.new @params_class, key_space_limit, param_depth_limit
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def params_hash_type?(obj)
|
134
|
+
obj.kind_of?(@params_class)
|
135
|
+
end
|
136
|
+
|
137
|
+
def params_hash_has_key?(hash, key)
|
138
|
+
return false if key =~ /\[\]/
|
139
|
+
|
140
|
+
key.split(/[\[\]]+/).inject(hash) do |h, part|
|
141
|
+
next h if part == ''
|
142
|
+
return false unless params_hash_type?(h) && h.key?(part)
|
143
|
+
h[part]
|
144
|
+
end
|
145
|
+
|
146
|
+
true
|
147
|
+
end
|
148
|
+
|
149
|
+
def unescape(s)
|
150
|
+
Utils.unescape(s)
|
151
|
+
end
|
152
|
+
|
153
|
+
class Params
|
154
|
+
def initialize(limit)
|
155
|
+
@limit = limit
|
156
|
+
@size = 0
|
157
|
+
@params = {}
|
158
|
+
end
|
159
|
+
|
160
|
+
def [](key)
|
161
|
+
@params[key]
|
162
|
+
end
|
163
|
+
|
164
|
+
def []=(key, value)
|
165
|
+
@size += key.size if key && !@params.key?(key)
|
166
|
+
raise RangeError, 'exceeded available parameter key space' if @size > @limit
|
167
|
+
@params[key] = value
|
168
|
+
end
|
169
|
+
|
170
|
+
def key?(key)
|
171
|
+
@params.key?(key)
|
172
|
+
end
|
173
|
+
|
174
|
+
def to_params_hash
|
175
|
+
hash = @params
|
176
|
+
hash.keys.each do |key|
|
177
|
+
value = hash[key]
|
178
|
+
if value.kind_of?(self.class)
|
179
|
+
if value.object_id == self.object_id
|
180
|
+
hash[key] = hash
|
181
|
+
else
|
182
|
+
hash[key] = value.to_params_hash
|
183
|
+
end
|
184
|
+
elsif value.kind_of?(Array)
|
185
|
+
value.map! {|x| x.kind_of?(self.class) ? x.to_params_hash : x}
|
186
|
+
end
|
187
|
+
end
|
188
|
+
hash
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
data/lib/rack/recursive.rb
CHANGED
@@ -14,11 +14,11 @@ module Rack
|
|
14
14
|
@url = URI(url)
|
15
15
|
@env = env
|
16
16
|
|
17
|
-
@env[PATH_INFO] =
|
18
|
-
@env[QUERY_STRING] =
|
19
|
-
@env[
|
20
|
-
@env["HTTP_PORT"] =
|
21
|
-
@env[
|
17
|
+
@env[PATH_INFO] = @url.path
|
18
|
+
@env[QUERY_STRING] = @url.query if @url.query
|
19
|
+
@env[HTTP_HOST] = @url.host if @url.host
|
20
|
+
@env["HTTP_PORT"] = @url.port if @url.port
|
21
|
+
@env[RACK_URL_SCHEME] = @url.scheme if @url.scheme
|
22
22
|
|
23
23
|
super "forwarding to #{url}"
|
24
24
|
end
|
@@ -40,7 +40,7 @@ module Rack
|
|
40
40
|
|
41
41
|
def _call(env)
|
42
42
|
@script_name = env[SCRIPT_NAME]
|
43
|
-
@app.call(env.merge(
|
43
|
+
@app.call(env.merge(RACK_RECURSIVE_INCLUDE => method(:include)))
|
44
44
|
rescue ForwardRequest => req
|
45
45
|
call(env.merge(req.env))
|
46
46
|
end
|
@@ -53,9 +53,9 @@ module Rack
|
|
53
53
|
|
54
54
|
env = env.merge(PATH_INFO => path,
|
55
55
|
SCRIPT_NAME => @script_name,
|
56
|
-
REQUEST_METHOD =>
|
56
|
+
REQUEST_METHOD => GET,
|
57
57
|
"CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
|
58
|
-
|
58
|
+
RACK_INPUT => StringIO.new(""))
|
59
59
|
@app.call(env)
|
60
60
|
end
|
61
61
|
end
|