Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 490 lines (428 sloc) 14.391 kB
5071302 @raggi Switch to emacs style encoding comment
raggi authored
1 # -*- encoding: binary -*-
a6320b9 @chneukirchen rack/utils needs FileUtils
chneukirchen authored
2 require 'fileutils'
ea814ff @rtomayko use Set instead of Array for STATUS_WITH_NO_ENTITY_BODY
rtomayko authored
3 require 'set'
4fe5360 @chneukirchen Make Rack::Request read multipart form data
chneukirchen authored
4 require 'tempfile'
24d5125 @shwoodard refactor of multipart module
shwoodard authored
5 require 'rack/multipart'
b8d3592 @tenderlove backporting cgi/util.rb from ruby 1.9 to rack
tenderlove authored
6
97ee1de @be9 Fix a regression caused by f043f32ce99
be9 authored
7 major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i }
f043f32 @sferik Restore Ruby 1.9.1 compatibility
sferik authored
8
0c3255d @toolmantim Added backport of Ruby URI's 1.9.3 DoS fix
toolmantim authored
9 if major == 1 && minor < 9
10 require 'rack/backports/uri/common_18'
11 elsif major == 1 && minor == 9 && patch < 3
12 require 'rack/backports/uri/common_192'
b8d3592 @tenderlove backporting cgi/util.rb from ruby 1.9 to rack
tenderlove authored
13 else
f0beb34 Backport URI.encode_www_form_component instead.
John Firebaugh authored
14 require 'uri/common'
b8d3592 @tenderlove backporting cgi/util.rb from ruby 1.9 to rack
tenderlove authored
15 end
4fe5360 @chneukirchen Make Rack::Request read multipart form data
chneukirchen authored
16
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
17 module Rack
376fa1e @chneukirchen Add RDocs
chneukirchen authored
18 # Rack::Utils contains a grab-bag of useful methods for writing web
19 # applications adopted from all kinds of Ruby libraries.
230d62c @chneukirchen Fix trailing whitespace. Sigh.
chneukirchen authored
20
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
21 module Utils
48d302c @spastorino Rack::Utils.escape should work with symbols in Ruby 1.8.7
spastorino authored
22 # URI escapes. (CGI style space to +)
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
23 def escape(s)
f0beb34 Backport URI.encode_www_form_component instead.
John Firebaugh authored
24 URI.encode_www_form_component(s)
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
25 end
26 module_function :escape
116f0ef @chneukirchen Remove trailing whitespace *sigh*
chneukirchen authored
27
3e9c822 @raggi escape_path (URI escape rather than CGI escape)
raggi authored
28 # Like URI escaping, but with %20 instead of +. Strictly speaking this is
29 # true URI escaping.
30 def escape_path(s)
31 escape(s).gsub('+', '%20')
32 end
33 module_function :escape_path
34
0700cd0 @jfirebaugh Just use CGI.escape/unescape.
jfirebaugh authored
35 # Unescapes a URI escaped string.
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
36 def unescape(s)
f0beb34 Backport URI.encode_www_form_component instead.
John Firebaugh authored
37 URI.decode_www_form_component(s)
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
38 end
39 module_function :unescape
116f0ef @chneukirchen Remove trailing whitespace *sigh*
chneukirchen authored
40
1189b1e @thinkerbot optimizations of parse/build query
thinkerbot authored
41 DEFAULT_SEP = /[&;] */n
5c4bd17 @josh Reverse hash for looking up status codes by symbol
josh authored
42
3adf1af @qerub utils.rb - Cleaned up parse_query
qerub authored
43 # Stolen from Mongrel, with some small modifications:
116f0ef @chneukirchen Remove trailing whitespace *sigh*
chneukirchen authored
44 # Parses a query string by breaking it up at the '&'
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
45 # and ';' characters. You can also use this to parse
46 # cookies by changing the characters used in the second
c5b420a @chneukirchen Small docfixes
chneukirchen authored
47 # parameter (which defaults to '&;').
1189b1e @thinkerbot optimizations of parse/build query
thinkerbot authored
48 def parse_query(qs, d = nil)
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
49 params = {}
488194e @josh Correct status code language to follow RFC 2616
josh authored
50
1189b1e @thinkerbot optimizations of parse/build query
thinkerbot authored
51 (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
7a55c98 Fix for form names containing "=": split first then unescape components
tlrobinson authored
52 k, v = p.split('=', 2).map { |x| unescape(x) }
5c00dd6 @josh Split parse_query utility into parse_query and parse_nested_query. pa…
josh authored
53 if cur = params[k]
54 if cur.class == Array
55 params[k] << v
56 else
57 params[k] = [cur, v]
58 end
59 else
60 params[k] = v
61 end
6e330bd @josh Add support for nested parameter parsing
josh authored
62 end
63
64 return params
65 end
66 module_function :parse_query
67
1189b1e @thinkerbot optimizations of parse/build query
thinkerbot authored
68 def parse_nested_query(qs, d = nil)
5c00dd6 @josh Split parse_query utility into parse_query and parse_nested_query. pa…
josh authored
69 params = {}
70
1189b1e @thinkerbot optimizations of parse/build query
thinkerbot authored
71 (qs || '').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
9134176 @raggi Correct bug L#94 reported by Nikolai Lugovoi, keys should not form pa…
raggi authored
72 k, v = p.split('=', 2).map { |s| unescape(s) }
5c00dd6 @josh Split parse_query utility into parse_query and parse_nested_query. pa…
josh authored
73 normalize_params(params, k, v)
74 end
75
76 return params
77 end
78 module_function :parse_nested_query
79
6e330bd @josh Add support for nested parameter parsing
josh authored
80 def normalize_params(params, name, v = nil)
40eba67 @josh Add anchor to nested params parsing regexp to prevent stack overflows
josh authored
81 name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
6e330bd @josh Add support for nested parameter parsing
josh authored
82 k = $1 || ''
83 after = $' || ''
488194e @josh Correct status code language to follow RFC 2616
josh authored
84
6e330bd @josh Add support for nested parameter parsing
josh authored
85 return if k.empty?
86
87 if after == ""
5c00dd6 @josh Split parse_query utility into parse_query and parse_nested_query. pa…
josh authored
88 params[k] = v
6e330bd @josh Add support for nested parameter parsing
josh authored
89 elsif after == "[]"
90 params[k] ||= []
880d9be @rob-at-thewebfellas Added extra nested params error handling and added messages to except…
rob-at-thewebfellas authored
91 raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
6e330bd @josh Add support for nested parameter parsing
josh authored
92 params[k] << v
93 elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$)
94 child_key = $1
95 params[k] ||= []
880d9be @rob-at-thewebfellas Added extra nested params error handling and added messages to except…
rob-at-thewebfellas authored
96 raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
6e330bd @josh Add support for nested parameter parsing
josh authored
97 if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key)
98 normalize_params(params[k].last, child_key, v)
99 else
100 params[k] << normalize_params({}, child_key, v)
101 end
102 else
103 params[k] ||= {}
880d9be @rob-at-thewebfellas Added extra nested params error handling and added messages to except…
rob-at-thewebfellas authored
104 raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash)
6e330bd @josh Add support for nested parameter parsing
josh authored
105 params[k] = normalize_params(params[k], after, v)
3adf1af @qerub utils.rb - Cleaned up parse_query
qerub authored
106 end
488194e @josh Correct status code language to follow RFC 2616
josh authored
107
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
108 return params
109 end
6e330bd @josh Add support for nested parameter parsing
josh authored
110 module_function :normalize_params
488194e @josh Correct status code language to follow RFC 2616
josh authored
111
31f8a93 @qerub utils.rb, spec_rack_utils.rb - Added build_query, the inverse of pars…
qerub authored
112 def build_query(params)
113 params.map { |k, v|
114 if v.class == Array
115 build_query(v.map { |x| [k, x] })
116 else
1189b1e @thinkerbot optimizations of parse/build query
thinkerbot authored
117 "#{escape(k)}=#{escape(v)}"
31f8a93 @qerub utils.rb, spec_rack_utils.rb - Added build_query, the inverse of pars…
qerub authored
118 end
119 }.join("&")
120 end
121 module_function :build_query
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
122
c4eb1ae @josh Add Utils.build_nested_query to complement Utils.parse_nested_query a…
josh authored
123 def build_nested_query(value, prefix = nil)
124 case value
125 when Array
126 value.map { |v|
127 build_nested_query(v, "#{prefix}[]")
128 }.join("&")
129 when Hash
130 value.map { |k, v|
131 build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
132 }.join("&")
133 when String
134 raise ArgumentError, "value must be a Hash" if prefix.nil?
135 "#{prefix}=#{escape(value)}"
136 else
137 prefix
138 end
139 end
140 module_function :build_nested_query
141
b4d0dc7 @manveru Improve performance and flexibility of Rack::Utils.escape_html
manveru authored
142 ESCAPE_HTML = {
143 "&" => "&amp;",
144 "<" => "&lt;",
145 ">" => "&gt;",
37ca253 @thinkerbot updated escape_html to use hex entities and to escape forward slash
thinkerbot authored
146 "'" => "&#x27;",
b4d0dc7 @manveru Improve performance and flexibility of Rack::Utils.escape_html
manveru authored
147 '"' => "&quot;",
37ca253 @thinkerbot updated escape_html to use hex entities and to escape forward slash
thinkerbot authored
148 "/" => "&#x2F;"
b4d0dc7 @manveru Improve performance and flexibility of Rack::Utils.escape_html
manveru authored
149 }
5a942eb @raggi Fix bugs with MRI 1.8.x regex engine
raggi authored
150 if //.respond_to?(:encoding)
151 ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
152 else
153 # On 1.8, there is a kcode = 'u' bug that allows for XSS otherwhise
154 # TODO doesn't apply to jruby, so a better condition above might be preferable?
155 ESCAPE_HTML_PATTERN = /#{Regexp.union(*ESCAPE_HTML.keys)}/n
156 end
b4d0dc7 @manveru Improve performance and flexibility of Rack::Utils.escape_html
manveru authored
157
376fa1e @chneukirchen Add RDocs
chneukirchen authored
158 # Escape ampersands, brackets and quotes to their HTML/XML entities.
69f11f6 @chneukirchen Add Rack::ShowExceptions
chneukirchen authored
159 def escape_html(string)
b4d0dc7 @manveru Improve performance and flexibility of Rack::Utils.escape_html
manveru authored
160 string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
69f11f6 @chneukirchen Add Rack::ShowExceptions
chneukirchen authored
161 end
162 module_function :escape_html
163
0f2dab5 @qerub Added support for Accept-Encoding (via Request#accept_encoding and Ut…
qerub authored
164 def select_best_encoding(available_encodings, accept_encoding)
165 # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
166
167 expanded_accept_encoding =
168 accept_encoding.map { |m, q|
169 if m == "*"
170 (available_encodings - accept_encoding.map { |m2, _| m2 }).map { |m2| [m2, q] }
171 else
172 [[m, q]]
173 end
174 }.inject([]) { |mem, list|
175 mem + list
176 }
177
178 encoding_candidates = expanded_accept_encoding.sort_by { |_, q| -q }.map { |m, _| m }
179
180 unless encoding_candidates.include?("identity")
181 encoding_candidates.push("identity")
182 end
183
184 expanded_accept_encoding.find_all { |m, q|
185 q == 0.0
186 }.each { |m, _|
187 encoding_candidates.delete(m)
188 }
189
190 return (encoding_candidates & available_encodings)[0]
191 end
192 module_function :select_best_encoding
193
39fec31 @josh Don't buffer response bodies in session store by creating an unnecess…
josh authored
194 def set_cookie_header!(header, key, value)
195 case value
196 when Hash
197 domain = "; domain=" + value[:domain] if value[:domain]
198 path = "; path=" + value[:path] if value[:path]
199 # According to RFC 2109, we need dashes here.
200 # N.B.: cgi.rb uses spaces...
79c7ccf @manveru Implement proper RFC 2822 Time format based on RFC 2109 example for c…
manveru authored
201 expires = "; expires=" +
202 rfc2822(value[:expires].clone.gmtime) if value[:expires]
39fec31 @josh Don't buffer response bodies in session store by creating an unnecess…
josh authored
203 secure = "; secure" if value[:secure]
204 httponly = "; HttpOnly" if value[:httponly]
205 value = value[:value]
206 end
207 value = [value] unless Array === value
208 cookie = escape(key) + "=" +
209 value.map { |v| escape v }.join("&") +
210 "#{domain}#{path}#{expires}#{secure}#{httponly}"
211
212 case header["Set-Cookie"]
c028a23 @rtomayko cookie utility methods use multiline strings instead of arrays
rtomayko authored
213 when nil, ''
39fec31 @josh Don't buffer response bodies in session store by creating an unnecess…
josh authored
214 header["Set-Cookie"] = cookie
c028a23 @rtomayko cookie utility methods use multiline strings instead of arrays
rtomayko authored
215 when String
216 header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n")
217 when Array
218 header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n")
39fec31 @josh Don't buffer response bodies in session store by creating an unnecess…
josh authored
219 end
220
221 nil
222 end
223 module_function :set_cookie_header!
224
225 def delete_cookie_header!(header, key, value = {})
c028a23 @rtomayko cookie utility methods use multiline strings instead of arrays
rtomayko authored
226 case header["Set-Cookie"]
227 when nil, ''
228 cookies = []
229 when String
230 cookies = header["Set-Cookie"].split("\n")
231 when Array
232 cookies = header["Set-Cookie"]
39fec31 @josh Don't buffer response bodies in session store by creating an unnecess…
josh authored
233 end
234
c028a23 @rtomayko cookie utility methods use multiline strings instead of arrays
rtomayko authored
235 cookies.reject! { |cookie|
55cbbc9 @zbrock allow delete of cookies with same name but different domain
zbrock authored
236 if value[:domain]
237 cookie =~ /\A#{escape(key)}=.*domain=#{value[:domain]}/
eead3b2 @joevandyk Fix cookie deletion with path specified
joevandyk authored
238 elsif value[:path]
239 cookie =~ /\A#{escape(key)}=.*path=#{value[:path]}/
55cbbc9 @zbrock allow delete of cookies with same name but different domain
zbrock authored
240 else
241 cookie =~ /\A#{escape(key)}=/
242 end
39fec31 @josh Don't buffer response bodies in session store by creating an unnecess…
josh authored
243 }
244
c028a23 @rtomayko cookie utility methods use multiline strings instead of arrays
rtomayko authored
245 header["Set-Cookie"] = cookies.join("\n")
246
39fec31 @josh Don't buffer response bodies in session store by creating an unnecess…
josh authored
247 set_cookie_header!(header, key,
248 {:value => '', :path => nil, :domain => nil,
249 :expires => Time.at(0) }.merge(value))
250
251 nil
252 end
253 module_function :delete_cookie_header!
254
b155fc5 @djanowski Make ShowExceptions respond with plain text on AJAX calls.
djanowski authored
255 # Return the bytesize of String; uses String#size under Ruby 1.8 and
980d681 @rtomayko Add Rack::Utils.bytesize function, use everywhere
rtomayko authored
256 # String#bytesize under 1.9.
257 if ''.respond_to?(:bytesize)
258 def bytesize(string)
259 string.bytesize
260 end
261 else
262 def bytesize(string)
263 string.size
264 end
265 end
266 module_function :bytesize
267
79c7ccf @manveru Implement proper RFC 2822 Time format based on RFC 2109 example for c…
manveru authored
268 # Modified version of stdlib time.rb Time#rfc2822 to use '%d-%b-%Y' instead
269 # of '% %b %Y'.
270 # It assumes that the time is in GMT to comply to the RFC 2109.
271 #
272 # NOTE: I'm not sure the RFC says it requires GMT, but is ambigous enough
273 # that I'm certain someone implemented only that option.
274 # Do not use %a and %b from Time.strptime, it would use localized names for
275 # weekday and month.
276 #
277 def rfc2822(time)
278 wday = Time::RFC2822_DAY_NAME[time.wday]
279 mon = Time::RFC2822_MONTH_NAME[time.mon - 1]
9ad83ca @manveru Replace %T with %H:%M:%S for compatibility on Windows
manveru authored
280 time.strftime("#{wday}, %d-#{mon}-%Y %H:%M:%S GMT")
79c7ccf @manveru Implement proper RFC 2822 Time format based on RFC 2109 example for c…
manveru authored
281 end
282 module_function :rfc2822
283
623a5fb @raggi Move Rack::File.byte_ranges to Rack::Utils
raggi authored
284 # Parses the "Range:" header, if present, into an array of Range objects.
285 # Returns nil if the header is missing or syntactically invalid.
286 # Returns an empty array if none of the ranges are satisfiable.
287 def byte_ranges(env, size)
288 # See <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35>
289 http_range = env['HTTP_RANGE']
290 return nil unless http_range
291 ranges = []
292 http_range.split(/,\s*/).each do |range_spec|
293 matches = range_spec.match(/bytes=(\d*)-(\d*)/)
294 return nil unless matches
295 r0,r1 = matches[1], matches[2]
296 if r0.empty?
297 return nil if r1.empty?
298 # suffix-byte-range-spec, represents trailing suffix of file
299 r0 = [size - r1.to_i, 0].max
300 r1 = size - 1
301 else
302 r0 = r0.to_i
303 if r1.empty?
304 r1 = size - 1
305 else
306 r1 = r1.to_i
307 return nil if r1 < r0 # backwards range is syntactically invalid
308 r1 = size-1 if r1 >= size
309 end
310 end
311 ranges << (r0..r1) if r0 <= r1
312 end
313 ranges
314 end
315 module_function :byte_ranges
316
8eac320 @scytrin Simplification of Rack::Utils::Context
scytrin authored
317 # Context allows the use of a compatible middleware at different points
318 # in a request handling stack. A compatible middleware must define
319 # #context which should take the arguments env and app. The first of which
320 # would be the request environment. The second of which would be the rack
321 # application that the request would be forwarded to.
322 class Context
ea7f9f7 @scytrin utils.rb - Utils::Context - addition of introspection methods
scytrin authored
323 attr_reader :for, :app
8eac320 @scytrin Simplification of Rack::Utils::Context
scytrin authored
324
325 def initialize(app_f, app_r)
1990057 @scytrin Added documentation, checks, and tests for Rack::Utils::Context
scytrin authored
326 raise 'running context does not respond to #context' unless app_f.respond_to? :context
8eac320 @scytrin Simplification of Rack::Utils::Context
scytrin authored
327 @for, @app = app_f, app_r
14fdd96 @scytrin Addition of Rack::Utils::Context
scytrin authored
328 end
8eac320 @scytrin Simplification of Rack::Utils::Context
scytrin authored
329
330 def call(env)
331 @for.context(env, @app)
14fdd96 @scytrin Addition of Rack::Utils::Context
scytrin authored
332 end
8eac320 @scytrin Simplification of Rack::Utils::Context
scytrin authored
333
334 def recontext(app)
335 self.class.new(@for, app)
ba05ad9 @scytrin utils.rb - addition of recontexting from a Context
scytrin authored
336 end
8eac320 @scytrin Simplification of Rack::Utils::Context
scytrin authored
337
338 def context(env, app=@app)
339 recontext(app).call(env)
14fdd96 @scytrin Addition of Rack::Utils::Context
scytrin authored
340 end
341 end
342
76c3aef @rtomayko Use HeaderHash where header case should be insensitive
rtomayko authored
343 # A case-insensitive Hash that preserves the original case of a
344 # header when set.
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
345 class HeaderHash < Hash
cdf1361 HeaderHash.new avoids unnecessary object creation
Eric Wong authored
346 def self.new(hash={})
347 HeaderHash === hash ? hash : super(hash)
348 end
349
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
350 def initialize(hash={})
07c1814 @FooBarWidget Fix Rack::Utils::HeaderHash#delete: it's supposed to return the delet…
FooBarWidget authored
351 super()
4e17443 @rtomayko Non-normalizing HeaderHash with case-insensitive lookups
rtomayko authored
352 @names = {}
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
353 hash.each { |k, v| self[k] = v }
354 end
116f0ef @chneukirchen Remove trailing whitespace *sigh*
chneukirchen authored
355
0f1bd25 HeaderHash#each yields Lint-OK multivalue headers
Eric Wong authored
356 def each
357 super do |k, v|
358 yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)
359 end
360 end
361
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
362 def to_hash
d0e8aed @rkh simpler, dry implementation for HeaderHash#to_hash, fixes #177
rkh authored
363 hash = {}
364 each { |k,v| hash[k] = v }
365 hash
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
366 end
367
368 def [](k)
b937c01 @thedarkone Fix the phantom header key bug.
thedarkone authored
369 super(k) || super(@names[k.downcase])
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
370 end
116f0ef @chneukirchen Remove trailing whitespace *sigh*
chneukirchen authored
371
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
372 def []=(k, v)
4682d96 @thedarkone Avoiding invoking #delete unless unnecessary.
thedarkone authored
373 canonical = k.downcase
be5a8b5 @thedarkone No need to delete a key that doesn't exist.
thedarkone authored
374 delete k if @names[canonical] && @names[canonical] != k # .delete is expensive, don't invoke it unless necessary
4682d96 @thedarkone Avoiding invoking #delete unless unnecessary.
thedarkone authored
375 @names[k] = @names[canonical] = k
4e17443 @rtomayko Non-normalizing HeaderHash with case-insensitive lookups
rtomayko authored
376 super k, v
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
377 end
378
4e17443 @rtomayko Non-normalizing HeaderHash with case-insensitive lookups
rtomayko authored
379 def delete(k)
0bc5662 @jeremy Speed up common header reads by avoiding downcase
jeremy authored
380 canonical = k.downcase
07c1814 @FooBarWidget Fix Rack::Utils::HeaderHash#delete: it's supposed to return the delet…
FooBarWidget authored
381 result = super @names.delete(canonical)
0bc5662 @jeremy Speed up common header reads by avoiding downcase
jeremy authored
382 @names.delete_if { |name,| name.downcase == canonical }
07c1814 @FooBarWidget Fix Rack::Utils::HeaderHash#delete: it's supposed to return the delet…
FooBarWidget authored
383 result
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
384 end
4e17443 @rtomayko Non-normalizing HeaderHash with case-insensitive lookups
rtomayko authored
385
386 def include?(k)
0bc5662 @jeremy Speed up common header reads by avoiding downcase
jeremy authored
387 @names.include?(k) || @names.include?(k.downcase)
4e17443 @rtomayko Non-normalizing HeaderHash with case-insensitive lookups
rtomayko authored
388 end
389
390 alias_method :has_key?, :include?
391 alias_method :member?, :include?
392 alias_method :key?, :include?
c00b386 @rtomayko Implement HeaderHash#merge! and HeaderHash#merge
rtomayko authored
393
394 def merge!(other)
395 other.each { |k, v| self[k] = v }
396 self
397 end
398
399 def merge(other)
400 hash = dup
401 hash.merge! other
402 end
e0322ed @kamal Add Rack::Utils::HeaderHash#replace
kamal authored
403
404 def replace(other)
405 clear
406 other.each { |k, v| self[k] = v }
407 self
408 end
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
409 end
b064d53 @chneukirchen Make multipart reading more robust
chneukirchen authored
410
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
411 # Every standard HTTP code mapped to the appropriate message.
ca6f9f9 Update Rack::Utils::HTTP_STATUS_CODES hash
Eric Wong authored
412 # Generated with:
413 # curl -s http://www.iana.org/assignments/http-status-codes | \
414 # ruby -ane 'm = /^(\d{3}) +(\S[^\[(]+)/.match($_) and
415 # puts " #{m[1]} => \x27#{m[2].strip}x27,"'
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
416 HTTP_STATUS_CODES = {
417 100 => 'Continue',
418 101 => 'Switching Protocols',
ca6f9f9 Update Rack::Utils::HTTP_STATUS_CODES hash
Eric Wong authored
419 102 => 'Processing',
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
420 200 => 'OK',
421 201 => 'Created',
422 202 => 'Accepted',
423 203 => 'Non-Authoritative Information',
424 204 => 'No Content',
425 205 => 'Reset Content',
426 206 => 'Partial Content',
ca6f9f9 Update Rack::Utils::HTTP_STATUS_CODES hash
Eric Wong authored
427 207 => 'Multi-Status',
428 226 => 'IM Used',
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
429 300 => 'Multiple Choices',
430 301 => 'Moved Permanently',
488194e @josh Correct status code language to follow RFC 2616
josh authored
431 302 => 'Found',
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
432 303 => 'See Other',
433 304 => 'Not Modified',
434 305 => 'Use Proxy',
ca6f9f9 Update Rack::Utils::HTTP_STATUS_CODES hash
Eric Wong authored
435 306 => 'Reserved',
488194e @josh Correct status code language to follow RFC 2616
josh authored
436 307 => 'Temporary Redirect',
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
437 400 => 'Bad Request',
438 401 => 'Unauthorized',
439 402 => 'Payment Required',
440 403 => 'Forbidden',
441 404 => 'Not Found',
442 405 => 'Method Not Allowed',
443 406 => 'Not Acceptable',
444 407 => 'Proxy Authentication Required',
488194e @josh Correct status code language to follow RFC 2616
josh authored
445 408 => 'Request Timeout',
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
446 409 => 'Conflict',
447 410 => 'Gone',
448 411 => 'Length Required',
449 412 => 'Precondition Failed',
450 413 => 'Request Entity Too Large',
ca6f9f9 Update Rack::Utils::HTTP_STATUS_CODES hash
Eric Wong authored
451 414 => 'Request-URI Too Long',
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
452 415 => 'Unsupported Media Type',
488194e @josh Correct status code language to follow RFC 2616
josh authored
453 416 => 'Requested Range Not Satisfiable',
454 417 => 'Expectation Failed',
ca6f9f9 Update Rack::Utils::HTTP_STATUS_CODES hash
Eric Wong authored
455 422 => 'Unprocessable Entity',
456 423 => 'Locked',
457 424 => 'Failed Dependency',
458 426 => 'Upgrade Required',
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
459 500 => 'Internal Server Error',
460 501 => 'Not Implemented',
461 502 => 'Bad Gateway',
462 503 => 'Service Unavailable',
488194e @josh Correct status code language to follow RFC 2616
josh authored
463 504 => 'Gateway Timeout',
ca6f9f9 Update Rack::Utils::HTTP_STATUS_CODES hash
Eric Wong authored
464 505 => 'HTTP Version Not Supported',
465 506 => 'Variant Also Negotiates',
466 507 => 'Insufficient Storage',
467 510 => 'Not Extended',
d110c39 @chneukirchen Add a list of HTTP status messages
chneukirchen authored
468 }
469
77725c7 Moved STATUS_WITH_NO_ENTITY_BODY into Rack::Utils
Dan Kubb authored
470 # Responses with HTTP status codes that should not have an entity body
2c5b076 @dkubb Add 205 Reset Content to the list of statuses without a message body
dkubb authored
471 STATUS_WITH_NO_ENTITY_BODY = Set.new((100..199).to_a << 204 << 205 << 304)
77725c7 Moved STATUS_WITH_NO_ENTITY_BODY into Rack::Utils
Dan Kubb authored
472
d3893c2 @raggi 186 bro :'(
raggi authored
473 SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message|
e9d7699 @spastorino PERF: change inject({}) to Hash + map
spastorino authored
474 [message.downcase.gsub(/\s|-/, '_').to_sym, code]
d3893c2 @raggi 186 bro :'(
raggi authored
475 }.flatten]
5c4bd17 @josh Reverse hash for looking up status codes by symbol
josh authored
476
1ffa95c @josh Status code lookup utility
josh authored
477 def status_code(status)
478 if status.is_a?(Symbol)
479 SYMBOL_TO_STATUS_CODE[status] || 500
480 else
481 status.to_i
482 end
483 end
484 module_function :status_code
5c4bd17 @josh Reverse hash for looking up status codes by symbol
josh authored
485
24d5125 @shwoodard refactor of multipart module
shwoodard authored
486 Multipart = Rack::Multipart
4fe5360 @chneukirchen Make Rack::Request read multipart form data
chneukirchen authored
487
7ed819a @chneukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
488 end
489 end
Something went wrong with that request. Please try again.