aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb6
-rw-r--r--actionpack/lib/action_controller/test_case.rb48
-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/parameters.rb25
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb92
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb24
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb19
-rw-r--r--actionpack/lib/action_dispatch/middleware/flash.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/public_exceptions.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/abstract_store.rb12
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb34
-rw-r--r--actionpack/lib/action_dispatch/middleware/show_exceptions.rb14
-rw-r--r--actionpack/lib/action_dispatch/request/session.rb44
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb56
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb4
-rw-r--r--actionpack/test/abstract_unit.rb2
-rw-r--r--actionpack/test/dispatch/header_test.rb14
-rw-r--r--actionpack/test/dispatch/request/session_test.rb40
-rw-r--r--actionpack/test/dispatch/session/abstract_store_test.rb6
21 files changed, 263 insertions, 250 deletions
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index d21a778d8d..e5f3cb8e8d 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -136,7 +136,7 @@ module ActionController #:nodoc:
# This is the method that defines the application behavior when a request is found to be unverified.
def handle_unverified_request
request = @controller.request
- request.session = NullSessionHash.new(request.env)
+ request.session = NullSessionHash.new(request)
request.env['action_dispatch.request.flash_hash'] = nil
request.env['rack.session.options'] = { skip: true }
request.cookie_jar = NullCookieJar.build(request, {})
@@ -145,8 +145,8 @@ module ActionController #:nodoc:
protected
class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc:
- def initialize(env)
- super(nil, env)
+ def initialize(req)
+ super(nil, req)
@data = {}
@loaded = true
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index e012fa617e..d14483dc72 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -36,11 +36,15 @@ module ActionController
end
def query_string=(string)
- @env[Rack::QUERY_STRING] = string
+ set_header Rack::QUERY_STRING, string
end
def request_parameters=(params)
- @env["action_dispatch.request.request_parameters"] = params
+ set_header "action_dispatch.request.request_parameters", params
+ end
+
+ def content_type=(type)
+ set_header 'CONTENT_TYPE', type
end
def assign_parameters(routes, controller_path, action, parameters, generated_path, query_string_keys)
@@ -67,10 +71,12 @@ module ActionController
end
else
if ENCODER.should_multipart?(non_path_parameters)
- @env['CONTENT_TYPE'] = ENCODER.content_type
+ self.content_type = ENCODER.content_type
data = ENCODER.build_multipart non_path_parameters
else
- @env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded'
+ get_header('CONTENT_TYPE') do |k|
+ set_header k, 'application/x-www-form-urlencoded'
+ end
# FIXME: setting `request_parametes` is normally handled by the
# params parser middleware, and we should remove this roundtripping
@@ -92,8 +98,8 @@ module ActionController
end
end
- @env['CONTENT_LENGTH'] = data.length.to_s
- @env['rack.input'] = StringIO.new(data)
+ set_header 'CONTENT_LENGTH', data.length.to_s
+ set_header 'rack.input', StringIO.new(data)
end
@env["PATH_INFO"] ||= generated_path
@@ -450,7 +456,7 @@ module ActionController
end
if body.present?
- @request.env['RAW_POST_DATA'] = body
+ @request.set_header 'RAW_POST_DATA', body
end
if http_method.present?
@@ -472,15 +478,15 @@ module ActionController
end
self.cookies.update @request.cookies
- @request.env['HTTP_COOKIE'] = cookies.to_header
- @request.env['action_dispatch.cookies'] = nil
+ @request.set_header 'HTTP_COOKIE', cookies.to_header
+ @request.delete_header 'action_dispatch.cookies'
@request = TestRequest.new scrub_env!(@request.env), @request.session
@response = build_response @response_klass
@response.request = @request
@controller.recycle!
- @request.env['REQUEST_METHOD'] = http_method
+ @request.set_header 'REQUEST_METHOD', http_method
parameters = parameters.symbolize_keys
@@ -494,24 +500,28 @@ module ActionController
@request.flash.update(flash || {})
if xhr
- @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
- @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ @request.set_header 'HTTP_X_REQUESTED_WITH', 'XMLHttpRequest'
+ @request.get_header('HTTP_ACCEPT') do |k|
+ @request.set_header k, [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ end
end
@controller.request = @request
@controller.response = @response
- @request.env["SCRIPT_NAME"] ||= @controller.config.relative_url_root
+ @request.get_header("SCRIPT_NAME") do |k|
+ @request.set_header k, @controller.config.relative_url_root
+ end
@controller.recycle!
@controller.process(action)
- @request.env.delete 'HTTP_COOKIE'
+ @request.delete_header 'HTTP_COOKIE'
- if cookies = @request.env['action_dispatch.cookies']
+ if @request.have_cookie_jar?
unless @response.committed?
- cookies.write(@response)
- self.cookies.update(cookies.instance_variable_get(:@cookies))
+ @request.cookie_jar.write(@response)
+ self.cookies.update(@request.cookie_jar.instance_variable_get(:@cookies))
end
end
@response.prepare!
@@ -523,8 +533,8 @@ module ActionController
end
if xhr
- @request.env.delete 'HTTP_X_REQUESTED_WITH'
- @request.env.delete 'HTTP_ACCEPT'
+ @request.delete_header 'HTTP_X_REQUESTED_WITH'
+ @request.delete_header 'HTTP_ACCEPT'
end
@request.query_string = ''
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/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index 4defb7f858..277207ae6e 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -8,20 +8,23 @@ module ActionDispatch
# Returns both GET and POST \parameters in a single hash.
def parameters
- @env["action_dispatch.request.parameters"] ||= begin
- params = begin
- request_parameters.merge(query_parameters)
- rescue EOFError
- query_parameters.dup
- end
- params.merge!(path_parameters)
- end
+ params = get_header("action_dispatch.request.parameters")
+ return params if params
+
+ params = begin
+ request_parameters.merge(query_parameters)
+ rescue EOFError
+ query_parameters.dup
+ end
+ params.merge!(path_parameters)
+ set_header("action_dispatch.request.parameters", params)
+ params
end
alias :params :parameters
def path_parameters=(parameters) #:nodoc:
- @env.delete('action_dispatch.request.parameters')
- @env[PARAMETERS_KEY] = parameters
+ delete_header('action_dispatch.request.parameters')
+ set_header PARAMETERS_KEY, parameters
end
# Returns a hash with the \parameters used to form the \path of the request.
@@ -29,7 +32,7 @@ module ActionDispatch
#
# {'action' => 'my_action', 'controller' => 'my_controller'}
def path_parameters
- @env[PARAMETERS_KEY] ||= {}
+ get_header(PARAMETERS_KEY) || {}
end
private
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index de28cd0998..4748a54550 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -20,8 +20,6 @@ module ActionDispatch
include ActionDispatch::Http::FilterParameters
include ActionDispatch::Http::URL
- HTTP_X_REQUEST_ID = "HTTP_X_REQUEST_ID".freeze # :nodoc:
-
autoload :Session, 'action_dispatch/request/session'
autoload :Utils, 'action_dispatch/request/utils'
@@ -31,17 +29,19 @@ module ActionDispatch
PATH_TRANSLATED REMOTE_HOST
REMOTE_IDENT REMOTE_USER REMOTE_ADDR
SERVER_NAME SERVER_PROTOCOL
+ ORIGINAL_SCRIPT_NAME
HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
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
].freeze
ENV_METHODS.each do |env|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
def #{env.sub(/^HTTP_/n, '').downcase} # def accept_charset
- @env["#{env}".freeze] # @env["HTTP_ACCEPT_CHARSET".freeze]
+ get_header "#{env}".freeze # get_header "HTTP_ACCEPT_CHARSET".freeze
end # end
METHOD
end
@@ -67,8 +67,20 @@ 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)
+ has_header? key
end
# List of HTTP request methods from the following RFCs:
@@ -109,44 +121,40 @@ module ActionDispatch
end
def routes # :nodoc:
- env["action_dispatch.routes".freeze]
+ get_header("action_dispatch.routes".freeze)
end
def routes=(routes) # :nodoc:
- env["action_dispatch.routes".freeze] = routes
- end
-
- def original_script_name # :nodoc:
- env['ORIGINAL_SCRIPT_NAME'.freeze]
+ set_header("action_dispatch.routes".freeze, routes)
end
def engine_script_name(_routes) # :nodoc:
- env[_routes.env_key]
+ get_header(_routes.env_key)
end
def engine_script_name=(name) # :nodoc:
- env[routes.env_key] = name.dup
+ set_header(routes.env_key, name.dup)
end
def request_method=(request_method) #:nodoc:
if check_method(request_method)
- @request_method = env["REQUEST_METHOD"] = request_method
+ @request_method = set_header("REQUEST_METHOD", request_method)
end
end
def controller_instance # :nodoc:
- env['action_controller.instance'.freeze]
+ get_header('action_controller.instance'.freeze)
end
def controller_instance=(controller) # :nodoc:
- env['action_controller.instance'.freeze] = controller
+ set_header('action_controller.instance'.freeze, controller)
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
# once.
- !(env['action_dispatch.show_exceptions'.freeze] == false)
+ !(get_header('action_dispatch.show_exceptions'.freeze) == false)
end
# Returns a symbol form of the #request_method
@@ -158,7 +166,7 @@ module ActionDispatch
# even if it was overridden by middleware. See #request_method for
# more information.
def method
- @method ||= check_method(env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'])
+ @method ||= check_method(get_header("rack.methodoverride.original_method") || get_header('REQUEST_METHOD'))
end
# Returns a symbol form of the #method
@@ -170,7 +178,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.
@@ -181,7 +189,7 @@ module ActionDispatch
# # get '/foo?bar'
# request.original_fullpath # => '/foo?bar'
def original_fullpath
- @original_fullpath ||= (env["ORIGINAL_FULLPATH"] || fullpath)
+ @original_fullpath ||= (get_header("ORIGINAL_FULLPATH") || fullpath)
end
# Returns the +String+ full path including params of the last URL requested.
@@ -220,7 +228,7 @@ module ActionDispatch
# (case-insensitive), which may need to be manually added depending on the
# choice of JavaScript libraries and frameworks.
def xml_http_request?
- @env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/i
+ get_header('HTTP_X_REQUESTED_WITH') =~ /XMLHttpRequest/i
end
alias :xhr? :xml_http_request?
@@ -232,11 +240,11 @@ module ActionDispatch
# Returns the IP address of client as a +String+,
# usually set by the RemoteIp middleware.
def remote_ip
- @remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
+ @remote_ip ||= (get_header("action_dispatch.remote_ip") || ip).to_s
end
def remote_ip=(remote_ip)
- @env["action_dispatch.remote_ip".freeze] = remote_ip
+ set_header "action_dispatch.remote_ip".freeze, remote_ip
end
ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id".freeze # :nodoc:
@@ -248,43 +256,39 @@ module ActionDispatch
# 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.
def request_id
- env[ACTION_DISPATCH_REQUEST_ID]
+ get_header ACTION_DISPATCH_REQUEST_ID
end
def request_id=(id) # :nodoc:
- env[ACTION_DISPATCH_REQUEST_ID] = id
+ set_header ACTION_DISPATCH_REQUEST_ID, id
end
alias_method :uuid, :request_id
- def x_request_id # :nodoc:
- @env[HTTP_X_REQUEST_ID]
- end
-
# Returns the lowercase name of the HTTP server software.
def server_software
- (@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil
+ (get_header('SERVER_SOFTWARE') && /^([a-zA-Z]+)/ =~ get_header('SERVER_SOFTWARE')) ? $1.downcase : nil
end
# Read the request \body. This is useful for web services that need to
# work with raw requests directly.
def raw_post
- unless @env.include? 'RAW_POST_DATA'
+ unless has_header? 'RAW_POST_DATA'
raw_post_body = body
- @env['RAW_POST_DATA'] = raw_post_body.read(content_length)
+ set_header('RAW_POST_DATA', raw_post_body.read(content_length))
raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
end
- @env['RAW_POST_DATA']
+ get_header 'RAW_POST_DATA'
end
# The request body is an IO input stream. If the RAW_POST_DATA environment
# variable is already set, wrap it in a StringIO.
def body
- if raw_post = @env['RAW_POST_DATA']
+ if raw_post = get_header('RAW_POST_DATA')
raw_post.force_encoding(Encoding::BINARY)
StringIO.new(raw_post)
else
- @env['rack.input']
+ body_stream
end
end
@@ -295,7 +299,7 @@ module ActionDispatch
end
def body_stream #:nodoc:
- @env['rack.input']
+ get_header('rack.input')
end
# TODO This should be broken apart into AD::Request::Session and probably
@@ -306,15 +310,15 @@ module ActionDispatch
else
self.session = {}
end
- @env['action_dispatch.request.flash_hash'] = nil
+ set_header('action_dispatch.request.flash_hash', nil)
end
def session=(session) #:nodoc:
- Session.set @env, session
+ Session.set self, session
end
def session_options=(options)
- Session::Options.set @env, options
+ Session::Options.set self, options
end
# Override Rack's GET method to support indifferent access
@@ -336,10 +340,10 @@ module ActionDispatch
# Returns the authorization header regardless of whether it was specified directly or through one of the
# proxy alternatives.
def authorization
- @env['HTTP_AUTHORIZATION'] ||
- @env['X-HTTP_AUTHORIZATION'] ||
- @env['X_HTTP_AUTHORIZATION'] ||
- @env['REDIRECT_X_HTTP_AUTHORIZATION']
+ get_header('HTTP_AUTHORIZATION') ||
+ get_header('X-HTTP_AUTHORIZATION') ||
+ get_header('X_HTTP_AUTHORIZATION') ||
+ get_header('REDIRECT_X_HTTP_AUTHORIZATION')
end
# True if the request came from localhost, 127.0.0.1.
@@ -348,11 +352,11 @@ module ActionDispatch
end
def request_parameters=(params)
- env["action_dispatch.request.request_parameters".freeze] = params
+ set_header("action_dispatch.request.request_parameters".freeze, params)
end
def logger
- env["action_dispatch.logger".freeze]
+ get_header("action_dispatch.logger".freeze)
end
private
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index cf4f654ed6..e4c5b0bd29 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -8,48 +8,50 @@ require 'active_support/json'
module ActionDispatch
class Request < Rack::Request
def cookie_jar
- env['action_dispatch.cookies'.freeze] ||= Cookies::CookieJar.build(self, cookies)
+ get_header('action_dispatch.cookies'.freeze) do |k|
+ self.cookie_jar = Cookies::CookieJar.build(self, cookies)
+ end
end
# :stopdoc:
def have_cookie_jar?
- env.key? 'action_dispatch.cookies'.freeze
+ has_header? 'action_dispatch.cookies'.freeze
end
def cookie_jar=(jar)
- env['action_dispatch.cookies'.freeze] = jar
+ set_header 'action_dispatch.cookies'.freeze, jar
end
def key_generator
- env[Cookies::GENERATOR_KEY]
+ get_header Cookies::GENERATOR_KEY
end
def signed_cookie_salt
- env[Cookies::SIGNED_COOKIE_SALT]
+ get_header Cookies::SIGNED_COOKIE_SALT
end
def encrypted_cookie_salt
- env[Cookies::ENCRYPTED_COOKIE_SALT]
+ get_header Cookies::ENCRYPTED_COOKIE_SALT
end
def encrypted_signed_cookie_salt
- env[Cookies::ENCRYPTED_SIGNED_COOKIE_SALT]
+ get_header Cookies::ENCRYPTED_SIGNED_COOKIE_SALT
end
def secret_token
- env[Cookies::SECRET_TOKEN]
+ get_header Cookies::SECRET_TOKEN
end
def secret_key_base
- env[Cookies::SECRET_KEY_BASE]
+ get_header Cookies::SECRET_KEY_BASE
end
def cookies_serializer
- env[Cookies::COOKIES_SERIALIZER]
+ get_header Cookies::COOKIES_SERIALIZER
end
def cookies_digest
- env[Cookies::COOKIES_DIGEST]
+ get_header Cookies::COOKIES_DIGEST
end
# :startdoc:
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 226a688fe2..66bb74b9c5 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -55,18 +55,17 @@ module ActionDispatch
response
rescue Exception => exception
raise exception unless request.show_exceptions?
- render_exception(env, exception)
+ render_exception(request, exception)
end
private
- def render_exception(env, exception)
- backtrace_cleaner = env['action_dispatch.backtrace_cleaner']
+ def render_exception(request, exception)
+ backtrace_cleaner = request.get_header('action_dispatch.backtrace_cleaner')
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
- log_error(env, wrapper)
+ log_error(request, wrapper)
- if env['action_dispatch.show_detailed_exceptions']
- request = Request.new(env)
+ if request.get_header('action_dispatch.show_detailed_exceptions')
traces = wrapper.traces
trace_to_show = 'Application Trace'
@@ -108,8 +107,8 @@ module ActionDispatch
[status, {'Content-Type' => "#{format}; charset=#{Response.default_charset}", 'Content-Length' => body.bytesize.to_s}, [body]]
end
- def log_error(env, wrapper)
- logger = logger(env)
+ def log_error(request, wrapper)
+ logger = logger(request)
return unless logger
exception = wrapper.exception
@@ -125,8 +124,8 @@ module ActionDispatch
end
end
- def logger(env)
- env['action_dispatch.logger'] || stderr_logger
+ def logger(request)
+ request.logger || stderr_logger
end
def stderr_logger
diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb
index 23da169b22..6041f84834 100644
--- a/actionpack/lib/action_dispatch/middleware/flash.rb
+++ b/actionpack/lib/action_dispatch/middleware/flash.rb
@@ -6,15 +6,17 @@ module ActionDispatch
# read a notice you put there or <tt>flash["notice"] = "hello"</tt>
# to put a new one.
def flash
- @env[Flash::KEY] ||= Flash::FlashHash.from_session_value(session["flash"])
+ flash = flash_hash
+ return flash if flash
+ self.flash = Flash::FlashHash.from_session_value(session["flash"])
end
def flash=(flash)
- @env[Flash::KEY] = flash
+ set_header Flash::KEY, flash
end
def flash_hash # :nodoc:
- @env[Flash::KEY]
+ get_header Flash::KEY
end
end
@@ -274,7 +276,7 @@ module ActionDispatch
req = ActionDispatch::Request.new env
@app.call(env)
ensure
- session = Request::Session.find(env) || {}
+ session = Request::Session.find(req) || {}
flash_hash = req.flash_hash
if flash_hash && (flash_hash.present? || session.key?('flash'))
diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
index 7cde76b30e..0f27984550 100644
--- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
@@ -17,8 +17,8 @@ module ActionDispatch
end
def call(env)
- status = env["PATH_INFO"][1..-1].to_i
request = ActionDispatch::Request.new(env)
+ status = request.path_info[1..-1].to_i
content_type = request.formats.first
body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
index 84df55fd5a..b924df789f 100644
--- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
@@ -36,6 +36,11 @@ module ActionDispatch
@default_options.delete(:sidbits)
@default_options.delete(:secure_random)
end
+
+ private
+ def make_request(env)
+ ActionDispatch::Request.new env
+ end
end
module StaleSessionCheck
@@ -65,8 +70,8 @@ module ActionDispatch
end
module SessionObject # :nodoc:
- def prepare_session(env)
- Request::Session.create(self, env, @default_options)
+ def prepare_session(req)
+ Request::Session.create(self, req, @default_options)
end
def loaded_session?(session)
@@ -81,8 +86,7 @@ module ActionDispatch
private
- def set_cookie(env, session_id, cookie)
- request = ActionDispatch::Request.new(env)
+ def set_cookie(request, session_id, cookie)
request.cookie_jar[key] = cookie
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index d8f9614904..e225f356df 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -71,16 +71,16 @@ module ActionDispatch
super(app, options.merge!(:cookie_only => true))
end
- def destroy_session(env, session_id, options)
+ def destroy_session(req, session_id, options)
new_sid = generate_sid unless options[:drop]
# Reset hash and Assign the new session id
- env["action_dispatch.request.unsigned_session_cookie"] = new_sid ? { "session_id" => new_sid } : {}
+ req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid } : {})
new_sid
end
- def load_session(env)
+ def load_session(req)
stale_session_check! do
- data = unpacked_cookie_data(env)
+ data = unpacked_cookie_data(req)
data = persistent_session_id!(data)
[data["session_id"], data]
end
@@ -88,20 +88,21 @@ module ActionDispatch
private
- def extract_session_id(env)
+ def extract_session_id(req)
stale_session_check! do
- unpacked_cookie_data(env)["session_id"]
+ unpacked_cookie_data(req)["session_id"]
end
end
- def unpacked_cookie_data(env)
- env["action_dispatch.request.unsigned_session_cookie"] ||= begin
- stale_session_check! do
- if data = get_cookie(env)
+ def unpacked_cookie_data(req)
+ req.get_header("action_dispatch.request.unsigned_session_cookie") do |k|
+ v = stale_session_check! do
+ if data = get_cookie(req)
data.stringify_keys!
end
data || {}
end
+ req.set_header k, v
end
end
@@ -111,21 +112,20 @@ module ActionDispatch
data
end
- def set_session(env, sid, session_data, options)
+ def set_session(req, sid, session_data, options)
session_data["session_id"] = sid
session_data
end
- def set_cookie(env, session_id, cookie)
- cookie_jar(env)[@key] = cookie
+ def set_cookie(request, session_id, cookie)
+ cookie_jar(request)[@key] = cookie
end
- def get_cookie(env)
- cookie_jar(env)[@key]
+ def get_cookie(req)
+ cookie_jar(req)[@key]
end
- def cookie_jar(env)
- request = ActionDispatch::Request.new(env)
+ def cookie_jar(request)
request.cookie_jar.signed_or_encrypted
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 12d8dab8eb..64695f9738 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -31,7 +31,7 @@ module ActionDispatch
@app.call(env)
rescue Exception => exception
if request.show_exceptions?
- render_exception(env, exception)
+ render_exception(request, exception)
else
raise exception
end
@@ -39,14 +39,14 @@ module ActionDispatch
private
- def render_exception(env, exception)
- backtrace_cleaner = env['action_dispatch.backtrace_cleaner']
+ def render_exception(request, exception)
+ backtrace_cleaner = request.get_header 'action_dispatch.backtrace_cleaner'
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
status = wrapper.status_code
- env["action_dispatch.exception"] = wrapper.exception
- env["action_dispatch.original_path"] = env["PATH_INFO"]
- env["PATH_INFO"] = "/#{status}"
- response = @exceptions_app.call(env)
+ request.set_header "action_dispatch.exception", wrapper.exception
+ request.set_header "action_dispatch.original_path", request.path_info
+ request.path_info = "/#{status}"
+ response = @exceptions_app.call(request.env)
response[1]['X-Cascade'] == 'pass' ? pass_response(status) : response
rescue Exception => failsafe_error
$stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb
index bae3d909fa..b946ccb49f 100644
--- a/actionpack/lib/action_dispatch/request/session.rb
+++ b/actionpack/lib/action_dispatch/request/session.rb
@@ -11,31 +11,31 @@ module ActionDispatch
Unspecified = Object.new
# Creates a session hash, merging the properties of the previous session if any
- def self.create(store, env, default_options)
- session_was = find env
- session = Request::Session.new(store, env)
+ def self.create(store, req, default_options)
+ session_was = find req
+ session = Request::Session.new(store, req)
session.merge! session_was if session_was
- set(env, session)
- Options.set(env, Request::Session::Options.new(store, default_options))
+ set(req, session)
+ Options.set(req, Request::Session::Options.new(store, default_options))
session
end
- def self.find(env)
- env[ENV_SESSION_KEY]
+ def self.find(req)
+ req.get_header ENV_SESSION_KEY
end
- def self.set(env, session)
- env[ENV_SESSION_KEY] = session
+ def self.set(req, session)
+ req.set_header ENV_SESSION_KEY, session
end
class Options #:nodoc:
- def self.set(env, options)
- env[ENV_SESSION_OPTIONS_KEY] = options
+ def self.set(req, options)
+ req.set_header ENV_SESSION_OPTIONS_KEY, options
end
- def self.find(env)
- env[ENV_SESSION_OPTIONS_KEY]
+ def self.find(req)
+ req.get_header ENV_SESSION_OPTIONS_KEY
end
def initialize(by, default_options)
@@ -47,9 +47,9 @@ module ActionDispatch
@delegate[key]
end
- def id(env)
+ def id(req)
@delegate.fetch(:id) {
- @by.send(:extract_session_id, env)
+ @by.send(:extract_session_id, req)
}
end
@@ -58,26 +58,26 @@ module ActionDispatch
def values_at(*args); @delegate.values_at(*args); end
end
- def initialize(by, env)
+ def initialize(by, req)
@by = by
- @env = env
+ @req = req
@delegate = {}
@loaded = false
@exists = nil # we haven't checked yet
end
def id
- options.id(@env)
+ options.id(@req)
end
def options
- Options.find @env
+ Options.find @req
end
def destroy
clear
options = self.options || {}
- @by.send(:destroy_session, @env, options.id(@env), options)
+ @by.send(:destroy_session, @req, options.id(@req), options)
# Load the new sid to be written with the response
@loaded = false
@@ -181,7 +181,7 @@ module ActionDispatch
def exists?
return @exists unless @exists.nil?
- @exists = @by.send(:session_exists?, @env)
+ @exists = @by.send(:session_exists?, @req)
end
def loaded?
@@ -209,7 +209,7 @@ module ActionDispatch
end
def load!
- id, session = @by.load_session @env
+ id, session = @by.load_session @req
options[:id] = id
@delegate.replace(stringify_keys(session))
@loaded = true
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)
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 60e2cea8a2..fa0b6087ba 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -122,7 +122,7 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher
protected
def controller_reference(controller_param)
- controller_param
+ controller_param.params[:controller]
end
def dispatch(controller, action, env)
diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb
index e2b38c23bc..79600b654b 100644
--- a/actionpack/test/dispatch/header_test.rb
+++ b/actionpack/test/dispatch/header_test.rb
@@ -1,15 +1,19 @@
require "abstract_unit"
class HeaderTest < ActiveSupport::TestCase
+ def make_headers(hash)
+ ActionDispatch::Http::Headers.new ActionDispatch::Request.new hash
+ end
+
setup do
- @headers = ActionDispatch::Http::Headers.new(
+ @headers = make_headers(
"CONTENT_TYPE" => "text/plain",
"HTTP_REFERER" => "/some/page"
)
end
test "#new does not normalize the data" do
- headers = ActionDispatch::Http::Headers.new(
+ headers = make_headers(
"Content-Type" => "application/json",
"HTTP_REFERER" => "/some/page",
"Host" => "http://test.com")
@@ -108,7 +112,7 @@ class HeaderTest < ActiveSupport::TestCase
end
test "env variables with . are not modified" do
- headers = ActionDispatch::Http::Headers.new
+ headers = make_headers({})
headers.merge! "rack.input" => "",
"rack.request.cookie_hash" => "",
"action_dispatch.logger" => ""
@@ -119,7 +123,7 @@ class HeaderTest < ActiveSupport::TestCase
end
test "symbols are treated as strings" do
- headers = ActionDispatch::Http::Headers.new
+ headers = make_headers({})
headers.merge!(:SERVER_NAME => "example.com",
"HTTP_REFERER" => "/",
:Host => "test.com")
@@ -130,7 +134,7 @@ class HeaderTest < ActiveSupport::TestCase
test "headers directly modifies the passed environment" do
env = {"HTTP_REFERER" => "/"}
- headers = ActionDispatch::Http::Headers.new(env)
+ headers = make_headers(env)
headers['Referer'] = "http://example.com/"
headers.merge! "CONTENT_TYPE" => "text/plain"
assert_equal({"HTTP_REFERER"=>"http://example.com/",
diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb
index 8bcc07dd04..410e3194e2 100644
--- a/actionpack/test/dispatch/request/session_test.rb
+++ b/actionpack/test/dispatch/request/session_test.rb
@@ -4,40 +4,42 @@ require 'action_dispatch/middleware/session/abstract_store'
module ActionDispatch
class Request
class SessionTest < ActiveSupport::TestCase
+ attr_reader :req
+
+ def setup
+ @req = ActionDispatch::Request.new({})
+ end
+
def test_create_adds_itself_to_env
- env = {}
- s = Session.create(store, env, {})
- assert_equal s, env[Rack::RACK_SESSION]
+ s = Session.create(store, req, {})
+ assert_equal s, req.env[Rack::RACK_SESSION]
end
def test_to_hash
- env = {}
- s = Session.create(store, env, {})
+ s = Session.create(store, req, {})
s['foo'] = 'bar'
assert_equal 'bar', s['foo']
assert_equal({'foo' => 'bar'}, s.to_hash)
end
def test_create_merges_old
- env = {}
- s = Session.create(store, env, {})
+ s = Session.create(store, req, {})
s['foo'] = 'bar'
- s1 = Session.create(store, env, {})
+ s1 = Session.create(store, req, {})
assert_not_equal s, s1
assert_equal 'bar', s1['foo']
end
def test_find
- env = {}
- assert_nil Session.find(env)
+ assert_nil Session.find(req)
- s = Session.create(store, env, {})
- assert_equal s, Session.find(env)
+ s = Session.create(store, req, {})
+ assert_equal s, Session.find(req)
end
def test_destroy
- s = Session.create(store, {}, {})
+ s = Session.create(store, req, {})
s['rails'] = 'ftw'
s.destroy
@@ -46,21 +48,21 @@ module ActionDispatch
end
def test_keys
- s = Session.create(store, {}, {})
+ s = Session.create(store, req, {})
s['rails'] = 'ftw'
s['adequate'] = 'awesome'
assert_equal %w[rails adequate], s.keys
end
def test_values
- s = Session.create(store, {}, {})
+ s = Session.create(store, req, {})
s['rails'] = 'ftw'
s['adequate'] = 'awesome'
assert_equal %w[ftw awesome], s.values
end
def test_clear
- s = Session.create(store, {}, {})
+ s = Session.create(store, req, {})
s['rails'] = 'ftw'
s['adequate'] = 'awesome'
@@ -69,7 +71,7 @@ module ActionDispatch
end
def test_update
- s = Session.create(store, {}, {})
+ s = Session.create(store, req, {})
s['rails'] = 'ftw'
s.update(:rails => 'awesome')
@@ -79,7 +81,7 @@ module ActionDispatch
end
def test_delete
- s = Session.create(store, {}, {})
+ s = Session.create(store, req, {})
s['rails'] = 'ftw'
s.delete('rails')
@@ -88,7 +90,7 @@ module ActionDispatch
end
def test_fetch
- session = Session.create(store, {}, {})
+ session = Session.create(store, req, {})
session['one'] = '1'
assert_equal '1', session.fetch(:one)
diff --git a/actionpack/test/dispatch/session/abstract_store_test.rb b/actionpack/test/dispatch/session/abstract_store_test.rb
index fe1a7b4f86..1c35144e6f 100644
--- a/actionpack/test/dispatch/session/abstract_store_test.rb
+++ b/actionpack/test/dispatch/session/abstract_store_test.rb
@@ -27,7 +27,7 @@ module ActionDispatch
as.call(env)
assert @env
- assert Request::Session.find @env
+ assert Request::Session.find ActionDispatch::Request.new @env
end
def test_new_session_object_is_merged_with_old
@@ -36,11 +36,11 @@ module ActionDispatch
as.call(env)
assert @env
- session = Request::Session.find @env
+ session = Request::Session.find ActionDispatch::Request.new @env
session['foo'] = 'bar'
as.call(@env)
- session1 = Request::Session.find @env
+ session1 = Request::Session.find ActionDispatch::Request.new @env
assert_not_equal session, session1
assert_equal session.to_hash, session1.to_hash