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/mime_negotiation.rb9
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb27
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb6
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb34
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb7
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb3
-rw-r--r--actionpack/lib/action_dispatch/journey/path/pattern.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb13
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb105
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb22
-rw-r--r--actionpack/lib/action_dispatch/middleware/reloader.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/remote_ip.rb22
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/abstract_store.rb20
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb40
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb15
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (renamed from actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb)0
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_source.text.erb8
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb2
-rw-r--r--actionpack/lib/action_dispatch/request/utils.rb15
-rw-r--r--actionpack/lib/action_dispatch/routing.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb25
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb60
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb24
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb5
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/response.rb29
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb10
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb11
-rw-r--r--actionpack/lib/action_dispatch/testing/test_process.rb2
33 files changed, 351 insertions, 186 deletions
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index 7acf91902d..e9b25339dc 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -69,6 +69,8 @@ module ActionDispatch
Array(Mime[parameters[:format]])
elsif use_accept_header && valid_accept_header
accepts
+ elsif extension_format = format_from_path_extension
+ [extension_format]
elsif xhr?
[Mime[:js]]
else
@@ -160,6 +162,13 @@ module ActionDispatch
def use_accept_header
!self.class.ignore_accept_header
end
+
+ def format_from_path_extension
+ path = @env['action_dispatch.original_path'] || @env['PATH_INFO']
+ if match = path && path.match(/\.(\w+)\z/)
+ Mime[match.captures.first]
+ end
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 95094c25c0..b8d395854c 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -1,7 +1,6 @@
require 'singleton'
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/string/starts_ends_with'
-require 'active_support/deprecation'
module Mime
class Mimes
@@ -48,15 +47,10 @@ module Mime
def const_missing(sym)
ext = sym.downcase
if Mime[ext]
- ActiveSupport::Deprecation.warn <<-eow
-Accessing mime types via constants is deprecated. Please change:
-
- `Mime::#{sym}`
-
-to:
-
- `Mime[:#{ext}]`
- eow
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Accessing mime types via constants is deprecated.
+ Please change `Mime::#{sym}` to `Mime[:#{ext}]`.
+ MSG
Mime[ext]
else
super
@@ -66,15 +60,10 @@ to:
def const_defined?(sym, inherit = true)
ext = sym.downcase
if Mime[ext]
- ActiveSupport::Deprecation.warn <<-eow
-Accessing mime types via constants is deprecated. Please change:
-
- `Mime.const_defined?(#{sym})`
-
-to:
-
- `Mime[:#{ext}]`
- eow
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Accessing mime types via constants is deprecated.
+ Please change `Mime.const_defined?(#{sym})` to `Mime[:#{ext}]`.
+ MSG
true
else
super
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index 248ecfd676..cca7376ffa 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -43,7 +43,7 @@ module ActionDispatch
#
# {'action' => 'my_action', 'controller' => 'my_controller'}
def path_parameters
- get_header(PARAMETERS_KEY) || {}
+ get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
end
private
@@ -55,11 +55,11 @@ module ActionDispatch
begin
strategy.call(raw_post)
- rescue => e # 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}"
- raise ParamsParser::ParseError.new(e.message, e)
+ raise ParamsParser::ParseError
end
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index bf20a33d36..29cf821090 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -36,8 +36,8 @@ module ActionDispatch
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 HTTP_X_FORWARDED_HOST
+ HTTP_X_FORWARDED_FOR HTTP_ORIGIN HTTP_VERSION
+ HTTP_X_CSRF_TOKEN HTTP_X_REQUEST_ID HTTP_X_FORWARDED_HOST
SERVER_ADDR
].freeze
@@ -49,6 +49,10 @@ module ActionDispatch
METHOD
end
+ def self.empty
+ new({})
+ end
+
def initialize(env)
super
@method = nil
@@ -59,13 +63,16 @@ module ActionDispatch
@ip = nil
end
+ def commit_cookie_jar! # :nodoc:
+ end
+
def check_path_parameters!
# If any of the path parameters has an invalid encoding then
# raise since it's likely to trigger errors further on.
path_parameters.each do |key, value|
next unless value.respond_to?(:valid_encoding?)
unless value.valid_encoding?
- raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
+ raise ActionController::BadRequest, "Invalid parameter encoding: #{key} => #{value.inspect}"
end
end
end
@@ -306,10 +313,16 @@ module ActionDispatch
end
end
- # Returns true if the request's content MIME type is
- # +application/x-www-form-urlencoded+ or +multipart/form-data+.
+ # Determine whether the request body contains form-data by checking
+ # the request Content-Type for one of the media-types:
+ # "application/x-www-form-urlencoded" or "multipart/form-data". The
+ # list of form-data media types can be modified through the
+ # +FORM_DATA_MEDIA_TYPES+ array.
+ #
+ # A request body is not assumed to contain form-data when no
+ # Content-Type header is provided and the request_method is POST.
def form_data?
- FORM_DATA_MEDIA_TYPES.include?(content_mime_type.to_s)
+ FORM_DATA_MEDIA_TYPES.include?(media_type)
end
def body_stream #:nodoc:
@@ -338,10 +351,13 @@ module ActionDispatch
# Override Rack's GET method to support indifferent access
def GET
fetch_header("action_dispatch.request.query_parameters") do |k|
- set_header k, Request::Utils.normalize_encode_params(super || {})
+ rack_query_params = super || {}
+ # Check for non UTF-8 parameter values, which would cause errors later
+ Request::Utils.check_param_encoding(rack_query_params)
+ set_header k, Request::Utils.normalize_encode_params(rack_query_params)
end
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
- raise ActionController::BadRequest.new(:query, e)
+ raise ActionController::BadRequest.new("Invalid query parameters: #{e.message}")
end
alias :query_parameters :GET
@@ -357,7 +373,7 @@ module ActionDispatch
self.request_parameters = Request::Utils.normalize_encode_params(super || {})
raise
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
- raise ActionController::BadRequest.new(:request, e)
+ raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
end
alias :request_parameters :POST
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index c54efb6541..9b11111a67 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -149,7 +149,6 @@ module ActionDispatch # :nodoc:
self.body, self.status = body, status
- @blank = false
@cv = new_cond
@committed = false
@sending = false
@@ -287,12 +286,8 @@ module ActionDispatch # :nodoc:
@stream.write string
end
- EMPTY = " "
-
# Allows you to manually set or override the response body.
def body=(body)
- @blank = true if body == EMPTY
-
if body.respond_to?(:to_path)
@stream = body
else
@@ -417,6 +412,8 @@ module ActionDispatch # :nodoc:
end
def before_sending
+ headers.freeze
+ request.commit_cookie_jar! unless committed?
end
def build_buffer(response, body)
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 92b10b6d3b..37f41ae988 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -81,7 +81,8 @@ module ActionDispatch
def add_params(path, params)
params = { params: params } unless params.is_a?(Hash)
params.reject! { |_,v| v.to_param.nil? }
- path << "?#{params.to_query}" unless params.empty?
+ query = params.to_query
+ path << "?#{query}" unless query.empty?
end
def add_anchor(path, anchor)
diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb
index 5ee8810066..018b89a2b7 100644
--- a/actionpack/lib/action_dispatch/journey/path/pattern.rb
+++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb
@@ -124,7 +124,7 @@ module ActionDispatch
end
def captures
- (length - 1).times.map { |i| self[i + 1] }
+ Array.new(length - 1) { |i| self[i + 1] }
end
def [](x)
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 2889acaeb8..3477aa8b29 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -12,6 +12,12 @@ module ActionDispatch
end
# :stopdoc:
+ prepend Module.new {
+ def commit_cookie_jar!
+ cookie_jar.commit!
+ end
+ }
+
def have_cookie_jar?
has_header? 'action_dispatch.cookies'.freeze
end
@@ -77,6 +83,12 @@ module ActionDispatch
# # It can be read using the signed method `cookies.signed[:name]`
# cookies.signed[:user_id] = current_user.id
#
+ # # Sets an encrypted cookie value before sending it to the client which
+ # # prevent users from reading and tampering with its value.
+ # # The cookie is signed by your app's `secrets.secret_key_base` value.
+ # # It can be read using the encrypted method `cookies.encrypted[:name]`
+ # cookies.encrypted[:discount] = 45
+ #
# # Sets a "permanent" cookie (which expires in 20 years from now).
# cookies.permanent[:login] = "XJ-122"
#
@@ -89,6 +101,7 @@ module ActionDispatch
# cookies.size # => 2
# JSON.parse(cookies[:lat_lon]) # => [47.68, -122.37]
# cookies.signed[:login] # => "XJ-122"
+ # cookies.encrypted[:discount] # => 45
#
# Example for deleting:
#
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 66bb74b9c5..b55c937e0c 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -38,9 +38,10 @@ module ActionDispatch
end
end
- def initialize(app, routes_app = nil)
- @app = app
- @routes_app = routes_app
+ def initialize(app, routes_app = nil, response_format = :default)
+ @app = app
+ @routes_app = routes_app
+ @response_format = response_format
end
def call(env)
@@ -66,41 +67,79 @@ module ActionDispatch
log_error(request, wrapper)
if request.get_header('action_dispatch.show_detailed_exceptions')
- traces = wrapper.traces
-
- trace_to_show = 'Application Trace'
- if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
- trace_to_show = 'Full Trace'
+ case @response_format
+ when :api
+ render_for_api_application(request, wrapper)
+ when :default
+ render_for_default_application(request, wrapper)
end
+ else
+ raise exception
+ end
+ end
- if source_to_show = traces[trace_to_show].first
- source_to_show_id = source_to_show[:id]
- end
+ def render_for_default_application(request, wrapper)
+ template = create_template(request, wrapper)
+ file = "rescues/#{wrapper.rescue_template}"
- template = DebugView.new([RESCUES_TEMPLATE_PATH],
- request: request,
- exception: wrapper.exception,
- traces: traces,
- show_source_idx: source_to_show_id,
- trace_to_show: trace_to_show,
- routes_inspector: routes_inspector(exception),
- source_extracts: wrapper.source_extracts,
- line_number: wrapper.line_number,
- file: wrapper.file
- )
- file = "rescues/#{wrapper.rescue_template}"
-
- if request.xhr?
- body = template.render(template: file, layout: false, formats: [:text])
- format = "text/plain"
- else
- body = template.render(template: file, layout: 'rescues/layout')
- format = "text/html"
- end
- render(wrapper.status_code, body, format)
+ if request.xhr?
+ body = template.render(template: file, layout: false, formats: [:text])
+ format = "text/plain"
else
- raise exception
+ body = template.render(template: file, layout: 'rescues/layout')
+ format = "text/html"
end
+ render(wrapper.status_code, body, format)
+ end
+
+ def render_for_api_application(request, wrapper)
+ body = {
+ status: wrapper.status_code,
+ error: Rack::Utils::HTTP_STATUS_CODES.fetch(
+ wrapper.status_code,
+ Rack::Utils::HTTP_STATUS_CODES[500]
+ ),
+ exception: wrapper.exception.inspect,
+ traces: wrapper.traces
+ }
+
+ content_type = request.formats.first
+ to_format = "to_#{content_type.to_sym}"
+
+ if content_type && body.respond_to?(to_format)
+ formatted_body = body.public_send(to_format)
+ format = content_type
+ else
+ formatted_body = body.to_json
+ format = Mime[:json]
+ end
+
+ render(wrapper.status_code, formatted_body, format)
+ end
+
+ def create_template(request, wrapper)
+ traces = wrapper.traces
+
+ trace_to_show = 'Application Trace'
+ if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
+ trace_to_show = 'Full Trace'
+ end
+
+ if source_to_show = traces[trace_to_show].first
+ source_to_show_id = source_to_show[:id]
+ end
+
+ DebugView.new([RESCUES_TEMPLATE_PATH],
+ request: request,
+ exception: wrapper.exception,
+ traces: traces,
+ show_source_idx: source_to_show_id,
+ trace_to_show: trace_to_show,
+ routes_inspector: routes_inspector(wrapper.exception),
+ source_extracts: wrapper.source_extracts,
+ line_number: wrapper.line_number,
+ file: wrapper.file
+ )
end
def render(status, body, format)
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 5fd984cd07..3b61824cc9 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -37,7 +37,7 @@ module ActionDispatch
@backtrace_cleaner = backtrace_cleaner
@exception = original_exception(exception)
- expand_backtrace if exception.is_a?(SyntaxError) || exception.try(:original_exception).try(:is_a?, SyntaxError)
+ expand_backtrace if exception.is_a?(SyntaxError) || exception.cause.is_a?(SyntaxError)
end
def rescue_template
@@ -106,17 +106,13 @@ module ActionDispatch
end
def original_exception(exception)
- if registered_original_exception?(exception)
- exception.original_exception
+ if @@rescue_responses.has_key?(exception.cause.class.name)
+ exception.cause
else
exception
end
end
- def registered_original_exception?(exception)
- exception.respond_to?(:original_exception) && @@rescue_responses.has_key?(exception.original_exception.class.name)
- end
-
def clean_backtrace(*args)
if backtrace_cleaner
backtrace_cleaner.clean(backtrace, *args)
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 18af0a583a..c2a4f46e67 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -10,11 +10,25 @@ module ActionDispatch
# Raised when raw data from the request cannot be parsed by the parser
# defined for request's content mime type.
class ParseError < StandardError
- attr_reader :original_exception
- def initialize(message, original_exception)
- super(message)
- @original_exception = original_exception
+ def initialize(message = nil, original_exception = nil)
+ if message
+ ActiveSupport::Deprecation.warn("Passing #message is deprecated and has no effect. " \
+ "#{self.class} will automatically capture the message " \
+ "of the original exception.", caller)
+ end
+
+ if original_exception
+ ActiveSupport::Deprecation.warn("Passing #original_exception is deprecated and has no effect. " \
+ "Exceptions will automatically capture the original exception.", caller)
+ end
+
+ super($!.message)
+ end
+
+ def original_exception
+ ActiveSupport::Deprecation.warn("#original_exception is deprecated. Use #cause instead.", caller)
+ cause
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb
index 6c7fba00cb..af9a29eb07 100644
--- a/actionpack/lib/action_dispatch/middleware/reloader.rb
+++ b/actionpack/lib/action_dispatch/middleware/reloader.rb
@@ -1,5 +1,3 @@
-require 'active_support/deprecation/reporting'
-
module ActionDispatch
# ActionDispatch::Reloader provides prepare and cleanup callbacks,
# intended to assist with code reloading during development.
diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
index aee2334da9..31b75498b6 100644
--- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb
+++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
@@ -43,7 +43,7 @@ module ActionDispatch
# Create a new +RemoteIp+ middleware instance.
#
- # The +check_ip_spoofing+ option is on by default. When on, an exception
+ # The +ip_spoofing_check+ option is on by default. When on, an exception
# is raised if it looks like the client is trying to lie about its own IP
# address. It makes sense to turn off this check on sites aimed at non-IP
# clients (like WAP devices), or behind proxies that set headers in an
@@ -57,9 +57,9 @@ module ActionDispatch
# with your proxy servers after it. If your proxies aren't removed, pass
# them in via the +custom_proxies+ parameter. That way, the middleware will
# ignore those IP addresses, and return the one that you want.
- def initialize(app, check_ip_spoofing = true, custom_proxies = nil)
+ def initialize(app, ip_spoofing_check = true, custom_proxies = nil)
@app = app
- @check_ip = check_ip_spoofing
+ @check_ip = ip_spoofing_check
@proxies = if custom_proxies.blank?
TRUSTED_PROXIES
elsif custom_proxies.respond_to?(:any?)
@@ -116,10 +116,18 @@ module ActionDispatch
forwarded_ips = ips_from(@req.x_forwarded_for).reverse
# +Client-Ip+ and +X-Forwarded-For+ should not, generally, both be set.
- # If they are both set, it means that this request passed through two
- # proxies with incompatible IP header conventions, and there is no way
- # for us to determine which header is the right one after the fact.
- # Since we have no idea, we give up and explode.
+ # If they are both set, it means that either:
+ #
+ # 1) This request passed through two proxies with incompatible IP header
+ # conventions.
+ # 2) The client passed one of +Client-Ip+ or +X-Forwarded-For+
+ # (whichever the proxy servers weren't using) themselves.
+ #
+ # Either way, there is no way for us to determine which header is the
+ # right one after the fact. Since we have no idea, if we are concerned
+ # about IP spoofing we need to give up and explode. (If you're not
+ # concerned about IP spoofing you can turn the +ip_spoofing_check+
+ # option off.)
should_check_ip = @check_ip && client_ips.last && forwarded_ips.last
if should_check_ip && !forwarded_ips.include?(client_ips.last)
# We don't know which came from the proxy, and which from the user
diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
index 9e50fea3fc..5fb5953811 100644
--- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
@@ -7,14 +7,22 @@ require 'action_dispatch/request/session'
module ActionDispatch
module Session
class SessionRestoreError < StandardError #:nodoc:
- attr_reader :original_exception
- def initialize(const_error)
- @original_exception = const_error
+ def initialize(const_error = nil)
+ if const_error
+ ActiveSupport::Deprecation.warn("Passing #original_exception is deprecated and has no effect. " \
+ "Exceptions will automatically capture the original exception.", caller)
+ end
super("Session contains objects whose class definition isn't available.\n" +
"Remember to require the classes for all objects kept in the session.\n" +
- "(Original exception: #{const_error.message} [#{const_error.class}])\n")
+ "(Original exception: #{$!.message} [#{$!.class}])\n")
+ set_backtrace $!.backtrace
+ end
+
+ def original_exception
+ ActiveSupport::Deprecation.warn("#original_exception is deprecated. Use #cause instead.", caller)
+ cause
end
end
@@ -59,8 +67,8 @@ module ActionDispatch
begin
# Note that the regexp does not allow $1 to end with a ':'
$1.constantize
- rescue LoadError, NameError => e
- raise ActionDispatch::Session::SessionRestoreError, e, e.backtrace
+ rescue LoadError, NameError
+ raise ActionDispatch::Session::SessionRestoreError
end
retry
else
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index 0e636b8257..429a98f236 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -36,7 +36,7 @@ module ActionDispatch
# development:
# secret_key_base: 'secret key'
#
- # To generate a secret key for an existing application, run `rake secret`.
+ # To generate a secret key for an existing application, run `rails secret`.
#
# If you are upgrading an existing Rails 3 app, you should leave your
# existing secret_token in place and simply add the new secret_key_base.
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 47f475559a..735b5939dd 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -1,19 +1,23 @@
module ActionDispatch
- # This middleware is added to the stack when `config.force_ssl = true`.
- # It does three jobs to enforce secure HTTP requests:
+ # This middleware is added to the stack when `config.force_ssl = true`, and is passed
+ # the options set in `config.ssl_options`. It does three jobs to enforce secure HTTP
+ # requests:
#
- # 1. TLS redirect. http:// requests are permanently redirected to https://
- # with the same URL host, path, etc. Pass `:host` and/or `:port` to
- # modify the destination URL. This is always enabled.
+ # 1. TLS redirect: Permanently redirects http:// requests to https://
+ # with the same URL host, path, etc. Enabled by default. Set `config.ssl_options`
+ # to modify the destination URL
+ # (e.g. `redirect: { host: "secure.widgets.com", port: 8080 }`), or set
+ # `redirect: false` to disable this feature.
#
- # 2. Secure cookies. Sets the `secure` flag on cookies to tell browsers they
- # mustn't be sent along with http:// requests. This is always enabled.
+ # 2. Secure cookies: Sets the `secure` flag on cookies to tell browsers they
+ # mustn't be sent along with http:// requests. Enabled by default. Set
+ # `config.ssl_options` with `secure_cookies: false` to disable this feature.
#
- # 3. HTTP Strict Transport Security (HSTS). Tells the browser to remember
+ # 3. HTTP Strict Transport Security (HSTS): Tells the browser to remember
# this site as TLS-only and automatically redirect non-TLS requests.
- # Enabled by default. Pass `hsts: false` to disable.
+ # Enabled by default. Configure `config.ssl_options` with `hsts: false` to disable.
#
- # Configure HSTS with `hsts: { … }`:
+ # Set `config.ssl_options` with `hsts: { … }` to configure HSTS:
# * `expires`: How long, in seconds, these settings will stick. Defaults to
# `180.days` (recommended). The minimum required to qualify for browser
# preload lists is `18.weeks`.
@@ -26,10 +30,10 @@ module ActionDispatch
# gap, browser vendors include a baked-in list of HSTS-enabled sites.
# Go to https://hstspreload.appspot.com to submit your site for inclusion.
#
- # Disabling HSTS: To turn off HSTS, omitting the header is not enough.
- # Browsers will remember the original HSTS directive until it expires.
- # Instead, use the header to tell browsers to expire HSTS immediately.
- # Setting `hsts: false` is a shortcut for `hsts: { expires: 0 }`.
+ # To turn off HSTS, omitting the header is not enough. Browsers will remember the
+ # original HSTS directive until it expires. Instead, use the header to tell browsers to
+ # expire HSTS immediately. Setting `hsts: false` is a shortcut for
+ # `hsts: { expires: 0 }`.
class SSL
# Default to 180 days, the low end for https://www.ssllabs.com/ssltest/
# and greater than the 18-week requirement for browser preload lists.
@@ -39,7 +43,7 @@ module ActionDispatch
{ expires: HSTS_EXPIRES_IN, subdomains: false, preload: false }
end
- def initialize(app, redirect: {}, hsts: {}, **options)
+ def initialize(app, redirect: {}, hsts: {}, secure_cookies: true, **options)
@app = app
if options[:host] || options[:port]
@@ -52,6 +56,7 @@ module ActionDispatch
@redirect = redirect
end
+ @secure_cookies = secure_cookies
@hsts_header = build_hsts_header(normalize_hsts_options(hsts))
end
@@ -61,10 +66,11 @@ module ActionDispatch
if request.ssl?
@app.call(env).tap do |status, headers, body|
set_hsts_header! headers
- flag_cookies_as_secure! headers
+ flag_cookies_as_secure! headers if @secure_cookies
end
else
- redirect_to_https request
+ return redirect_to_https request if @redirect
+ @app.call(env)
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index 90e2ae6802..0b4bee5462 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -14,8 +14,21 @@ module ActionDispatch
def name; klass.name; end
+ def ==(middleware)
+ case middleware
+ when Middleware
+ klass == middleware.klass
+ when Class
+ klass == middleware
+ end
+ end
+
def inspect
- klass.to_s
+ if klass.is_a?(Class)
+ klass.to_s
+ else
+ klass.class.to_s
+ end
end
def build(app)
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index 75f8e05a3f..ea9ab3821d 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -15,7 +15,6 @@ module ActionDispatch
class FileHandler
def initialize(root, index: 'index', headers: {})
@root = root.chomp('/')
- @compiled_root = /^#{Regexp.escape(root)}/
@file_server = ::Rack::File.new(@root, headers)
@index = index
end
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
index e7b913bbe4..e7b913bbe4 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.text.erb
new file mode 100644
index 0000000000..23a9c7ba3f
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.text.erb
@@ -0,0 +1,8 @@
+<% @source_extracts.first(3).each do |source_extract| %>
+<% if source_extract[:code] %>
+Extracted source (around line #<%= source_extract[:line_number] %>):
+
+<% source_extract[:code].each do |line, source| -%>
+<%= line == source_extract[:line_number] ? "*#{line}" : "##{line}" -%> <%= source -%><% end -%>
+<% end %>
+<% end %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb
index c1e8b6cae3..5060da9369 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb
@@ -1,6 +1,6 @@
<header>
<h1>
- <%= @exception.original_exception.class.to_s %> in
+ <%= @exception.cause.class.to_s %> in
<%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %>
</h1>
</header>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb
index 77bcd26726..78d52acd96 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb
@@ -1,4 +1,4 @@
-<%= @exception.original_exception.class.to_s %> in <%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %>
+<%= @exception.cause.class.to_s %> in <%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %>
Showing <%= @exception.file_name %> where line #<%= @exception.line_number %> raised:
<%= @exception.message %>
diff --git a/actionpack/lib/action_dispatch/request/utils.rb b/actionpack/lib/action_dispatch/request/utils.rb
index a8151a8224..bb3df3c311 100644
--- a/actionpack/lib/action_dispatch/request/utils.rb
+++ b/actionpack/lib/action_dispatch/request/utils.rb
@@ -13,6 +13,21 @@ module ActionDispatch
end
end
+ def self.check_param_encoding(params)
+ case params
+ when Array
+ params.each { |element| check_param_encoding(element) }
+ when Hash
+ params.each_value { |value| check_param_encoding(value) }
+ when String
+ unless params.valid_encoding?
+ # Raise Rack::Utils::InvalidParameterError for consistency with Rack.
+ # ActionDispatch::Request#GET will re-raise as a BadRequest error.
+ raise Rack::Utils::InvalidParameterError, "Non UTF-8 value: #{params}"
+ end
+ end
+ end
+
class ParamEncoder # :nodoc:
# Convert nested Hash to HashWithIndifferentAccess.
#
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 59c3f9248f..d00b2c3eb5 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -237,7 +237,7 @@ module ActionDispatch
#
# == View a list of all your routes
#
- # rake routes
+ # rails routes
#
# Target specific controllers by prefixing the command with <tt>CONTROLLER=x</tt>.
#
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index f3a5268d2e..69e6dd5215 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -65,7 +65,7 @@ module ActionDispatch
routes = collect_routes(routes_to_display)
if routes.none?
- formatter.no_routes
+ formatter.no_routes(collect_routes(@routes), filter)
return formatter.result
end
@@ -84,7 +84,8 @@ module ActionDispatch
def filter_routes(filter)
if filter
- @routes.select { |route| route.defaults[:controller] == filter }
+ filter_name = filter.underscore.sub(/_controller$/, '')
+ @routes.select { |route| route.defaults[:controller] == filter_name }
else
@routes
end
@@ -136,17 +137,27 @@ module ActionDispatch
@buffer << draw_header(routes)
end
- def no_routes
- @buffer << <<-MESSAGE.strip_heredoc
+ def no_routes(routes, filter)
+ @buffer <<
+ if routes.none?
+ <<-MESSAGE.strip_heredoc
You don't have any routes defined!
Please add some routes in config/routes.rb.
-
- For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html.
MESSAGE
+ elsif missing_controller?(filter)
+ "The controller #{filter} does not exist!"
+ else
+ "No routes were found for this controller"
+ end
+ @buffer << "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html."
end
private
+ def missing_controller?(controller_name)
+ [ controller_name.camelize, "#{controller_name.camelize}Controller" ].none?(&:safe_constantize)
+ end
+
def draw_section(routes)
header_lengths = ['Prefix', 'Verb', 'URI Pattern'].map(&:length)
name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max)
@@ -187,7 +198,7 @@ module ActionDispatch
def header(routes)
end
- def no_routes
+ def no_routes(*)
@buffer << <<-MESSAGE.strip_heredoc
<p>You don't have any routes defined!</p>
<ul>
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 921cda91ee..522012063d 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -3,7 +3,6 @@ require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/enumerable'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/regexp'
-require 'active_support/deprecation'
require 'action_dispatch/routing/redirection'
require 'action_dispatch/routing/endpoint'
@@ -12,7 +11,7 @@ module ActionDispatch
class Mapper
URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
- class Constraints < Endpoint #:nodoc:
+ class Constraints < Routing::Endpoint #:nodoc:
attr_reader :app, :constraints
SERVE = ->(app, req) { app.serve req }
@@ -388,24 +387,6 @@ module ActionDispatch
end
module Base
- # You can specify what Rails should route "/" to with the root method:
- #
- # root to: 'pages#main'
- #
- # For options, see +match+, as +root+ uses it internally.
- #
- # You can also pass a string which will expand
- #
- # root 'pages#main'
- #
- # You should put the root route at the top of <tt>config/routes.rb</tt>,
- # because this means it will be matched first. As this is the most popular route
- # of most Rails applications, this is beneficial.
- def root(options = {})
- name = has_named_route?(:root) ? nil : :root
- match '/', { as: name, via: :get }.merge!(options)
- end
-
# Matches a url pattern to one or more routes.
#
# You should not use the +match+ method in your router
@@ -601,17 +582,20 @@ module ActionDispatch
def mount(app, options = nil)
if options
path = options.delete(:at)
- else
- unless Hash === app
- raise ArgumentError, "must be called with mount point"
- end
-
+ elsif Hash === app
options = app
app, path = options.find { |k, _| k.respond_to?(:call) }
options.delete(app) if app
end
- raise "A rack application must be specified" unless path
+ raise ArgumentError, "A rack application must be specified" unless app.respond_to?(:call)
+ raise ArgumentError, <<-MSG.strip_heredoc unless path
+ Must be called with mount point
+
+ mount SomeRackApp, at: "some_route"
+ or
+ mount(SomeRackApp => "some_route")
+ MSG
rails_app = rails_app? app
options[:as] ||= app_name(app, rails_app)
@@ -1687,7 +1671,20 @@ to this:
@set.add_route(mapping, ast, as, anchor)
end
- def root(path, options={})
+ # You can specify what Rails should route "/" to with the root method:
+ #
+ # root to: 'pages#main'
+ #
+ # For options, see +match+, as +root+ uses it internally.
+ #
+ # You can also pass a string which will expand
+ #
+ # root 'pages#main'
+ #
+ # You should put the root route at the top of <tt>config/routes.rb</tt>,
+ # because this means it will be matched first. As this is the most popular route
+ # of most Rails applications, this is beneficial.
+ def root(path, options = {})
if path.is_a?(String)
options[:to] = path
elsif path.is_a?(Hash) and options.empty?
@@ -1699,11 +1696,11 @@ to this:
if @scope.resources?
with_scope_level(:root) do
path_scope(parent_resource.path) do
- super(options)
+ match_root_route(options)
end
end
else
- super(options)
+ match_root_route(options)
end
end
@@ -1898,6 +1895,11 @@ to this:
ensure
@scope = @scope.parent
end
+
+ def match_root_route(options)
+ name = has_named_route?(:root) ? nil : :root
+ match '/', { :as => name, :via => :get }.merge!(options)
+ end
end
# Routing Concerns allow you to declare common routes that can be reused
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 339e2b7c4a..846b5fa1fc 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -1,5 +1,4 @@
require 'action_dispatch/journey'
-require 'forwardable'
require 'active_support/concern'
require 'active_support/core_ext/object/to_query'
require 'active_support/core_ext/hash/slice'
@@ -31,9 +30,9 @@ module ActionDispatch
controller = controller req
res = controller.make_response! req
dispatch(controller, params[:action], req, res)
- rescue NameError => e
+ rescue ActionController::RoutingError
if @raise_on_name_error
- raise ActionController::RoutingError, e.message, e.backtrace
+ raise
else
return [404, {'X-Cascade' => 'pass'}, []]
end
@@ -43,6 +42,8 @@ module ActionDispatch
def controller(req)
req.controller_class
+ rescue NameError => e
+ raise ActionController::RoutingError, e.message, e.backtrace
end
def dispatch(controller, action, req, res)
@@ -280,8 +281,17 @@ module ActionDispatch
helper = UrlHelper.create(route, opts, route_key, url_strategy)
mod.module_eval do
define_method(name) do |*args|
- options = nil
- options = args.pop if args.last.is_a? Hash
+ last = args.last
+ options = case last
+ when Hash
+ args.pop
+ when ActionController::Parameters
+ if last.permitted?
+ args.pop.to_h
+ else
+ raise ArgumentError, "Generating an URL from non sanitized request parameters is insecure!"
+ end
+ end
helper.call self, args, options
end
end
@@ -372,10 +382,6 @@ module ActionDispatch
end
def eval_block(block)
- if block.arity == 1
- raise "You are using the old router DSL which has been removed in Rails 3.1. " <<
- "Please check how to update your routes file at: http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/"
- end
mapper = Mapper.new(self)
if default_scope
mapper.with_default_scope(default_scope, &block)
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index b6c031dcf4..f91679593e 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -172,8 +172,11 @@ module ActionDispatch
_routes.url_for(options.symbolize_keys.reverse_merge!(url_options),
route_name)
when ActionController::Parameters
+ unless options.permitted?
+ raise ArgumentError.new("Generating an URL from non sanitized request parameters is insecure!")
+ end
route_name = options.delete :use_route
- _routes.url_for(options.to_unsafe_h.symbolize_keys.
+ _routes.url_for(options.to_h.symbolize_keys.
reverse_merge!(url_options), route_name)
when String
options
diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb
index 8dd0bd63ad..fae266273e 100644
--- a/actionpack/lib/action_dispatch/testing/assertions.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions.rb
@@ -12,7 +12,7 @@ module ActionDispatch
include Rails::Dom::Testing::Assertions
def html_document
- @html_document ||= if @response.content_type === Mime[:xml]
+ @html_document ||= if @response.content_type.to_s =~ /xml\z/
Nokogiri::XML::Document.parse(@response.body)
else
Nokogiri::HTML::Document.parse(@response.body)
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
index b6e21b0d28..c138660a21 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -21,15 +21,17 @@ module ActionDispatch
# or its symbolic equivalent <tt>assert_response(:not_implemented)</tt>.
# See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list.
#
- # # assert that the response was a redirection
+ # # Asserts that the response was a redirection
# assert_response :redirect
#
- # # assert that the response code was status code 401 (unauthorized)
+ # # Asserts that the response code was status code 401 (unauthorized)
# assert_response 401
def assert_response(type, message = nil)
+ message ||= generate_response_message(type)
+
if Symbol === type
if [:success, :missing, :redirect, :error].include?(type)
- assert_predicate @response, RESPONSE_PREDICATES[type], message
+ assert @response.send(RESPONSE_PREDICATES[type]), message
else
code = Rack::Utils::SYMBOL_TO_STATUS_CODE[type]
if code.nil?
@@ -42,20 +44,20 @@ module ActionDispatch
end
end
- # Assert that the redirection options passed in match those of the redirect called in the latest action.
+ # Asserts that the redirection options passed in match those of the redirect called in the latest action.
# This match can be partial, such that <tt>assert_redirected_to(controller: "weblog")</tt> will also
# match the redirection of <tt>redirect_to(controller: "weblog", action: "show")</tt> and so on.
#
- # # assert that the redirection was to the "index" action on the WeblogController
+ # # Asserts that the redirection was to the "index" action on the WeblogController
# assert_redirected_to controller: "weblog", action: "index"
#
- # # assert that the redirection was to the named route login_url
+ # # Asserts that the redirection was to the named route login_url
# assert_redirected_to login_url
#
- # # assert that the redirection was to the url for @customer
+ # # Asserts that the redirection was to the url for @customer
# assert_redirected_to @customer
#
- # # asserts that the redirection matches the regular expression
+ # # Asserts that the redirection matches the regular expression
# assert_redirected_to %r(\Ahttp://example.org)
def assert_redirected_to(options = {}, message=nil)
assert_response(:redirect, message)
@@ -82,6 +84,17 @@ module ActionDispatch
handle._compute_redirect_to_location(@request, fragment)
end
end
+
+ def generate_response_message(type, code = @response.response_code)
+ "Expected response to be a <#{type}>, but was a <#{code}>"
+ .concat location_if_redirected
+ end
+
+ def location_if_redirected
+ return '' unless @response.redirection? && @response.location.present?
+ location = normalize_argument_to_redirection(@response.location)
+ " redirect to <#{location}>"
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index 54e24ed6bf..78ef860548 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -14,14 +14,14 @@ module ActionDispatch
# requiring a specific HTTP method. The hash should contain a :path with the incoming request path
# and a :method containing the required HTTP verb.
#
- # # assert that POSTing to /items will call the create action on ItemsController
+ # # Asserts that POSTing to /items will call the create action on ItemsController
# assert_recognizes({controller: 'items', action: 'create'}, {path: 'items', method: :post})
#
# You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used
- # to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the
+ # to assert that values in the query string will end up in the params hash correctly. To test query strings you must use the
# extras argument, appending the query string on the path directly will not work. For example:
#
- # # assert that a path of '/items/list/1?view=print' returns the correct options
+ # # Asserts that a path of '/items/list/1?view=print' returns the correct options
# assert_recognizes({controller: 'items', action: 'list', id: '1', view: 'print'}, 'items/list/1', { view: "print" })
#
# The +message+ parameter allows you to pass in an error message that is displayed upon failure.
@@ -104,13 +104,13 @@ module ActionDispatch
# The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
# +message+ parameter allows you to specify a custom error message to display upon failure.
#
- # # Assert a basic route: a controller with the default action (index)
+ # # Asserts a basic route: a controller with the default action (index)
# assert_routing '/home', controller: 'home', action: 'index'
#
# # Test a route generated with a specific controller, action, and parameter (id)
# assert_routing '/entries/show/23', controller: 'entries', action: 'show', id: 23
#
- # # Assert a basic route (controller + default action), with an error message if it fails
+ # # Asserts a basic route (controller + default action), with an error message if it fails
# assert_routing '/store', { controller: 'store', action: 'index' }, {}, {}, 'Route for store index not generated properly'
#
# # Tests a route, providing a defaults hash
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 7e59bb68cf..711ca10419 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -131,35 +131,35 @@ module ActionDispatch
# Performs a GET request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def get_via_redirect(path, *args)
- ActiveSupport::Deprecation.warn('`get_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
+ ActiveSupport::Deprecation.warn('`get_via_redirect` is deprecated and will be removed in Rails 5.1. Please use follow_redirect! manually after the request call for the same behavior.')
request_via_redirect(:get, path, *args)
end
# Performs a POST request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def post_via_redirect(path, *args)
- ActiveSupport::Deprecation.warn('`post_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
+ ActiveSupport::Deprecation.warn('`post_via_redirect` is deprecated and will be removed in Rails 5.1. Please use follow_redirect! manually after the request call for the same behavior.')
request_via_redirect(:post, path, *args)
end
# Performs a PATCH request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def patch_via_redirect(path, *args)
- ActiveSupport::Deprecation.warn('`patch_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
+ ActiveSupport::Deprecation.warn('`patch_via_redirect` is deprecated and will be removed in Rails 5.1. Please use follow_redirect! manually after the request call for the same behavior.')
request_via_redirect(:patch, path, *args)
end
# Performs a PUT request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def put_via_redirect(path, *args)
- ActiveSupport::Deprecation.warn('`put_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
+ ActiveSupport::Deprecation.warn('`put_via_redirect` is deprecated and will be removed in Rails 5.1. Please use follow_redirect! manually after the request call for the same behavior.')
request_via_redirect(:put, path, *args)
end
# Performs a DELETE request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def delete_via_redirect(path, *args)
- ActiveSupport::Deprecation.warn('`delete_via_redirect` is deprecated and will be removed in the next version of Rails. Please use follow_redirect! manually after the request call for the same behavior.')
+ ActiveSupport::Deprecation.warn('`delete_via_redirect` is deprecated and will be removed in Rails 5.1. Please use follow_redirect! manually after the request call for the same behavior.')
request_via_redirect(:delete, path, *args)
end
end
@@ -375,6 +375,7 @@ module ActionDispatch
@request = ActionDispatch::Request.new(session.last_request.env)
response = _mock_session.last_response
@response = ActionDispatch::TestResponse.from_response(response)
+ @response.request = @request
@html_document = nil
@url_options = nil
diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb
index c28d701b48..eca0439909 100644
--- a/actionpack/lib/action_dispatch/testing/test_process.rb
+++ b/actionpack/lib/action_dispatch/testing/test_process.rb
@@ -26,7 +26,7 @@ module ActionDispatch
@response.redirect_url
end
- # Shortcut for <tt>Rack::Test::UploadedFile.new(File.join(ActionController::TestCase.fixture_path, path), type)</tt>:
+ # Shortcut for <tt>Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.fixture_path, path), type)</tt>:
#
# post :change_avatar, avatar: fixture_file_upload('files/spongebob.png', 'image/png')
#