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.

Files changed (144) hide show
  1. checksums.yaml +5 -5
  2. data/COPYING +1 -1
  3. data/HISTORY.md +138 -8
  4. data/README.rdoc +17 -25
  5. data/Rakefile +6 -14
  6. data/SPEC +8 -9
  7. data/contrib/rack_logo.svg +164 -111
  8. data/example/protectedlobster.rb +1 -1
  9. data/example/protectedlobster.ru +1 -1
  10. data/lib/rack/auth/abstract/request.rb +5 -1
  11. data/lib/rack/auth/digest/params.rb +2 -3
  12. data/lib/rack/auth/digest/request.rb +1 -1
  13. data/lib/rack/body_proxy.rb +14 -9
  14. data/lib/rack/builder.rb +3 -3
  15. data/lib/rack/chunked.rb +5 -5
  16. data/lib/rack/{commonlogger.rb → common_logger.rb} +3 -3
  17. data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
  18. data/lib/rack/content_length.rb +2 -2
  19. data/lib/rack/deflater.rb +4 -4
  20. data/lib/rack/directory.rb +66 -54
  21. data/lib/rack/etag.rb +4 -3
  22. data/lib/rack/events.rb +154 -0
  23. data/lib/rack/file.rb +63 -39
  24. data/lib/rack/handler/cgi.rb +15 -16
  25. data/lib/rack/handler/fastcgi.rb +13 -14
  26. data/lib/rack/handler/lsws.rb +11 -11
  27. data/lib/rack/handler/scgi.rb +15 -15
  28. data/lib/rack/handler/thin.rb +3 -0
  29. data/lib/rack/handler/webrick.rb +22 -24
  30. data/lib/rack/handler.rb +3 -25
  31. data/lib/rack/head.rb +15 -17
  32. data/lib/rack/lint.rb +38 -38
  33. data/lib/rack/lobster.rb +1 -1
  34. data/lib/rack/lock.rb +6 -10
  35. data/lib/rack/logger.rb +2 -2
  36. data/lib/rack/media_type.rb +38 -0
  37. data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
  38. data/lib/rack/mime.rb +18 -5
  39. data/lib/rack/mock.rb +35 -53
  40. data/lib/rack/multipart/generator.rb +5 -5
  41. data/lib/rack/multipart/parser.rb +272 -158
  42. data/lib/rack/multipart/uploaded_file.rb +1 -2
  43. data/lib/rack/multipart.rb +35 -6
  44. data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
  45. data/lib/rack/query_parser.rb +192 -0
  46. data/lib/rack/recursive.rb +8 -8
  47. data/lib/rack/request.rb +383 -307
  48. data/lib/rack/response.rb +129 -56
  49. data/lib/rack/rewindable_input.rb +1 -12
  50. data/lib/rack/runtime.rb +10 -18
  51. data/lib/rack/sendfile.rb +5 -7
  52. data/lib/rack/server.rb +31 -25
  53. data/lib/rack/session/abstract/id.rb +95 -135
  54. data/lib/rack/session/cookie.rb +26 -28
  55. data/lib/rack/session/memcache.rb +8 -14
  56. data/lib/rack/session/pool.rb +14 -21
  57. data/lib/rack/show_exceptions.rb +386 -0
  58. data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
  59. data/lib/rack/static.rb +30 -5
  60. data/lib/rack/tempfile_reaper.rb +2 -2
  61. data/lib/rack/urlmap.rb +15 -14
  62. data/lib/rack/utils.rb +135 -210
  63. data/lib/rack.rb +70 -21
  64. data/rack.gemspec +7 -5
  65. data/test/builder/an_underscore_app.rb +5 -0
  66. data/test/builder/options.ru +1 -1
  67. data/test/cgi/test.fcgi +1 -0
  68. data/test/cgi/test.gz +0 -0
  69. data/test/helper.rb +34 -0
  70. data/test/multipart/filename_with_encoded_words +7 -0
  71. data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
  72. data/test/multipart/quoted +15 -0
  73. data/test/multipart/rack-logo.png +0 -0
  74. data/test/multipart/unity3d_wwwform +11 -0
  75. data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
  76. data/test/spec_auth_basic.rb +27 -19
  77. data/test/spec_auth_digest.rb +47 -46
  78. data/test/spec_body_proxy.rb +27 -27
  79. data/test/spec_builder.rb +51 -41
  80. data/test/spec_cascade.rb +24 -22
  81. data/test/spec_cgi.rb +49 -67
  82. data/test/spec_chunked.rb +36 -34
  83. data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
  84. data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
  85. data/test/spec_config.rb +3 -2
  86. data/test/spec_content_length.rb +18 -17
  87. data/test/spec_content_type.rb +13 -12
  88. data/test/spec_deflater.rb +66 -40
  89. data/test/spec_directory.rb +87 -27
  90. data/test/spec_etag.rb +32 -31
  91. data/test/spec_events.rb +133 -0
  92. data/test/spec_fastcgi.rb +50 -72
  93. data/test/spec_file.rb +107 -77
  94. data/test/spec_handler.rb +19 -34
  95. data/test/spec_head.rb +15 -14
  96. data/test/spec_lint.rb +162 -197
  97. data/test/spec_lobster.rb +24 -23
  98. data/test/spec_lock.rb +69 -39
  99. data/test/spec_logger.rb +4 -3
  100. data/test/spec_media_type.rb +42 -0
  101. data/test/spec_method_override.rb +83 -0
  102. data/test/spec_mime.rb +19 -19
  103. data/test/spec_mock.rb +196 -151
  104. data/test/spec_multipart.rb +317 -201
  105. data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
  106. data/test/spec_recursive.rb +17 -14
  107. data/test/spec_request.rb +768 -607
  108. data/test/spec_response.rb +214 -111
  109. data/test/spec_rewindable_input.rb +50 -40
  110. data/test/spec_runtime.rb +11 -10
  111. data/test/spec_sendfile.rb +30 -35
  112. data/test/spec_server.rb +78 -52
  113. data/test/spec_session_abstract_id.rb +11 -33
  114. data/test/spec_session_abstract_session_hash.rb +28 -0
  115. data/test/spec_session_cookie.rb +97 -65
  116. data/test/spec_session_memcache.rb +63 -101
  117. data/test/spec_session_pool.rb +48 -84
  118. data/test/spec_show_exceptions.rb +80 -0
  119. data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
  120. data/test/spec_static.rb +71 -32
  121. data/test/spec_tempfile_reaper.rb +11 -10
  122. data/test/spec_thin.rb +55 -50
  123. data/test/spec_urlmap.rb +79 -78
  124. data/test/spec_utils.rb +441 -346
  125. data/test/spec_version.rb +2 -8
  126. data/test/spec_webrick.rb +91 -67
  127. data/test/static/foo.html +1 -0
  128. data/test/testrequest.rb +1 -1
  129. data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
  130. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
  131. metadata +103 -69
  132. data/KNOWN-ISSUES +0 -44
  133. data/lib/rack/backports/uri/common_18.rb +0 -56
  134. data/lib/rack/backports/uri/common_192.rb +0 -52
  135. data/lib/rack/backports/uri/common_193.rb +0 -29
  136. data/lib/rack/handler/evented_mongrel.rb +0 -8
  137. data/lib/rack/handler/mongrel.rb +0 -106
  138. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  139. data/lib/rack/showexceptions.rb +0 -387
  140. data/lib/rack/utils/okjson.rb +0 -600
  141. data/test/spec_methodoverride.rb +0 -111
  142. data/test/spec_mongrel.rb +0 -182
  143. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  144. 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
@@ -14,11 +14,11 @@ module Rack
14
14
  @url = URI(url)
15
15
  @env = env
16
16
 
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
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('rack.recursive.include' => method(:include)))
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 => "GET",
56
+ REQUEST_METHOD => GET,
57
57
  "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
58
- "rack.input" => StringIO.new(""))
58
+ RACK_INPUT => StringIO.new(""))
59
59
  @app.call(env)
60
60
  end
61
61
  end