lib/rack/utils.rb in rack-0.4.0 vs lib/rack/utils.rb in rack-0.9.0

- old
+ new

@@ -1,5 +1,6 @@ +require 'set' require 'tempfile' module Rack # Rack::Utils contains a grab-bag of useful methods for writing web # applications adopted from all kinds of Ruby libraries. @@ -29,29 +30,29 @@ # cookies by changing the characters used in the second # parameter (which defaults to '&;'). def parse_query(qs, d = '&;') params = {} - + (qs || '').split(/[#{d}] */n).each do |p| k, v = unescape(p).split('=', 2) - + if cur = params[k] if cur.class == Array params[k] << v else params[k] = [cur, v] end else params[k] = v end end - + return params end module_function :parse_query - + def build_query(params) params.map { |k, v| if v.class == Array build_query(v.map { |x| [k, x] }) else @@ -153,31 +154,53 @@ pp.pp @app end end end - # A case-normalizing Hash, adjusting on [] and []=. + # A case-insensitive Hash that preserves the original case of a + # header when set. class HeaderHash < Hash def initialize(hash={}) + @names = {} hash.each { |k, v| self[k] = v } end def to_hash {}.replace(self) end def [](k) - super capitalize(k) + super @names[k.downcase] end def []=(k, v) - super capitalize(k), v + delete k + @names[k.downcase] = k + super k, v end - def capitalize(k) - k.to_s.downcase.gsub(/^.|[-_\s]./) { |x| x.upcase } + def delete(k) + super @names.delete(k.downcase) end + + def include?(k) + @names.has_key? k.downcase + end + + alias_method :has_key?, :include? + alias_method :member?, :include? + alias_method :key?, :include? + + def merge!(other) + other.each { |k, v| self[k] = v } + self + end + + def merge(other) + hash = dup + hash.merge! other + end end # Every standard HTTP code mapped to the appropriate message. # Stolen from Mongrel. HTTP_STATUS_CODES = { @@ -190,36 +213,42 @@ 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', - 302 => 'Moved Temporarily', + 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', + 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', - 408 => 'Request Time-out', + 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', - 504 => 'Gateway Time-out', - 505 => 'HTTP Version not supported' + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported' } + + # Responses with HTTP status codes that should not have an entity body + STATUS_WITH_NO_ENTITY_BODY = Set.new((100..199).to_a << 204 << 304) # A multipart form data parser, adapted from IOWA. # # Usually, Rack::Request#POST takes care of calling this.