aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb4
-rw-r--r--actionpack/lib/action_controller/metal/head.rb2
-rw-r--r--actionpack/lib/action_controller/metal/instrumentation.rb2
-rw-r--r--actionpack/lib/action_controller/metal/live.rb2
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb11
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb2
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb3
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb79
-rw-r--r--actionpack/lib/action_controller/metal/responder.rb2
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb40
-rw-r--r--actionpack/lib/action_controller/railtie.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb2
-rw-r--r--actionpack/lib/action_dispatch/journey/parser.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb16
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb5
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb4
-rw-r--r--actionpack/lib/action_dispatch/railtie.rb2
-rw-r--r--actionpack/lib/action_dispatch/request/session.rb16
-rw-r--r--actionpack/lib/action_dispatch/request/utils.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb4
-rw-r--r--actionpack/lib/action_pack/version.rb2
25 files changed, 149 insertions, 66 deletions
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index 2580a78c7d..7be61d94c9 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -22,7 +22,7 @@ module AbstractController
def render(*args, &block)
options = _normalize_render(*args, &block)
self.response_body = render_to_body(options)
- _process_format(rendered_format)
+ _process_format(rendered_format) if rendered_format
self.response_body
end
@@ -47,7 +47,7 @@ module AbstractController
def render_to_body(options = {})
end
- # Return Content-Type of rendered content
+ # Returns Content-Type of rendered content
# :api: public
def rendered_format
Mime::TEXT
diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb
index 424473801d..43407f5b78 100644
--- a/actionpack/lib/action_controller/metal/head.rb
+++ b/actionpack/lib/action_controller/metal/head.rb
@@ -1,6 +1,6 @@
module ActionController
module Head
- # Return a response that has no content (merely headers). The options
+ # Returns a response that has no content (merely headers). The options
# argument is interpreted to be a hash of header names and values.
# This allows you to easily return a response that consists only of
# significant headers:
diff --git a/actionpack/lib/action_controller/metal/instrumentation.rb b/actionpack/lib/action_controller/metal/instrumentation.rb
index d3aa8f90c5..b0e164bc57 100644
--- a/actionpack/lib/action_controller/metal/instrumentation.rb
+++ b/actionpack/lib/action_controller/metal/instrumentation.rb
@@ -67,7 +67,7 @@ module ActionController
private
- # A hook invoked everytime a before callback is halted.
+ # A hook invoked every time a before callback is halted.
def halted_callback_hook(filter)
ActiveSupport::Notifications.instrument("halted_callback.action_controller", :filter => filter)
end
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index 0dd788645b..b7d1334dd3 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -48,7 +48,7 @@ module ActionController
# the server will receive a +Last-Event-ID+ header with value equal to +id+.
#
# After setting an option in the constructor of the SSE object, all future
- # SSEs sent accross the stream will use those options unless overridden.
+ # SSEs sent across the stream will use those options unless overridden.
#
# Example Usage:
#
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index dedff9f476..fbc4024c2d 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -184,7 +184,7 @@ module ActionController #:nodoc:
# Formats can have different variants.
#
# The request variant is a specialization of the request format, like <tt>:tablet</tt>,
- # <tt>:phone</tt>, or <tt>:desktop<tt>.
+ # <tt>:phone</tt>, or <tt>:desktop</tt>.
#
# We often want to render different html/json/xml templates for phones,
# tablets, and desktop browsers. Variants make it easy.
@@ -209,6 +209,15 @@ module ActionController #:nodoc:
# app/views/projects/show.html+tablet.erb
# app/views/projects/show.html+phone.erb
#
+ # When you're not sharing any code within the format, you can simplify defining variants
+ # using the inline syntax:
+ #
+ # respond_to do |format|
+ # format.js { render "trash" }
+ # format.html.phone { redirect_to progress_path }
+ # format.html.none { render "trash" }
+ # end
+ #
# Be sure to check the documentation of +respond_with+ and
# <tt>ActionController::MimeResponds.respond_to</tt> for more examples.
def respond_to(*mimes, &block)
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index ab14a61b97..2812038938 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -58,7 +58,7 @@ module ActionController
# redirect_to post_url(@post), alert: "Watch it, mister!"
# redirect_to post_url(@post), status: :found, notice: "Pay attention to the road"
# redirect_to post_url(@post), status: 301, flash: { updated_post_id: @post.id }
- # redirect_to { action: 'atom' }, alert: "Something serious happened"
+ # redirect_to({ action: 'atom' }, alert: "Something serious happened")
#
# When using <tt>redirect_to :back</tt>, if there is no referrer, ActionController::RedirectBackError will be raised. You may specify some fallback
# behavior for this case by rescuing ActionController::RedirectBackError.
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index 66d34f3b67..5c48b4ab98 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -34,8 +34,7 @@ module ActionController
def _process_format(format)
super
- # format is a Mime::NullType instance here then this condition can't be changed to `if format`
- self.content_type ||= format.to_s unless format.nil?
+ self.content_type ||= format.to_s
end
# Normalize arguments by catching blocks and setting them on :update.
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index bd64b1f812..c88074d4c6 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -5,14 +5,24 @@ module ActionController #:nodoc:
class InvalidAuthenticityToken < ActionControllerError #:nodoc:
end
+ class InvalidCrossOriginRequest < ActionControllerError #:nodoc:
+ end
+
# Controller actions are protected from Cross-Site Request Forgery (CSRF) attacks
# by including a token in the rendered html for your application. This token is
# stored as a random string in the session, to which an attacker does not have
# access. When a request reaches your application, \Rails verifies the received
# token with the token in the session. Only HTML and JavaScript requests are checked,
# so this will not protect your XML API (presumably you'll have a different
- # authentication scheme there anyway). Also, GET requests are not protected as these
- # should be idempotent.
+ # authentication scheme there anyway).
+ #
+ # GET requests are not protected since they don't have side effects like writing
+ # to the database and don't leak sensitive information. JavaScript requests are
+ # an exception: a third-party site can use a <script> tag to reference a JavaScript
+ # URL on your site. When your JavaScript response loads on their site, it executes.
+ # With carefully crafted JavaScript on their end, sensitive data in your JavaScript
+ # response may be extracted. To prevent this, only XmlHttpRequest (known as XHR or
+ # Ajax) requests are allowed to make GET requests for JavaScript responses.
#
# It's important to remember that XML or JSON requests are also affected and if
# you're building an API you'll need something like:
@@ -65,17 +75,16 @@ module ActionController #:nodoc:
module ClassMethods
# Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked.
#
+ # class ApplicationController < ActionController::Base
+ # protect_from_forgery
+ # end
+ #
# class FooController < ApplicationController
# protect_from_forgery except: :index
#
- # You can disable csrf protection on controller-by-controller basis:
- #
+ # You can disable CSRF protection on controller by skipping the verification before_action:
# skip_before_action :verify_authenticity_token
#
- # It can also be disabled for specific controller actions:
- #
- # skip_before_action :verify_authenticity_token, except: [:create]
- #
# Valid Options:
#
# * <tt>:only/:except</tt> - Passed to the <tt>before_action</tt> call. Set which actions are verified.
@@ -89,6 +98,7 @@ module ActionController #:nodoc:
self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
self.request_forgery_protection_token ||= :authenticity_token
prepend_before_action :verify_authenticity_token, options
+ append_after_action :verify_same_origin_request
end
private
@@ -169,18 +179,61 @@ module ActionController #:nodoc:
end
protected
+ # The actual before_action that is used to verify the CSRF token.
+ # Don't override this directly. Provide your own forgery protection
+ # strategy instead. If you override, you'll disable same-origin
+ # `<script>` verification.
+ #
+ # Lean on the protect_from_forgery declaration to mark which actions are
+ # due for same-origin request verification. If protect_from_forgery is
+ # enabled on an action, this before_action flags its after_action to
+ # verify that JavaScript responses are for XHR requests, ensuring they
+ # follow the browser's same-origin policy.
+ def verify_authenticity_token
+ mark_for_same_origin_verification!
+
+ if !verified_request?
+ logger.warn "Can't verify CSRF token authenticity" if logger
+ handle_unverified_request
+ end
+ end
+
def handle_unverified_request
forgery_protection_strategy.new(self).handle_unverified_request
end
- # The actual before_action that is used. Modify this to change how you handle unverified requests.
- def verify_authenticity_token
- unless verified_request?
- logger.warn "Can't verify CSRF token authenticity" if logger
- handle_unverified_request
+ CROSS_ORIGIN_JAVASCRIPT_WARNING = "Security warning: an embedded " \
+ "<script> tag on another site requested protected JavaScript. " \
+ "If you know what you're doing, go ahead and disable forgery " \
+ "protection on this action to permit cross-origin JavaScript embedding."
+ private_constant :CROSS_ORIGIN_JAVASCRIPT_WARNING
+
+ # If `verify_authenticity_token` was run (indicating that we have
+ # forgery protection enabled for this request) then also verify that
+ # we aren't serving an unauthorized cross-origin response.
+ def verify_same_origin_request
+ if marked_for_same_origin_verification? && non_xhr_javascript_response?
+ logger.warn CROSS_ORIGIN_JAVASCRIPT_WARNING if logger
+ raise ActionController::InvalidCrossOriginRequest, CROSS_ORIGIN_JAVASCRIPT_WARNING
end
end
+ # GET requests are checked for cross-origin JavaScript after rendering.
+ def mark_for_same_origin_verification!
+ @marked_for_same_origin_verification = request.get?
+ end
+
+ # If the `verify_authenticity_token` before_action ran, verify that
+ # JavaScript responses are only served to same-origin GET requests.
+ def marked_for_same_origin_verification?
+ @marked_for_same_origin_verification ||= false
+ end
+
+ # Check for cross-origin JavaScript responses.
+ def non_xhr_javascript_response?
+ content_type =~ %r(\Atext/javascript) && !request.xhr?
+ end
+
# Returns true or false if a request is verified. Checks:
#
# * is it a GET or HEAD request? Gets should be safe and idempotent
diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb
index b4ba169e8f..e24b56fa91 100644
--- a/actionpack/lib/action_controller/metal/responder.rb
+++ b/actionpack/lib/action_controller/metal/responder.rb
@@ -270,7 +270,7 @@ module ActionController #:nodoc:
resource.respond_to?(:errors) && !resource.errors.empty?
end
- # Check whether the neceessary Renderer is available
+ # Check whether the necessary Renderer is available
def has_renderer?
Renderers::RENDERERS.include?(format)
end
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index b4948d99a8..48a916f2b1 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -3,6 +3,7 @@ require 'active_support/core_ext/array/wrap'
require 'active_support/rescuable'
require 'action_dispatch/http/upload'
require 'stringio'
+require 'set'
module ActionController
# Raised when a required parameter is missing.
@@ -125,6 +126,13 @@ module ActionController
@permitted = self.class.permit_all_parameters
end
+ # Attribute that keeps track of converted arrays, if any, to avoid double
+ # looping in the common use case permit + mass-assignment. Defined in a
+ # method to instantiate it only if needed.
+ def converted_arrays
+ @converted_arrays ||= Set.new
+ end
+
# Returns +true+ if the parameter is permitted, +false+ otherwise.
#
# params = ActionController::Parameters.new
@@ -149,8 +157,10 @@ module ActionController
# Person.new(params) # => #<Person id: nil, name: "Francesco">
def permit!
each_pair do |key, value|
- convert_hashes_to_parameters(key, value)
- self[key].permit! if self[key].respond_to? :permit!
+ value = convert_hashes_to_parameters(key, value)
+ Array.wrap(value).each do |_|
+ _.permit! if _.respond_to? :permit!
+ end
end
@permitted = true
@@ -284,14 +294,7 @@ module ActionController
# params.fetch(:none, 'Francesco') # => "Francesco"
# params.fetch(:none) { 'Francesco' } # => "Francesco"
def fetch(key, *args)
- value = super
- # Don't rely on +convert_hashes_to_parameters+
- # so as to not mutate via a +fetch+
- if value.is_a?(Hash)
- value = self.class.new(value)
- value.permit! if permitted?
- end
- value
+ convert_hashes_to_parameters(key, super, false)
rescue KeyError
raise ActionController::ParameterMissing.new(key)
end
@@ -329,12 +332,21 @@ module ActionController
end
private
- def convert_hashes_to_parameters(key, value)
- if value.is_a?(Parameters) || !value.is_a?(Hash)
+ def convert_hashes_to_parameters(key, value, assign_if_converted=true)
+ converted = convert_value_to_parameters(value)
+ self[key] = converted if assign_if_converted && !converted.equal?(value)
+ converted
+ end
+
+ def convert_value_to_parameters(value)
+ if value.is_a?(Array) && !converted_arrays.member?(value)
+ converted = value.map { |_| convert_value_to_parameters(_) }
+ converted_arrays << converted
+ converted
+ elsif value.is_a?(Parameters) || !value.is_a?(Hash)
value
else
- # Convert to Parameters on first access
- self[key] = self.class.new(value)
+ self.class.new(value)
end
end
diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb
index 0833e65d23..a2fc814221 100644
--- a/actionpack/lib/action_controller/railtie.rb
+++ b/actionpack/lib/action_controller/railtie.rb
@@ -3,6 +3,7 @@ require "action_controller"
require "action_dispatch/railtie"
require "abstract_controller/railties/routes_helpers"
require "action_controller/railties/helpers"
+require "action_view/railtie"
module ActionController
class Railtie < Rails::Railtie #:nodoc:
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index 346598b6de..c33ba201e1 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -50,7 +50,7 @@ module ActionDispatch
# GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first
#
def format(view_path = [])
- formats.first
+ formats.first || Mime::NullType.instance
end
def formats
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 2a8ff0a5d2..3d2dd2d632 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -28,7 +28,7 @@ module Mime
class << self
def [](type)
return type if type.is_a?(Type)
- Type.lookup_by_extension(type) || NullType.instance
+ Type.lookup_by_extension(type)
end
def fetch(type)
diff --git a/actionpack/lib/action_dispatch/journey/parser.rb b/actionpack/lib/action_dispatch/journey/parser.rb
index bb4cbb00e2..430812fafe 100644
--- a/actionpack/lib/action_dispatch/journey/parser.rb
+++ b/actionpack/lib/action_dispatch/journey/parser.rb
@@ -1,7 +1,7 @@
#
# DO NOT MODIFY!!!!
# This file is automatically generated by Racc 1.4.9
-# from Racc grammer file "".
+# from Racc grammar file "".
#
require 'racc/parser.rb'
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 3ccd0c9ee8..fe110d7938 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -30,7 +30,7 @@ module ActionDispatch
# cookies[:login] = { value: "XJ-122", expires: 1.hour.from_now }
#
# # Sets a signed cookie, which prevents users from tampering with its value.
- # # The cookie is signed by your app's <tt>config.secret_key_base</tt> value.
+ # # The cookie is signed by your app's <tt>secrets.secret_key_base</tt> value.
# # It can be read using the signed method <tt>cookies.signed[:name]</tt>
# cookies.signed[:user_id] = current_user.id
#
@@ -117,10 +117,10 @@ module ActionDispatch
# the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed
# cookie was tampered with by the user (or a 3rd party), nil will be returned.
#
- # If +config.secret_key_base+ and +config.secret_token+ (deprecated) are both set,
+ # If +secrets.secret_key_base+ and +config.secret_token+ (deprecated) are both set,
# legacy cookies signed with the old key generator will be transparently upgraded.
#
- # This jar requires that you set a suitable secret for the verification on your app's +config.secret_key_base+.
+ # This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
#
# Example:
#
@@ -140,10 +140,10 @@ module ActionDispatch
# Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read.
# If the cookie was tampered with by the user (or a 3rd party), nil will be returned.
#
- # If +config.secret_key_base+ and +config.secret_token+ (deprecated) are both set,
+ # If +secrets.secret_key_base+ and +config.secret_token+ (deprecated) are both set,
# legacy cookies signed with the old key generator will be transparently upgraded.
#
- # This jar requires that you set a suitable secret for the verification on your app's +config.secret_key_base+.
+ # This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
#
# Example:
#
@@ -409,7 +409,7 @@ module ActionDispatch
end
# UpgradeLegacySignedCookieJar is used instead of SignedCookieJar if
- # config.secret_token and config.secret_key_base are both set. It reads
+ # config.secret_token and secrets.secret_key_base are both set. It reads
# legacy cookies signed with the old dummy key generator and re-saves
# them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacySignedCookieJar < SignedCookieJar #:nodoc:
@@ -427,7 +427,7 @@ module ActionDispatch
def initialize(parent_jar, key_generator, options = {})
if ActiveSupport::LegacyKeyGenerator === key_generator
- raise "You didn't set config.secret_key_base, which is required for this cookie jar. " +
+ raise "You didn't set secrets.secret_key_base, which is required for this cookie jar. " +
"Read the upgrade documentation to learn more about this new config option."
end
@@ -465,7 +465,7 @@ module ActionDispatch
end
# UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore
- # instead of EncryptedCookieJar if config.secret_token and config.secret_key_base
+ # instead of EncryptedCookieJar if config.secret_token and secrets.secret_key_base
# are both set. It reads legacy cookies signed with the old dummy key generator and
# encrypts and re-saves them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacyEncryptedCookieJar < EncryptedCookieJar #:nodoc:
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index 11b42ee5be..1ebc189c28 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -31,9 +31,10 @@ module ActionDispatch
#
# Myapp::Application.config.session_store :cookie_store, key: '_your_app_session'
#
- # Configure your secret key in config/initializers/secret_token.rb:
+ # Configure your secret key in config/secrets.yml:
#
- # Myapp::Application.config.secret_key_base 'secret key'
+ # development:
+ # secret_key_base: 'secret key'
#
# To generate a secret key for an existing application, run `rake secret`.
#
diff --git a/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
index 95461fa693..323873ba4b 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
@@ -89,8 +89,8 @@
}
// takes an array of elements with a data-regexp attribute and
- // passes their their parent <tr> into the callback function
- // if the regexp matchs a given path
+ // passes their parent <tr> into the callback function
+ // if the regexp matches a given path
function eachElemsForPath(elems, path, func) {
each(elems, function(e){
var reg = e.getAttribute("data-regexp");
diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb
index 2dfaab3587..ddeea24bb3 100644
--- a/actionpack/lib/action_dispatch/railtie.rb
+++ b/actionpack/lib/action_dispatch/railtie.rb
@@ -16,6 +16,7 @@ module ActionDispatch
config.action_dispatch.signed_cookie_salt = 'signed cookie'
config.action_dispatch.encrypted_cookie_salt = 'encrypted cookie'
config.action_dispatch.encrypted_signed_cookie_salt = 'signed encrypted cookie'
+ config.action_dispatch.perform_deep_munge = true
config.action_dispatch.default_headers = {
'X-Frame-Options' => 'SAMEORIGIN',
@@ -28,6 +29,7 @@ module ActionDispatch
initializer "action_dispatch.configure" do |app|
ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
+ ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge
ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
ActionDispatch::Response.default_headers = app.config.action_dispatch.default_headers
diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb
index 6d911a75f1..973627f106 100644
--- a/actionpack/lib/action_dispatch/request/session.rb
+++ b/actionpack/lib/action_dispatch/request/session.rb
@@ -7,6 +7,9 @@ module ActionDispatch
ENV_SESSION_KEY = Rack::Session::Abstract::ENV_SESSION_KEY # :nodoc:
ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY # :nodoc:
+ # Singleton object used to determine if an optional param wasn't specified
+ Unspecified = Object.new
+
def self.create(store, env, default_options)
session_was = find env
session = Request::Session.new(store, env)
@@ -127,15 +130,12 @@ module ActionDispatch
@delegate.delete key.to_s
end
- def fetch(key, default=nil)
- if self.key?(key)
- self[key]
- elsif default
- self[key] = default
- elsif block_given?
- self[key] = yield(key)
+ def fetch(key, default=Unspecified, &block)
+ load_for_read!
+ if default == Unspecified
+ @delegate.fetch(key.to_s, &block)
else
- raise KeyError
+ @delegate.fetch(key.to_s, default, &block)
end
end
diff --git a/actionpack/lib/action_dispatch/request/utils.rb b/actionpack/lib/action_dispatch/request/utils.rb
index 8b43cdada8..a6dca9741c 100644
--- a/actionpack/lib/action_dispatch/request/utils.rb
+++ b/actionpack/lib/action_dispatch/request/utils.rb
@@ -1,9 +1,15 @@
module ActionDispatch
class Request < Rack::Request
class Utils # :nodoc:
+
+ mattr_accessor :perform_deep_munge
+ self.perform_deep_munge = true
+
class << self
# Remove nils from the params hash
def deep_munge(hash)
+ return hash unless perform_deep_munge
+
hash.each do |k, v|
case v
when Array
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index 120bc54333..f612e91aef 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -69,7 +69,7 @@ module ActionDispatch
end
def internal?
- controller.to_s =~ %r{\Arails/(info|welcome)} || path =~ %r{\A#{Rails.application.config.assets.prefix}}
+ controller.to_s =~ %r{\Arails/(info|mailers|welcome)} || path =~ %r{\A#{Rails.application.config.assets.prefix}\z}
end
def engine?
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index b8abdabca5..04faabef37 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -361,7 +361,7 @@ module ActionDispatch
include UrlFor
end
- # Contains all the mounted helpers accross different
+ # Contains all the mounted helpers across different
# engines and the `main_app` helper for the application.
# You can include this in your classes if you want to
# access routes for other engines.
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index 496682e8bd..f1f998d932 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -211,7 +211,7 @@ module ActionDispatch
def fail_on(exception_class)
yield
rescue exception_class => e
- raise MiniTest::Assertion, e.message
+ raise Minitest::Assertion, e.message
end
end
end
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 9beb30307b..cc6b763093 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -137,7 +137,7 @@ module ActionDispatch
class Session
DEFAULT_HOST = "www.example.com"
- include MiniTest::Assertions
+ include Minitest::Assertions
include TestProcess, RequestHelpers, Assertions
%w( status status_message headers body redirect? ).each do |method|
@@ -242,7 +242,7 @@ module ActionDispatch
@https = flag
end
- # Return +true+ if the session is mimicking a secure HTTPS request.
+ # Returns +true+ if the session is mimicking a secure HTTPS request.
#
# if session.https?
# ...
diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb
index fd08f392aa..a51f6a434a 100644
--- a/actionpack/lib/action_pack/version.rb
+++ b/actionpack/lib/action_pack/version.rb
@@ -1,7 +1,7 @@
module ActionPack
# Returns the version of the currently loaded ActionPack as a Gem::Version
def self.version
- Gem::Version.new "4.1.0.beta"
+ Gem::Version.new "4.1.0.beta1"
end
module VERSION #:nodoc: