lib/rack/request.rb in rack-1.5.5 vs lib/rack/request.rb in rack-1.6.0.beta

- old
+ new

@@ -6,14 +6,10 @@ # constructor will be directly modified. # # req = Rack::Request.new(env) # req.post? # req.params["data"] - # - # The environment hash passed will store a reference to the Request object - # instantiated so that it will only instantiate if an instance of the Request - # object doesn't already exist. class Request # The environment of the request. attr_reader :env @@ -54,11 +50,11 @@ # { 'charset' => 'utf-8' } def media_type_params return {} if content_type.nil? Hash[*content_type.split(/\s*[;,]\s*/)[1..-1]. collect { |s| s.split('=', 2) }. - map { |k,v| [k.downcase, v] }.flatten] + map { |k,v| [k.downcase, strip_doublequotes(v)] }.flatten] end # The character set of the request body if a "charset" media type # parameter was given, or nil if no "charset" was specified. Note # that, per RFC2616, text/* media types that specify no explicit @@ -99,19 +95,19 @@ elsif port = @env['HTTP_X_FORWARDED_PORT'] port.to_i elsif @env.has_key?("HTTP_X_FORWARDED_HOST") DEFAULT_PORTS[scheme] elsif @env.has_key?("HTTP_X_FORWARDED_PROTO") - DEFAULT_PORTS[@env['HTTP_X_FORWARDED_PROTO']] + DEFAULT_PORTS[@env['HTTP_X_FORWARDED_PROTO'].split(',')[0]] else @env["SERVER_PORT"].to_i end end def host # Remove port number. - host_with_port.to_s.gsub(/:\d+\z/, '') + host_with_port.to_s.sub(/:\d+\z/, '') end def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end def path_info=(s); @env["PATH_INFO"] = s.to_s end @@ -126,10 +122,13 @@ def head?; request_method == "HEAD" end # Checks the HTTP request method (or verb) to see if it was of type OPTIONS def options?; request_method == "OPTIONS" end + # Checks the HTTP request method (or verb) to see if it was of type LINK + def link?; request_method == "LINK" end + # Checks the HTTP request method (or verb) to see if it was of type PATCH def patch?; request_method == "PATCH" end # Checks the HTTP request method (or verb) to see if it was of type POST def post?; request_method == "POST" end @@ -138,11 +137,14 @@ def put?; request_method == "PUT" end # Checks the HTTP request method (or verb) to see if it was of type TRACE def trace?; request_method == "TRACE" end + # Checks the HTTP request method (or verb) to see if it was of type UNLINK + def unlink?; request_method == "UNLINK" end + # The set of form-data media-types. Requests that do not indicate # one of the media types presents in this list will not be eligible # for form-data / param parsing. FORM_DATA_MEDIA_TYPES = [ 'application/x-www-form-urlencoded', @@ -184,12 +186,13 @@ # Returns the data received in the query string. def GET if @env["rack.request.query_string"] == query_string @env["rack.request.query_hash"] else + p = parse_query(query_string) @env["rack.request.query_string"] = query_string - @env["rack.request.query_hash"] = parse_query(query_string) + @env["rack.request.query_hash"] = p end end # Returns the data received in the request body. # @@ -199,11 +202,10 @@ if @env["rack.input"].nil? raise "Missing rack.input" elsif @env["rack.request.form_input"].equal? @env["rack.input"] @env["rack.request.form_hash"] elsif form_data? || parseable_data? - @env["rack.request.form_input"] = @env["rack.input"] unless @env["rack.request.form_hash"] = parse_multipart(env) form_vars = @env["rack.input"].read # Fix for Safari Ajax postings that always append \0 # form_vars.sub!(/\0\z/, '') # performance replacement: @@ -212,10 +214,11 @@ @env["rack.request.form_vars"] = form_vars @env["rack.request.form_hash"] = parse_query(form_vars) @env["rack.input"].rewind end + @env["rack.request.form_input"] = @env["rack.input"] @env["rack.request.form_hash"] else {} end end @@ -329,20 +332,17 @@ def fullpath query_string.empty? ? path : "#{path}?#{query_string}" end def accept_encoding - @env["HTTP_ACCEPT_ENCODING"].to_s.split(/\s*,\s*/).map do |part| - encoding, parameters = part.split(/\s*;\s*/, 2) - quality = 1.0 - if parameters and /\Aq=([\d.]+)/ =~ parameters - quality = $1.to_f - end - [encoding, quality] - end + parse_http_accept_header(@env["HTTP_ACCEPT_ENCODING"]) end + def accept_language + parse_http_accept_header(@env["HTTP_ACCEPT_LANGUAGE"]) + end + def trusted_proxy?(ip) ip =~ /\A127\.0\.0\.1\Z|\A(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.|\A::1\Z|\Afd[0-9a-f]{2}:.+|\Alocalhost\Z|\Aunix\Z|\Aunix:/i end def ip @@ -351,16 +351,10 @@ return remote_addrs.first if remote_addrs.any? forwarded_ips = split_ip_addresses(@env['HTTP_X_FORWARDED_FOR']) - if client_ip = @env['HTTP_CLIENT_IP'] - # If forwarded_ips doesn't include the client_ip, it might be an - # ip spoofing attempt, so we ignore HTTP_CLIENT_IP - return client_ip if forwarded_ips.include?(client_ip) - end - return reject_trusted_ip_addresses(forwarded_ips).last || @env["REMOTE_ADDR"] end protected def split_ip_addresses(ip_addresses) @@ -370,13 +364,33 @@ def reject_trusted_ip_addresses(ip_addresses) ip_addresses.reject { |ip| trusted_proxy?(ip) } end def parse_query(qs) - Utils.parse_nested_query(qs) + Utils.parse_nested_query(qs, '&') end def parse_multipart(env) Rack::Multipart.parse_multipart(env) end + + def parse_http_accept_header(header) + header.to_s.split(/\s*,\s*/).map do |part| + attribute, parameters = part.split(/\s*;\s*/, 2) + quality = 1.0 + if parameters and /\Aq=([\d.]+)/ =~ parameters + quality = $1.to_f + end + [attribute, quality] + end + end + + private + def strip_doublequotes(s) + if s[0] == ?" && s[-1] == ?" + s[1..-2] + else + s + end + end end end