aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/http
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/http')
-rw-r--r--actionpack/lib/action_dispatch/http/filter_parameters.rb14
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb15
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb35
-rw-r--r--actionpack/lib/action_dispatch/http/parameter_filter.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb36
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb35
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb24
-rw-r--r--actionpack/lib/action_dispatch/http/upload.rb8
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb9
9 files changed, 99 insertions, 79 deletions
diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb
index e5874a39f6..eb6761d067 100644
--- a/actionpack/lib/action_dispatch/http/filter_parameters.rb
+++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb
@@ -1,4 +1,4 @@
-require "action_dispatch/http/parameter_filter"
+require_relative "parameter_filter"
module ActionDispatch
module Http
@@ -51,30 +51,30 @@ module ActionDispatch
@filtered_path ||= query_string.empty? ? path : "#{path}?#{filtered_query_string}"
end
- protected
+ private
- def parameter_filter
+ def parameter_filter # :doc:
parameter_filter_for fetch_header("action_dispatch.parameter_filter") {
return NULL_PARAM_FILTER
}
end
- def env_filter
+ def env_filter # :doc:
user_key = fetch_header("action_dispatch.parameter_filter") {
return NULL_ENV_FILTER
}
parameter_filter_for(Array(user_key) + ENV_MATCH)
end
- def parameter_filter_for(filters)
+ def parameter_filter_for(filters) # :doc:
ParameterFilter.new(filters)
end
KV_RE = "[^&;=]+"
PAIR_RE = %r{(#{KV_RE})=(#{KV_RE})}
- def filtered_query_string
+ def filtered_query_string # :doc:
query_string.gsub(PAIR_RE) do |_|
- parameter_filter.filter([[$1, $2]]).first.join("=")
+ parameter_filter.filter($1 => $2).first.join("=")
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index e5f20003a3..5994a01c78 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -6,8 +6,7 @@ module ActionDispatch
extend ActiveSupport::Concern
included do
- mattr_accessor :ignore_accept_header
- self.ignore_accept_header = false
+ mattr_accessor :ignore_accept_header, default: false
end
# The MIME type of the HTTP request, such as Mime[:xml].
@@ -135,9 +134,7 @@ module ActionDispatch
}
end
- # Receives an array of mimes and return the first user sent mime that
- # matches the order array.
- #
+ # Returns the first MIME type that matches the provided array of MIME types.
def negotiate_mime(order)
formats.each do |priority|
if priority == Mime::ALL
@@ -150,20 +147,20 @@ module ActionDispatch
order.include?(Mime::ALL) ? format : nil
end
- protected
+ private
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
- def valid_accept_header
+ def valid_accept_header # :doc:
(xhr? && (accept.present? || content_mime_type)) ||
(accept.present? && accept !~ BROWSER_LIKE_ACCEPTS)
end
- def use_accept_header
+ def use_accept_header # :doc:
!self.class.ignore_accept_header
end
- def format_from_path_extension
+ def format_from_path_extension # :doc:
path = get_header("action_dispatch.original_path") || get_header("PATH_INFO")
if match = path && path.match(/\.(\w+)\z/)
Mime[match.captures.first]
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 58eb8d0baf..5a0f661d99 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -1,7 +1,6 @@
# -*- frozen-string-literal: true -*-
require "singleton"
-require "active_support/core_ext/module/attribute_accessors"
require "active_support/core_ext/string/starts_ends_with"
module Mime
@@ -47,7 +46,7 @@ module Mime
end
end
- # Encapsulates the notion of a mime type. Can be used at render time, for example, with:
+ # Encapsulates the notion of a MIME type. Can be used at render time, for example, with:
#
# class PostsController < ActionController::Base
# def show
@@ -65,7 +64,7 @@ module Mime
@register_callbacks = []
- # A simple helper class used in parsing the accept header
+ # A simple helper class used in parsing the accept header.
class AcceptItem #:nodoc:
attr_accessor :index, :name, :q
alias :to_s :name
@@ -73,7 +72,7 @@ module Mime
def initialize(index, name, q = nil)
@index = index
@name = name
- q ||= 0.0 if @name == "*/*".freeze # default wildcard match to end of list
+ q ||= 0.0 if @name == "*/*".freeze # Default wildcard match to end of list.
@q = ((q || 1.0).to_f * 100).to_i
end
@@ -91,22 +90,22 @@ module Mime
text_xml_idx = find_item_by_name list, "text/xml"
app_xml_idx = find_item_by_name list, Mime[:xml].to_s
- # Take care of the broken text/xml entry by renaming or deleting it
+ # Take care of the broken text/xml entry by renaming or deleting it.
if text_xml_idx && app_xml_idx
app_xml = list[app_xml_idx]
text_xml = list[text_xml_idx]
- app_xml.q = [text_xml.q, app_xml.q].max # set the q value to the max of the two
- if app_xml_idx > text_xml_idx # make sure app_xml is ahead of text_xml in the list
+ app_xml.q = [text_xml.q, app_xml.q].max # Set the q value to the max of the two.
+ if app_xml_idx > text_xml_idx # Make sure app_xml is ahead of text_xml in the list.
list[app_xml_idx], list[text_xml_idx] = text_xml, app_xml
app_xml_idx, text_xml_idx = text_xml_idx, app_xml_idx
end
- list.delete_at(text_xml_idx) # delete text_xml from the list
+ list.delete_at(text_xml_idx) # Delete text_xml from the list.
elsif text_xml_idx
list[text_xml_idx].name = Mime[:xml].to_s
end
- # Look for more specific XML-based types and sort them ahead of app/xml
+ # Look for more specific XML-based types and sort them ahead of app/xml.
if app_xml_idx
app_xml = list[app_xml_idx]
idx = app_xml_idx
@@ -148,7 +147,7 @@ module Mime
EXTENSION_LOOKUP[extension.to_s]
end
- # Registers an alias that's not used on mime type lookup, but can be referenced directly. Especially useful for
+ # Registers an alias that's not used on MIME type lookup, but can be referenced directly. Especially useful for
# rendering different HTML versions depending on the user agent, like an iPhone.
def register_alias(string, symbol, extension_synonyms = [])
register(string, symbol, [], extension_synonyms, true)
@@ -278,6 +277,8 @@ module Mime
def all?; false; end
+ # TODO Change this to private once we've dropped Ruby 2.2 support.
+ # Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :string, :synonyms
@@ -295,8 +296,8 @@ module Mime
end
end
- def respond_to_missing?(method, include_private = false) #:nodoc:
- method.to_s.ends_with? "?"
+ def respond_to_missing?(method, include_private = false)
+ (method.to_s.ends_with? "?") || super
end
end
@@ -325,15 +326,15 @@ module Mime
def ref; end
- def respond_to_missing?(method, include_private = false)
- method.to_s.ends_with? "?"
- end
-
private
+ def respond_to_missing?(method, _)
+ method.to_s.ends_with? "?"
+ end
+
def method_missing(method, *args)
false if method.to_s.ends_with? "?"
end
end
end
-require "action_dispatch/http/mime_types"
+require_relative "mime_types"
diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb
index 889f55a52a..1d2b4b902b 100644
--- a/actionpack/lib/action_dispatch/http/parameter_filter.rb
+++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb
@@ -54,7 +54,7 @@ module ActionDispatch
end
def call(original_params, parents = [])
- filtered_params = {}
+ filtered_params = original_params.class.new
original_params.each do |key, value|
parents.push(key) if deep_regexps
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index ddd15b748b..7c585dbe68 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -13,7 +13,7 @@ module ActionDispatch
}
# Raised when raw data from the request cannot be parsed by the parser
- # defined for request's content mime type.
+ # defined for request's content MIME type.
class ParseError < StandardError
def initialize
super($!.message)
@@ -22,6 +22,7 @@ module ActionDispatch
included do
class << self
+ # Returns the parameter parsers.
attr_reader :parameter_parsers
end
@@ -29,7 +30,16 @@ module ActionDispatch
end
module ClassMethods
- def parameter_parsers=(parsers) # :nodoc:
+ # Configure the parameter parser for a given MIME type.
+ #
+ # It accepts a hash where the key is the symbol of the MIME type
+ # and the value is a proc.
+ #
+ # original_parsers = ActionDispatch::Request.parameter_parsers
+ # xml_parser = -> (raw_post) { Hash.from_xml(raw_post) || {} }
+ # new_parsers = original_parsers.merge(xml: xml_parser)
+ # ActionDispatch::Request.parameter_parsers = new_parsers
+ def parameter_parsers=(parsers)
@parameter_parsers = parsers.transform_keys { |key| key.respond_to?(:symbol) ? key.symbol : key }
end
end
@@ -45,7 +55,7 @@ module ActionDispatch
query_parameters.dup
end
params.merge!(path_parameters)
- params = set_custom_encoding(params)
+ params = set_binary_encoding(params)
set_header("action_dispatch.request.parameters", params)
params
end
@@ -73,19 +83,20 @@ module ActionDispatch
private
- def set_custom_encoding(params)
+ def set_binary_encoding(params)
action = params[:action]
- params.each do |k, v|
- if v.is_a?(String) && v.encoding != encoding_template(action, k)
- params[k] = v.force_encoding(encoding_template(action, k))
+ if binary_params_for?(action)
+ ActionDispatch::Request::Utils.each_param_value(params) do |param|
+ param.force_encoding ::Encoding::ASCII_8BIT
end
end
-
params
end
- def encoding_template(action, param)
- controller_class.encoding_for_param(action, param)
+ def binary_params_for?(action)
+ controller_class.binary_params_for?(action)
+ rescue NameError
+ false
end
def parse_formatted_parameters(parsers)
@@ -95,7 +106,7 @@ module ActionDispatch
begin
strategy.call(raw_post)
- rescue # JSON or Ruby code block errors
+ rescue # JSON or Ruby code block errors.
my_logger = logger || ActiveSupport::Logger.new($stderr)
my_logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{raw_post}"
@@ -110,6 +121,7 @@ module ActionDispatch
end
module ParamsParser
- ParseError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("ActionDispatch::ParamsParser::ParseError", "ActionDispatch::Http::Parameters::ParseError")
+ include ActiveSupport::Deprecation::DeprecatedConstantAccessor
+ deprecate_constant "ParseError", "ActionDispatch::Http::Parameters::ParseError"
end
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 9986d6e1e9..fd986d88e7 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -1,15 +1,17 @@
+# frozen_string_literal: true
+
require "stringio"
require "active_support/inflector"
-require "action_dispatch/http/headers"
+require_relative "headers"
require "action_controller/metal/exceptions"
require "rack/request"
-require "action_dispatch/http/cache"
-require "action_dispatch/http/mime_negotiation"
-require "action_dispatch/http/parameters"
-require "action_dispatch/http/filter_parameters"
-require "action_dispatch/http/upload"
-require "action_dispatch/http/url"
+require_relative "cache"
+require_relative "mime_negotiation"
+require_relative "parameters"
+require_relative "filter_parameters"
+require_relative "upload"
+require_relative "url"
require "active_support/core_ext/array/conversions"
module ActionDispatch
@@ -69,7 +71,7 @@ module ActionDispatch
PASS_NOT_FOUND = Class.new { # :nodoc:
def self.action(_); self; end
def self.call(_); [404, { "X-Cascade" => "pass" }, []]; end
- def self.encoding_for_param(action, param); ::Encoding::UTF_8; end
+ def self.binary_params_for?(action); false; end
}
def controller_class
@@ -85,6 +87,9 @@ module ActionDispatch
end
end
+ # Returns true if the request has a header matching the given key parameter.
+ #
+ # request.key? :ip_spoofing_check # => true
def key?(key)
has_header? key
end
@@ -111,7 +116,7 @@ module ActionDispatch
HTTP_METHOD_LOOKUP = {}
- # Populate the HTTP method lookup cache
+ # Populate the HTTP method lookup cache.
HTTP_METHODS.each { |method|
HTTP_METHOD_LOOKUP[method] = method.underscore.to_sym
}
@@ -162,12 +167,12 @@ module ActionDispatch
def show_exceptions? # :nodoc:
# We're treating `nil` as "unset", and we want the default setting to be
- # `true`. This logic should be extracted to `env_config` and calculated
+ # `true`. This logic should be extracted to `env_config` and calculated
# once.
!(get_header("action_dispatch.show_exceptions".freeze) == false)
end
- # Returns a symbol form of the #request_method
+ # Returns a symbol form of the #request_method.
def request_method_symbol
HTTP_METHOD_LOOKUP[request_method]
end
@@ -179,7 +184,7 @@ module ActionDispatch
@method ||= check_method(get_header("rack.methodoverride.original_method") || get_header("REQUEST_METHOD"))
end
- # Returns a symbol form of the #method
+ # Returns a symbol form of the #method.
def method_symbol
HTTP_METHOD_LOOKUP[method]
end
@@ -264,7 +269,7 @@ module ActionDispatch
# (which sets the action_dispatch.request_id environment variable).
#
# This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
- # This relies on the rack variable set by the ActionDispatch::RequestId middleware.
+ # This relies on the Rack variable set by the ActionDispatch::RequestId middleware.
def request_id
get_header ACTION_DISPATCH_REQUEST_ID
end
@@ -336,7 +341,7 @@ module ActionDispatch
Session::Options.set self, options
end
- # Override Rack's GET method to support indifferent access
+ # Override Rack's GET method to support indifferent access.
def GET
fetch_header("action_dispatch.request.query_parameters") do |k|
rack_query_params = super || {}
@@ -349,7 +354,7 @@ module ActionDispatch
end
alias :query_parameters :GET
- # Override Rack's POST method to support indifferent access
+ # Override Rack's POST method to support indifferent access.
def POST
fetch_header("action_dispatch.request.request_parameters") do
pr = parse_formatted_parameters(params_parsers) do |params|
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 357ca56036..29d8ba3d04 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -1,6 +1,6 @@
require "active_support/core_ext/module/attribute_accessors"
-require "action_dispatch/http/filter_redirect"
-require "action_dispatch/http/cache"
+require_relative "filter_redirect"
+require_relative "cache"
require "monitor"
module ActionDispatch # :nodoc:
@@ -81,11 +81,11 @@ module ActionDispatch # :nodoc:
LOCATION = "Location".freeze
NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304]
- cattr_accessor(:default_charset) { "utf-8" }
- cattr_accessor(:default_headers)
+ cattr_accessor :default_charset, default: "utf-8"
+ cattr_accessor :default_headers
include Rack::Response::Helpers
- # Aliasing these off because AD::Http::Cache::Response defines them
+ # Aliasing these off because AD::Http::Cache::Response defines them.
alias :_cache_control :cache_control
alias :_cache_control= :cache_control=
@@ -103,7 +103,7 @@ module ActionDispatch # :nodoc:
def body
@str_body ||= begin
- buf = ""
+ buf = "".dup
each { |chunk| buf << chunk }
buf
end
@@ -142,7 +142,7 @@ module ActionDispatch # :nodoc:
private
def each_chunk(&block)
- @buf.each(&block) # extract into own method
+ @buf.each(&block)
end
end
@@ -227,7 +227,9 @@ module ActionDispatch # :nodoc:
return unless content_type
new_header_info = parse_content_type(content_type.to_s)
prev_header_info = parsed_content_type_header
- set_content_type new_header_info.mime_type, new_header_info.charset || prev_header_info.charset || self.class.default_charset
+ charset = new_header_info.charset || prev_header_info.charset
+ charset ||= self.class.default_charset unless prev_header_info.mime_type
+ set_content_type new_header_info.mime_type, charset
end
# Sets the HTTP response's content MIME type. For example, in the controller
@@ -250,7 +252,7 @@ module ActionDispatch # :nodoc:
end
# Sets the HTTP character set. In case of +nil+ parameter
- # it sets the charset to utf-8.
+ # it sets the charset to +default_charset+.
#
# response.charset = 'utf-16' # => 'utf-16'
# response.charset = nil # => 'utf-8'
@@ -408,7 +410,7 @@ module ActionDispatch # :nodoc:
def parse_content_type(content_type)
if content_type
type, charset = content_type.split(/;\s*charset=/)
- type = nil if type.empty?
+ type = nil if type && type.empty?
ContentTypeHeader.new(type, charset)
else
NullContentTypeHeader
@@ -423,7 +425,7 @@ module ActionDispatch # :nodoc:
def set_content_type(content_type, charset)
type = (content_type || "").dup
- type << "; charset=#{charset}" if charset
+ type << "; charset=#{charset.to_s.downcase}" if charset
set_header CONTENT_TYPE, type
end
diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb
index 61ba052e45..225272d66e 100644
--- a/actionpack/lib/action_dispatch/http/upload.rb
+++ b/actionpack/lib/action_dispatch/http/upload.rb
@@ -27,14 +27,18 @@ module ActionDispatch
@tempfile = hash[:tempfile]
raise(ArgumentError, ":tempfile is required") unless @tempfile
- @original_filename = hash[:filename]
- if @original_filename
+ if hash[:filename]
+ @original_filename = hash[:filename].dup
+
begin
@original_filename.encode!(Encoding::UTF_8)
rescue EncodingError
@original_filename.force_encoding(Encoding::UTF_8)
end
+ else
+ @original_filename = nil
end
+
@content_type = hash[:type]
@headers = hash[:head]
end
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index a6937d54ff..f0344fd927 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/core_ext/module/attribute_accessors"
module ActionDispatch
@@ -7,8 +9,7 @@ module ActionDispatch
HOST_REGEXP = /(^[^:]+:\/\/)?(\[[^\]]+\]|[^:]+)(?::(\d+$))?/
PROTOCOL_REGEXP = /^([^:]+)(:)?(\/\/)?$/
- mattr_accessor :tld_length
- self.tld_length = 1
+ mattr_accessor :tld_length, default: 1
class << self
# Returns the domain part of a host given the domain level.
@@ -101,10 +102,8 @@ module ActionDispatch
end
def add_trailing_slash(path)
- # includes querysting
if path.include?("?")
path.sub!(/\?/, '/\&')
- # does not have a .format
elsif !path.include?(".")
path.sub!(/[^\/]\z|\A\z/, '\&/')
end
@@ -158,7 +157,7 @@ module ActionDispatch
subdomain = options.fetch :subdomain, true
domain = options[:domain]
- host = ""
+ host = "".dup
if subdomain == true
return _host if domain.nil?