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/filter_parameters.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/headers.rb34
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb23
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb14
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb56
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb4
6 files changed, 65 insertions, 70 deletions
diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb
index 3170389b36..e70e90018c 100644
--- a/actionpack/lib/action_dispatch/http/filter_parameters.rb
+++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb
@@ -50,13 +50,13 @@ module ActionDispatch
protected
def parameter_filter
- parameter_filter_for @env.fetch("action_dispatch.parameter_filter") {
+ parameter_filter_for get_header("action_dispatch.parameter_filter") {
return NULL_PARAM_FILTER
}
end
def env_filter
- user_key = @env.fetch("action_dispatch.parameter_filter") {
+ user_key = get_header("action_dispatch.parameter_filter") {
return NULL_ENV_FILTER
}
parameter_filter_for(Array(user_key) + ENV_MATCH)
diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb
index bc5410dc38..fbdec6c132 100644
--- a/actionpack/lib/action_dispatch/http/headers.rb
+++ b/actionpack/lib/action_dispatch/http/headers.rb
@@ -30,27 +30,32 @@ module ActionDispatch
HTTP_HEADER = /\A[A-Za-z0-9-]+\z/
include Enumerable
- attr_reader :env
- def initialize(env = {}) # :nodoc:
- @env = env
+ def self.from_hash(hash)
+ new ActionDispatch::Request.new hash
+ end
+
+ def initialize(request) # :nodoc:
+ @req = request
end
# Returns the value for the given key mapped to @env.
def [](key)
- @env[env_name(key)]
+ @req.get_header env_name(key)
end
# Sets the given value for the key mapped to @env.
def []=(key, value)
- @env[env_name(key)] = value
+ @req.set_header env_name(key), value
end
def key?(key)
- @env.key? env_name(key)
+ @req.has_header? env_name(key)
end
alias :include? :key?
+ DEFAULT = Object.new # :nodoc:
+
# Returns the value for the given key mapped to @env.
#
# If the key is not found and an optional code block is not provided,
@@ -58,18 +63,22 @@ module ActionDispatch
#
# If the code block is provided, then it will be run and
# its result returned.
- def fetch(key, *args, &block)
- @env.fetch env_name(key), *args, &block
+ def fetch(key, default = DEFAULT)
+ @req.get_header(env_name(key)) do
+ return default unless default == DEFAULT
+ return yield if block_given?
+ raise NameError, key
+ end
end
def each(&block)
- @env.each(&block)
+ @req.each_header(&block)
end
# Returns a new Http::Headers instance containing the contents of
# <tt>headers_or_env</tt> and the original instance.
def merge(headers_or_env)
- headers = Http::Headers.new(env.dup)
+ headers = @req.dup.headers
headers.merge!(headers_or_env)
headers
end
@@ -79,11 +88,14 @@ module ActionDispatch
# <tt>headers_or_env</tt>.
def merge!(headers_or_env)
headers_or_env.each do |key, value|
- self[env_name(key)] = value
+ @req.set_header env_name(key), value
end
end
+ def env; @req.env.dup; end
+
private
+
# Converts a HTTP header name to an environment variable name if it is
# not contained within the headers hash.
def env_name(key)
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index ff336b7354..e01d5ecc8f 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -15,12 +15,13 @@ module ActionDispatch
# For backward compatibility, the post \format is extracted from the
# X-Post-Data-Format HTTP header if present.
def content_mime_type
- @env["action_dispatch.request.content_type"] ||= begin
- if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/
+ get_header("action_dispatch.request.content_type") do |k|
+ v = if get_header('CONTENT_TYPE') =~ /^([^,\;]*)/
Mime::Type.lookup($1.strip.downcase)
else
nil
end
+ set_header k, v
end
end
@@ -30,14 +31,15 @@ module ActionDispatch
# Returns the accepted MIME type for the request.
def accepts
- @env["action_dispatch.request.accepts"] ||= begin
- header = @env['HTTP_ACCEPT'].to_s.strip
+ get_header("action_dispatch.request.accepts") do |k|
+ header = get_header('HTTP_ACCEPT').to_s.strip
- if header.empty?
+ v = if header.empty?
[content_mime_type]
else
Mime::Type.parse(header)
end
+ set_header k, v
end
end
@@ -52,14 +54,14 @@ module ActionDispatch
end
def formats
- @env["action_dispatch.request.formats"] ||= begin
+ get_header("action_dispatch.request.formats") do |k|
params_readable = begin
parameters[:format]
rescue ActionController::BadRequest
false
end
- if params_readable
+ v = if params_readable
Array(Mime[parameters[:format]])
elsif use_accept_header && valid_accept_header
accepts
@@ -68,6 +70,7 @@ module ActionDispatch
else
[Mime::HTML]
end
+ set_header k, v
end
end
@@ -102,7 +105,7 @@ module ActionDispatch
# end
def format=(extension)
parameters[:format] = extension.to_s
- @env["action_dispatch.request.formats"] = [Mime::Type.lookup_by_extension(parameters[:format])]
+ set_header "action_dispatch.request.formats", [Mime::Type.lookup_by_extension(parameters[:format])]
end
# Sets the \formats by string extensions. This differs from #format= by allowing you
@@ -121,9 +124,9 @@ module ActionDispatch
# end
def formats=(extensions)
parameters[:format] = extensions.first.to_s
- @env["action_dispatch.request.formats"] = extensions.collect do |extension|
+ set_header "action_dispatch.request.formats", extensions.collect { |extension|
Mime::Type.lookup_by_extension(extension)
- end
+ }
end
# Receives an array of mimes and return the first user sent mime that
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index de28cd0998..1189111f20 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -67,6 +67,18 @@ module ActionDispatch
end
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)
+ end
+
def key?(key)
@env.key?(key)
end
@@ -170,7 +182,7 @@ module ActionDispatch
#
# request.headers["Content-Type"] # => "text/plain"
def headers
- @headers ||= Http::Headers.new(@env)
+ @headers ||= Http::Headers.new(self)
end
# Returns a +String+ with the last requested path including their params.
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 20926012b4..af6f0de556 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -1,6 +1,5 @@
require 'action_dispatch/journey'
require 'forwardable'
-require 'thread_safe'
require 'active_support/concern'
require 'active_support/core_ext/object/to_query'
require 'active_support/core_ext/hash/slice'
@@ -23,49 +22,27 @@ module ActionDispatch
class Dispatcher < Routing::Endpoint
def initialize(raise_on_name_error)
@raise_on_name_error = raise_on_name_error
- @controller_class_names = ThreadSafe::Cache.new
end
def dispatcher?; true; end
def serve(req)
- req.check_path_parameters!
params = req.path_parameters
-
- prepare_params!(params)
-
- controller = controller(params, @raise_on_name_error) do
+ controller = controller_reference(req) do
return [404, {'X-Cascade' => 'pass'}, []]
end
-
dispatch(controller, params[:action], req)
- end
-
- def prepare_params!(params)
- normalize_controller!(params)
- merge_default_action!(params)
- end
-
- # If this is a default_controller (i.e. a controller specified by the user)
- # we should raise an error in case it's not found, because it usually means
- # a user error. However, if the controller was retrieved through a dynamic
- # segment, as in :controller(/:action), we should simply return nil and
- # delegate the control back to Rack cascade. Besides, if this is not a default
- # controller, it means we should respect the @scope[:module] parameter.
- def controller(params, raise_on_name_error=true)
- controller_reference params.fetch(:controller) { yield }
rescue NameError => e
- raise ActionController::RoutingError, e.message, e.backtrace if raise_on_name_error
- yield
+ if @raise_on_name_error
+ raise ActionController::RoutingError, e.message, e.backtrace
+ else
+ return [404, {'X-Cascade' => 'pass'}, []]
+ end
end
protected
-
- attr_reader :controller_class_names
-
- def controller_reference(controller_param)
- const_name = controller_class_names[controller_param] ||= "#{controller_param.camelize}Controller"
- ActiveSupport::Dependencies.constantize(const_name)
+ def controller_reference(req, &block)
+ req.controller_class(&block)
end
private
@@ -73,14 +50,6 @@ module ActionDispatch
def dispatch(controller, action, req)
controller.action(action).call(req.env)
end
-
- def normalize_controller!(params)
- params[:controller] = params[:controller].underscore if params.key?(:controller)
- end
-
- def merge_default_action!(params)
- params[:action] ||= 'index'
- end
end
# A NamedRouteCollection instance is a collection of named routes, and also
@@ -760,14 +729,13 @@ module ActionDispatch
req.path_parameters = old_params.merge params
app = route.app
if app.matches?(req) && app.dispatcher?
- dispatcher = app.app
-
- dispatcher.controller(params, false) do
+ begin
+ req.controller_class
+ rescue NameError
raise ActionController::RoutingError, "A route matches #{path.inspect}, but references missing controller: #{params[:controller].camelize}Controller"
end
- dispatcher.prepare_params!(params)
- return params
+ return req.path_parameters
end
end
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 0cdc6d4e77..4dfd4f3f71 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -359,10 +359,10 @@ module ActionDispatch
# this modifies the passed request_env directly
if headers.present?
- Http::Headers.new(request_env).merge!(headers)
+ Http::Headers.from_hash(request_env).merge!(headers)
end
if env.present?
- Http::Headers.new(request_env).merge!(env)
+ Http::Headers.from_hash(request_env).merge!(env)
end
session = Rack::Test::Session.new(_mock_session)