aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb49
-rw-r--r--actionpack/lib/action_dispatch/http/filter_redirect.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb11
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb35
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb32
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb16
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb51
11 files changed, 112 insertions, 104 deletions
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index cc1cb3f0f0..08ebd2e8b2 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -8,13 +8,13 @@ module ActionDispatch
HTTP_IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze
def if_modified_since
- if since = env[HTTP_IF_MODIFIED_SINCE]
+ if since = get_header(HTTP_IF_MODIFIED_SINCE)
Time.rfc2822(since) rescue nil
end
end
def if_none_match
- env[HTTP_IF_NONE_MATCH]
+ get_header HTTP_IF_NONE_MATCH
end
def if_none_match_etags
@@ -51,41 +51,45 @@ module ActionDispatch
end
module Response
- attr_reader :cache_control, :etag
- alias :etag? :etag
+ attr_reader :cache_control
def last_modified
- if last = headers[LAST_MODIFIED]
+ if last = get_header(LAST_MODIFIED)
Time.httpdate(last)
end
end
def last_modified?
- headers.include?(LAST_MODIFIED)
+ have_header? LAST_MODIFIED
end
def last_modified=(utc_time)
- headers[LAST_MODIFIED] = utc_time.httpdate
+ set_header LAST_MODIFIED, utc_time.httpdate
end
def date
- if date_header = headers[DATE]
+ if date_header = get_header(DATE)
Time.httpdate(date_header)
end
end
def date?
- headers.include?(DATE)
+ have_header? DATE
end
def date=(utc_time)
- headers[DATE] = utc_time.httpdate
+ set_header DATE, utc_time.httpdate
end
def etag=(etag)
key = ActiveSupport::Cache.expand_cache_key(etag)
- @etag = self[ETAG] = %("#{Digest::MD5.hexdigest(key)}")
+ set_header ETAG, %("#{Digest::MD5.hexdigest(key)}")
+ end
+
+ def etag
+ get_header ETAG
end
+ alias :etag? :etag
private
@@ -96,7 +100,7 @@ module ActionDispatch
SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public must-revalidate])
def cache_control_segments
- if cache_control = self[CACHE_CONTROL]
+ if cache_control = get_header(CACHE_CONTROL)
cache_control.delete(' ').split(',')
else
[]
@@ -123,12 +127,11 @@ module ActionDispatch
def prepare_cache_control!
@cache_control = cache_control_headers
- @etag = self[ETAG]
end
def handle_conditional_get!
if etag? || last_modified? || !@cache_control.empty?
- set_conditional_cache_control!
+ set_conditional_cache_control!(@cache_control)
end
end
@@ -138,24 +141,24 @@ module ActionDispatch
PRIVATE = "private".freeze
MUST_REVALIDATE = "must-revalidate".freeze
- def set_conditional_cache_control!
+ def set_conditional_cache_control!(cache_control)
control = {}
cc_headers = cache_control_headers
if extras = cc_headers.delete(:extras)
- @cache_control[:extras] ||= []
- @cache_control[:extras] += extras
- @cache_control[:extras].uniq!
+ cache_control[:extras] ||= []
+ cache_control[:extras] += extras
+ cache_control[:extras].uniq!
end
control.merge! cc_headers
- control.merge! @cache_control
+ control.merge! cache_control
if control.empty?
- self[CACHE_CONTROL] = DEFAULT_CACHE_CONTROL
+ set_header CACHE_CONTROL, DEFAULT_CACHE_CONTROL
elsif control[:no_cache]
- self[CACHE_CONTROL] = NO_CACHE
+ set_header CACHE_CONTROL, NO_CACHE
if control[:extras]
- self[CACHE_CONTROL] += ", #{control[:extras].join(', ')}"
+ set_header(CACHE_CONTROL, get_header(CACHE_CONTROL) + ", #{control[:extras].join(', ')}")
end
else
extras = control[:extras]
@@ -167,7 +170,7 @@ module ActionDispatch
options << MUST_REVALIDATE if control[:must_revalidate]
options.concat(extras) if extras
- self[CACHE_CONTROL] = options.join(", ")
+ set_header CACHE_CONTROL, options.join(", ")
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/filter_redirect.rb b/actionpack/lib/action_dispatch/http/filter_redirect.rb
index 94c1f2b41f..f4b806b8b5 100644
--- a/actionpack/lib/action_dispatch/http/filter_redirect.rb
+++ b/actionpack/lib/action_dispatch/http/filter_redirect.rb
@@ -16,7 +16,7 @@ module ActionDispatch
def location_filters
if request
- request.env['action_dispatch.redirect_filter'] || []
+ request.get_header('action_dispatch.redirect_filter') || []
else
[]
end
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index 277207ae6e..3c9f8cd9e4 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -1,6 +1,3 @@
-require 'active_support/core_ext/hash/keys'
-require 'active_support/core_ext/hash/indifferent_access'
-
module ActionDispatch
module Http
module Parameters
@@ -34,14 +31,6 @@ module ActionDispatch
def path_parameters
get_header(PARAMETERS_KEY) || {}
end
-
- private
-
- # Convert nested Hash to HashWithIndifferentAccess.
- #
- def normalize_encode_params(params)
- ActionDispatch::Request::Utils.normalize_encode_params params
- end
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 4748a54550..45600d0a61 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -35,7 +35,8 @@ module ActionDispatch
HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM
HTTP_NEGOTIATE HTTP_PRAGMA HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR HTTP_VERSION
- HTTP_X_REQUEST_ID
+ HTTP_X_REQUEST_ID HTTP_X_FORWARDED_HOST
+ SERVER_ADDR
].freeze
ENV_METHODS.each do |env|
@@ -67,16 +68,23 @@ module ActionDispatch
end
end
+ PASS_NOT_FOUND = Class.new { # :nodoc:
+ def self.action(_); self; end
+ def self.call(_); [404, {'X-Cascade' => 'pass'}, []]; end
+ }
+
def controller_class
check_path_parameters!
params = path_parameters
- controller_param = params[:controller].underscore if params.key?(:controller)
- params[:action] ||= 'index'
-
- yield unless controller_param
- const_name = "#{controller_param.camelize}Controller"
- ActiveSupport::Dependencies.constantize(const_name)
+ if params.key?(:controller)
+ controller_param = params[:controller].underscore
+ params[:action] ||= 'index'
+ const_name = "#{controller_param.camelize}Controller"
+ ActiveSupport::Dependencies.constantize(const_name)
+ else
+ PASS_NOT_FOUND
+ end
end
def key?(key)
@@ -150,6 +158,10 @@ module ActionDispatch
set_header('action_controller.instance'.freeze, controller)
end
+ def http_auth_salt
+ get_header "action_dispatch.http_auth_salt"
+ end
+
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
@@ -323,7 +335,9 @@ module ActionDispatch
# Override Rack's GET method to support indifferent access
def GET
- @env["action_dispatch.request.query_parameters"] ||= normalize_encode_params(super || {})
+ get_header("action_dispatch.request.query_parameters") do |k|
+ set_header k, Request::Utils.normalize_encode_params(super || {})
+ end
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
raise ActionController::BadRequest.new(:query, e)
end
@@ -331,7 +345,9 @@ module ActionDispatch
# Override Rack's POST method to support indifferent access
def POST
- @env["action_dispatch.request.request_parameters"] ||= normalize_encode_params(super || {})
+ get_header("action_dispatch.request.request_parameters") do
+ self.request_parameters = Request::Utils.normalize_encode_params(super || {})
+ end
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
raise ActionController::BadRequest.new(:request, e)
end
@@ -352,6 +368,7 @@ module ActionDispatch
end
def request_parameters=(params)
+ raise if params.nil?
set_header("action_dispatch.request.request_parameters".freeze, params)
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index fd92e89231..4aee489912 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -65,7 +65,7 @@ module ActionDispatch # :nodoc:
CONTENT_TYPE = "Content-Type".freeze
SET_COOKIE = "Set-Cookie".freeze
LOCATION = "Location".freeze
- NO_CONTENT_CODES = [204, 304]
+ NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304]
cattr_accessor(:default_charset) { "utf-8" }
cattr_accessor(:default_headers)
@@ -150,6 +150,11 @@ module ActionDispatch # :nodoc:
yield self if block_given?
end
+ def have_header?(key); headers.key? key; end
+ def get_header(key); headers[key]; end
+ def set_header(key, v); headers[key] = v; end
+ def delete_header(key); headers.delete key; end
+
def await_commit
synchronize do
@cv.wait_until { @committed }
@@ -256,25 +261,9 @@ module ActionDispatch # :nodoc:
parts
end
- def set_cookie(key, value)
- ::Rack::Utils.set_cookie_header!(header, key, value)
- end
-
- def delete_cookie(key, value={})
- ::Rack::Utils.delete_cookie_header!(header, key, value)
- end
-
# The location header we'll be responding with.
- def location
- headers[LOCATION]
- end
alias_method :redirect_url, :location
- # Sets the location header we'll be responding with.
- def location=(url)
- headers[LOCATION] = url
- end
-
def close
stream.close if stream.respond_to?(:close)
end
@@ -305,7 +294,7 @@ module ActionDispatch # :nodoc:
# assert_equal 'AuthorOfNewPage', r.cookies['author']
def cookies
cookies = {}
- if header = self[SET_COOKIE]
+ if header = get_header(SET_COOKIE)
header = header.split("\n") if header.respond_to?(:to_str)
header.each do |cookie|
if pair = cookie.split(';').first
@@ -341,14 +330,14 @@ module ActionDispatch # :nodoc:
end
def assign_default_content_type_and_charset!
- return if self[CONTENT_TYPE].present?
+ return if get_header(CONTENT_TYPE).present?
@content_type ||= Mime::HTML
type = @content_type.to_s.dup
type << "; charset=#{charset}" if append_charset?
- self[CONTENT_TYPE] = type
+ set_header CONTENT_TYPE, type
end
def append_charset?
@@ -392,10 +381,9 @@ module ActionDispatch # :nodoc:
end
def rack_response(status, header)
- header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join)
-
if NO_CONTENT_CODES.include?(@status)
header.delete CONTENT_TYPE
+ header.delete 'Content-Length'
[status, header, []]
else
[status, header, RackBody.new(self)]
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 6fcf49030b..e413954066 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -229,10 +229,10 @@ module ActionDispatch
# req = Request.new 'HTTP_HOST' => 'example.com:8080'
# req.raw_host_with_port # => "example.com:8080"
def raw_host_with_port
- if forwarded = env["HTTP_X_FORWARDED_HOST"].presence
+ if forwarded = x_forwarded_host.presence
forwarded.split(/,\s?/).last
else
- env['HTTP_HOST'] || "#{env['SERVER_NAME'] || env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
+ get_header('HTTP_HOST') || "#{server_name || server_addr}:#{get_header('SERVER_PORT')}"
end
end
@@ -348,7 +348,7 @@ module ActionDispatch
end
def server_port
- @env['SERVER_PORT'].to_i
+ get_header('SERVER_PORT').to_i
end
# Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index e4c5b0bd29..6d0387cf74 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -1,6 +1,4 @@
require 'active_support/core_ext/hash/keys'
-require 'active_support/core_ext/module/attribute_accessors'
-require 'active_support/core_ext/object/blank'
require 'active_support/key_generator'
require 'active_support/message_verifier'
require 'active_support/json'
@@ -8,7 +6,7 @@ require 'active_support/json'
module ActionDispatch
class Request < Rack::Request
def cookie_jar
- get_header('action_dispatch.cookies'.freeze) do |k|
+ get_header('action_dispatch.cookies'.freeze) do
self.cookie_jar = Cookies::CookieJar.build(self, cookies)
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 402ad778fa..9cde9c9b98 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -37,7 +37,9 @@ module ActionDispatch
def call(env)
request = Request.new(env)
- request.request_parameters = parse_formatted_parameters(request, @parsers)
+ parse_formatted_parameters(request, @parsers) do |params|
+ request.request_parameters = params
+ end
@app.call(env)
end
@@ -48,7 +50,7 @@ module ActionDispatch
strategy = parsers.fetch(request.content_mime_type) { return nil }
- strategy.call(request.raw_post)
+ yield strategy.call(request.raw_post)
rescue => e # JSON or Ruby code block errors
logger(request).debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index 0430ce3b9a..90e2ae6802 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -87,7 +87,7 @@ module ActionDispatch
middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
end
- protected
+ private
def assert_index(index, where)
index = get_class index
@@ -96,8 +96,6 @@ module ActionDispatch
i
end
- private
-
def get_class(klass)
if klass.is_a?(String) || klass.is_a?(Symbol)
classcache = ActiveSupport::Dependencies::Reference
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 51bafb539f..1acfb2bfe8 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -283,12 +283,16 @@ module ActionDispatch
end
def app(blocks)
- if to.respond_to?(:call)
- Constraints.new(to, blocks, Constraints::CALL)
- elsif blocks.any?
- Constraints.new(dispatcher(defaults.key?(:controller)), blocks, Constraints::SERVE)
+ if to.is_a?(Class) && to < ActionController::Metal
+ Routing::RouteSet::StaticDispatcher.new to
else
- dispatcher(defaults.key?(:controller))
+ if to.respond_to?(:call)
+ Constraints.new(to, blocks, Constraints::CALL)
+ elsif blocks.any?
+ Constraints.new(dispatcher(defaults.key?(:controller)), blocks, Constraints::SERVE)
+ else
+ dispatcher(defaults.key?(:controller))
+ end
end
end
@@ -368,7 +372,7 @@ module ActionDispatch
end
def dispatcher(raise_on_name_error)
- @set.dispatcher raise_on_name_error
+ Routing::RouteSet::Dispatcher.new raise_on_name_error
end
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index af6f0de556..e4b8d5993e 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -27,11 +27,10 @@ module ActionDispatch
def dispatcher?; true; end
def serve(req)
- params = req.path_parameters
- controller = controller_reference(req) do
- return [404, {'X-Cascade' => 'pass'}, []]
- end
- dispatch(controller, params[:action], req)
+ params = req.path_parameters
+ controller = controller req
+ res = controller.make_response! req
+ dispatch(controller, params[:action], req, res)
rescue NameError => e
if @raise_on_name_error
raise ActionController::RoutingError, e.message, e.backtrace
@@ -40,16 +39,26 @@ module ActionDispatch
end
end
- protected
- def controller_reference(req, &block)
- req.controller_class(&block)
+ private
+
+ def controller(req)
+ req.controller_class
end
- private
+ def dispatch(controller, action, req, res)
+ controller.dispatch(action, req, res)
+ end
+ end
- def dispatch(controller, action, req)
- controller.action(action).call(req.env)
+ class StaticDispatcher < Dispatcher
+ def initialize(controller_class)
+ super(false)
+ @controller_class = controller_class
end
+
+ private
+
+ def controller(_); @controller_class; end
end
# A NamedRouteCollection instance is a collection of named routes, and also
@@ -171,9 +180,9 @@ module ActionDispatch
private
def optimized_helper(args)
- params = parameterize_args(args) { |k|
+ params = parameterize_args(args) do
raise_generation_error(args)
- }
+ end
@route.format params
end
@@ -285,7 +294,7 @@ module ActionDispatch
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
attr_accessor :disable_clear_and_finalize, :resources_path_names
- attr_accessor :default_url_options, :dispatcher_class
+ attr_accessor :default_url_options
attr_reader :env_key
alias :routes :set
@@ -328,7 +337,6 @@ module ActionDispatch
@set = Journey::Routes.new
@router = Journey::Router.new @set
@formatter = Journey::Formatter.new self
- @dispatcher_class = Routing::RouteSet::Dispatcher
end
def relative_url_root
@@ -343,6 +351,11 @@ module ActionDispatch
ActionDispatch::Request
end
+ def make_request(env)
+ request_class.new env
+ end
+ private :make_request
+
def draw(&block)
clear! unless @disable_clear_and_finalize
eval_block(block)
@@ -386,10 +399,6 @@ module ActionDispatch
@prepend.each { |blk| eval_block(blk) }
end
- def dispatcher(raise_on_name_error)
- dispatcher_class.new(raise_on_name_error)
- end
-
module MountedHelpers
extend ActiveSupport::Concern
include UrlFor
@@ -700,7 +709,7 @@ module ActionDispatch
end
def call(env)
- req = request_class.new(env)
+ req = make_request(env)
req.path_info = Journey::Router::Utils.normalize_path(req.path_info)
@router.serve(req)
end
@@ -716,7 +725,7 @@ module ActionDispatch
raise ActionController::RoutingError, e.message
end
- req = request_class.new(env)
+ req = make_request(env)
@router.recognize(req) do |route, params|
params.merge!(extras)
params.each do |key, value|