diff options
Diffstat (limited to 'actionpack')
24 files changed, 130 insertions, 59 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index a5497aa055..7781980cab 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,22 @@ +* Expose `ActionController::Parameters#each_key` which allows iterating over + keys without allocating an array. + + *Richard Schneeman* + +* Purpose metadata for signed/encrypted cookies. + + Rails can now thwart attacks that attempt to copy signed/encrypted value + of a cookie and use it as the value of another cookie. + + It does so by stashing the cookie-name in the purpose field which is + then signed/encrypted along with the cookie value. Then, on a server-side + read, we verify the cookie-names and discard any attacked cookies. + + Enable `action_dispatch.use_cookies_with_metadata` to use this feature, which + writes cookies with the new purpose and expiry metadata embedded. + + *Assain Jaleel* + * Raises `ActionController::RespondToMismatchError` with confliciting `respond_to` invocations. `respond_to` can match multiple types and lead to undefined behavior when @@ -23,7 +42,7 @@ *Aaron Kromer* -* Pass along arguments to underlying `get` method in `follow_redirect!` +* Pass along arguments to underlying `get` method in `follow_redirect!`. Now all arguments passed to `follow_redirect!` are passed to the underlying `get` method. This for example allows to set custom headers for the @@ -40,7 +59,7 @@ *Vinicius Stock* -* Introduce ActionDispatch::DebugExceptions.register_interceptor +* Introduce `ActionDispatch::DebugExceptions.register_interceptor`. Exception aware plugin authors can use the newly introduced `.register_interceptor` method to get the processed exception, instead of diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index a312af6715..6e6786d0be 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -78,7 +78,9 @@ module AbstractController # Except for public instance methods of Base and its ancestors internal_methods + # Be sure to include shadowed public instance methods of this class - public_instance_methods(false)).uniq.map(&:to_s) + public_instance_methods(false)) + + methods.map!(&:to_s) methods.to_set end diff --git a/actionpack/lib/abstract_controller/caching/fragments.rb b/actionpack/lib/abstract_controller/caching/fragments.rb index f99b0830b2..95078a2a28 100644 --- a/actionpack/lib/abstract_controller/caching/fragments.rb +++ b/actionpack/lib/abstract_controller/caching/fragments.rb @@ -82,13 +82,17 @@ module AbstractController # Given a key (as described in +expire_fragment+), returns # a key array suitable for use in reading, writing, or expiring a # cached fragment. All keys begin with <tt>:views</tt>, - # followed by ENV["RAILS_CACHE_ID"] or ENV["RAILS_APP_VERSION"] if set, + # followed by <tt>ENV["RAILS_CACHE_ID"]</tt> or <tt>ENV["RAILS_APP_VERSION"]</tt> if set, # followed by any controller-wide key prefix values, ending # with the specified +key+ value. def combined_fragment_cache_key(key) head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) } tail = key.is_a?(Hash) ? url_for(key).split("://").last : key - [ :views, (ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]), *head, *tail ].compact + + cache_key = [:views, ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"], head, tail] + cache_key.flatten!(1) + cache_key.compact! + cache_key end # Writes +content+ to the location signified by diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index 4be4557e2c..d6911ee2b5 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -230,6 +230,12 @@ module ActionController # This method will overwrite an existing Cache-Control header. # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities. # + # HTTP Cache-Control Extensions for Stale Content. See https://tools.ietf.org/html/rfc5861 + # It helps to cache an asset and serve it while is being revalidated and/or returning with an error. + # + # expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds + # expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds, stale_if_error: 5.minutes + # # The method will also ensure an HTTP Date header for client compatibility. def expires_in(seconds, options = {}) response.cache_control.merge!( diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb index 8d53a30e93..26e6f72b66 100644 --- a/actionpack/lib/action_controller/metal/force_ssl.rb +++ b/actionpack/lib/action_controller/metal/force_ssl.rb @@ -5,8 +5,8 @@ require "active_support/core_ext/hash/slice" module ActionController # This module is deprecated in favor of +config.force_ssl+ in your environment - # config file. This will ensure all communication to non-whitelisted endpoints - # served by your application occurs over HTTPS. + # config file. This will ensure all endpoints not explicitly marked otherwise + # will have all communication served over HTTPS. module ForceSSL # :nodoc: extend ActiveSupport::Concern include AbstractController::Callbacks diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index 22c84e440b..0faaac1ce4 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -100,8 +100,7 @@ module ActionController # # => ["application", "chart", "rubygems"] def all_helpers_from_path(path) helpers = Array(path).flat_map do |_path| - extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/ - names = Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1'.freeze) } + names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] } names.sort! end helpers.uniq! diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb index 2f4c8fb83c..b1c2391afe 100644 --- a/actionpack/lib/action_controller/metal/live.rb +++ b/actionpack/lib/action_controller/metal/live.rb @@ -86,7 +86,7 @@ module ActionController # Note: SSEs are not currently supported by IE. However, they are supported # by Chrome, Firefox, Opera, and Safari. class SSE - WHITELISTED_OPTIONS = %w( retry event id ) + PERMITTED_OPTIONS = %w( retry event id ) def initialize(stream, options = {}) @stream = stream @@ -111,7 +111,7 @@ module ActionController def perform_write(json, options) current_options = @options.merge(options).stringify_keys - WHITELISTED_OPTIONS.each do |option_name| + PERMITTED_OPTIONS.each do |option_name| if (option_value = current_options[option_name]) @stream.write "#{option_name}: #{option_value}\n" end diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index 2b55b9347c..118da11990 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -11,7 +11,7 @@ module ActionController #:nodoc: # @people = Person.all # end # - # That action implicitly responds to all formats, but formats can also be whitelisted: + # That action implicitly responds to all formats, but formats can also be explicitly enumerated: # # def index # @people = Person.all @@ -105,7 +105,7 @@ module ActionController #:nodoc: # # Mime::Type.register "image/jpg", :jpg # - # Respond to also allows you to specify a common block for different formats by using +any+: + # +respond_to+ also allows you to specify a common block for different formats by using +any+: # # def index # @people = Person.all diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb index 4c2b5120eb..2804a06a58 100644 --- a/actionpack/lib/action_controller/metal/redirecting.rb +++ b/actionpack/lib/action_controller/metal/redirecting.rb @@ -105,7 +105,7 @@ module ActionController when String request.protocol + request.host_with_port + options when Proc - _compute_redirect_to_location request, options.call + _compute_redirect_to_location request, instance_eval(&options) else url_for(options) end.delete("\0\r\n") diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index ea637c8150..cb109c6ad8 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -45,8 +45,8 @@ module ActionController #:nodoc: # the same origin. Note however that any cross-origin third party domain # allowed via {CORS}[https://en.wikipedia.org/wiki/Cross-origin_resource_sharing] # will also be able to create XHR requests. Be sure to check your - # CORS whitelist before disabling forgery protection for XHR. - # + # CORS configuration before disabling forgery protection for XHR. + # # CSRF protection is turned on with the <tt>protect_from_forgery</tt> method. # By default <tt>protect_from_forgery</tt> protects your session with # <tt>:null_session</tt> method, which provides an empty session diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb index 7af29f8dca..a37f08d944 100644 --- a/actionpack/lib/action_controller/metal/strong_parameters.rb +++ b/actionpack/lib/action_controller/metal/strong_parameters.rb @@ -58,7 +58,7 @@ module ActionController # == Action Controller \Parameters # - # Allows you to choose which attributes should be whitelisted for mass updating + # Allows you to choose which attributes should be permitted for mass updating # and thus prevent accidentally exposing that which shouldn't be exposed. # Provides two methods for this purpose: #require and #permit. The former is # used to mark parameters as required. The latter is used to set the parameter @@ -133,6 +133,15 @@ module ActionController # Returns a hash that can be used as the JSON representation for the parameters. ## + # :method: each_key + # + # :call-seq: + # each_key() + # + # Calls block once for each key in the parameters, passing the key. + # If no block is given, an enumerator is returned instead. + + ## # :method: empty? # # :call-seq: @@ -204,7 +213,7 @@ module ActionController # # Returns a new array of the values of the parameters. delegate :keys, :key?, :has_key?, :values, :has_value?, :value?, :empty?, :include?, - :as_json, :to_s, to: :@parameters + :as_json, :to_s, :each_key, to: :@parameters # By default, never raise an UnpermittedParameters exception if these # params are present. The default includes both 'controller' and 'action' @@ -505,7 +514,7 @@ module ActionController # # Note that if you use +permit+ in a key that points to a hash, # it won't allow all the hash. You also need to specify which - # attributes inside the hash should be whitelisted. + # attributes inside the hash should be permitted. # # params = ActionController::Parameters.new({ # person: { @@ -904,15 +913,28 @@ module ActionController PERMITTED_SCALAR_TYPES.any? { |type| value.is_a?(type) } end - def permitted_scalar_filter(params, key) - if has_key?(key) && permitted_scalar?(self[key]) - params[key] = self[key] + # Adds existing keys to the params if their values are scalar. + # + # For example: + # + # puts self.keys #=> ["zipcode(90210i)"] + # params = {} + # + # permitted_scalar_filter(params, "zipcode") + # + # puts params.keys # => ["zipcode"] + def permitted_scalar_filter(params, permitted_key) + permitted_key = permitted_key.to_s + + if has_key?(permitted_key) && permitted_scalar?(self[permitted_key]) + params[permitted_key] = self[permitted_key] end - keys.grep(/\A#{Regexp.escape(key)}\(\d+[if]?\)\z/) do |k| - if permitted_scalar?(self[k]) - params[k] = self[k] - end + each_key do |key| + next unless key =~ /\(\d+[if]?\)\z/ + next unless $~.pre_match == permitted_key + + params[key] = self[key] if permitted_scalar?(self[key]) end end @@ -997,8 +1019,8 @@ module ActionController # # It provides an interface for protecting attributes from end-user # assignment. This makes Action Controller parameters forbidden - # to be used in Active Model mass assignment until they have been - # whitelisted. + # to be used in Active Model mass assignment until they have been explicitly + # enumerated. # # In addition, parameters can be marked as required and flow through a # predefined raise/rescue flow to end up as a <tt>400 Bad Request</tt> with no @@ -1034,7 +1056,7 @@ module ActionController # end # # In order to use <tt>accepts_nested_attributes_for</tt> with Strong \Parameters, you - # will need to specify which nested attributes should be whitelisted. You might want + # will need to specify which nested attributes should be permitted. You might want # to allow +:id+ and +:_destroy+, see ActiveRecord::NestedAttributes for more information. # # class Person @@ -1052,7 +1074,7 @@ module ActionController # private # # def person_params - # # It's mandatory to specify the nested attributes that should be whitelisted. + # # It's mandatory to specify the nested attributes that should be permitted. # # If you use `permit` with just the key that points to the nested attributes hash, # # it will return an empty hash. # params.require(:person).permit(:name, :age, pets_attributes: [ :id, :name, :category ]) diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb index 2d1523f0fc..2b4559c760 100644 --- a/actionpack/lib/action_controller/renderer.rb +++ b/actionpack/lib/action_controller/renderer.rb @@ -81,7 +81,7 @@ module ActionController # * <tt>:html</tt> - Renders the provided HTML safe string, otherwise # performs HTML escape on the string first. Sets the content type as <tt>text/html</tt>. # * <tt>:json</tt> - Renders the provided hash or object in JSON. You don't - # need to call <tt>.to_json<tt> on the object you want to render. + # need to call <tt>.to_json</tt> on the object you want to render. # * <tt>:body</tt> - Renders provided text and sets content type of <tt>text/plain</tt>. # # If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified, the default is diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index d7435fa8df..be129965d1 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -85,10 +85,7 @@ module ActionDispatch if variant.all? { |v| v.is_a?(Symbol) } @variant = ActiveSupport::ArrayInquirer.new(variant) else - raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols. " \ - "For security reasons, never directly set the variant to a user-provided value, " \ - "like params[:variant].to_sym. Check user-provided value against a whitelist first, " \ - "then set the variant: request.variant = :tablet if params[:variant] == 'tablet'" + raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols." end end diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb index 1d58964862..09aab631ed 100644 --- a/actionpack/lib/action_dispatch/http/parameter_filter.rb +++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "active_support/core_ext/object/duplicable" +require "active_support/core_ext/array/extract" module ActionDispatch module Http @@ -38,8 +39,8 @@ module ActionDispatch end end - deep_regexps, regexps = regexps.partition { |r| r.to_s.include?("\\.".freeze) } - deep_strings, strings = strings.partition { |s| s.include?("\\.".freeze) } + deep_regexps = regexps.extract! { |r| r.to_s.include?("\\.".freeze) } + deep_strings = strings.extract! { |s| s.include?("\\.".freeze) } regexps << Regexp.new(strings.join("|".freeze), true) unless strings.empty? deep_regexps << Regexp.new(deep_strings.join("|".freeze), true) unless deep_strings.empty? @@ -55,23 +56,23 @@ module ActionDispatch @blocks = blocks end - def call(original_params, parents = []) - filtered_params = original_params.class.new + def call(params, parents = [], original_params = params) + filtered_params = params.class.new - original_params.each do |key, value| + params.each do |key, value| parents.push(key) if deep_regexps if regexps.any? { |r| key =~ r } value = FILTERED elsif deep_regexps && (joined = parents.join(".")) && deep_regexps.any? { |r| joined =~ r } value = FILTERED elsif value.is_a?(Hash) - value = call(value, parents) + value = call(value, parents, original_params) elsif value.is_a?(Array) - value = value.map { |v| v.is_a?(Hash) ? call(v, parents) : v } + value = value.map { |v| v.is_a?(Hash) ? call(v, parents, original_params) : v } elsif blocks.any? key = key.dup if key.duplicable? value = value.dup if value.duplicable? - blocks.each { |b| b.call(key, value) } + blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) } end parents.pop if deep_regexps 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 1fa0691303..0242b706b2 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb @@ -197,4 +197,7 @@ setupMatchPaths(); setupRouteToggleHelperLinks(); + + // Focus the search input after page has loaded + document.getElementById('search').focus(); </script> diff --git a/actionpack/lib/action_dispatch/request/utils.rb b/actionpack/lib/action_dispatch/request/utils.rb index 0ae464082d..fb0efb9a58 100644 --- a/actionpack/lib/action_dispatch/request/utils.rb +++ b/actionpack/lib/action_dispatch/request/utils.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "active_support/core_ext/hash/indifferent_access" + module ActionDispatch class Request class Utils # :nodoc: diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb index cba49d1a0b..413e524ef6 100644 --- a/actionpack/lib/action_dispatch/routing/inspector.rb +++ b/actionpack/lib/action_dispatch/routing/inspector.rb @@ -83,7 +83,7 @@ module ActionDispatch private def normalize_filter(filter) if filter[:controller] - { controller: /#{filter[:controller].downcase.sub(/_?controller\z/, '').sub('::', '/')}/ } + { controller: /#{filter[:controller].underscore.sub(/_?controller\z/, "")}/ } elsif filter[:grep] { controller: /#{filter[:grep]}/, action: /#{filter[:grep]}/, verb: /#{filter[:grep]}/, name: /#{filter[:grep]}/, path: /#{filter[:grep]}/ } diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index ff325afc54..07e3be4db8 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -553,10 +553,10 @@ module ActionDispatch # # match 'json_only', constraints: { format: 'json' }, via: :get # - # class Whitelist + # class PermitList # def matches?(request) request.remote_ip == '1.2.3.4' end # end - # match 'path', to: 'c#a', constraints: Whitelist.new, via: :get + # match 'path', to: 'c#a', constraints: PermitList.new, via: :get # # See <tt>Scoping#constraints</tt> for more examples with its scope # equivalent. diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb index 8ac50c730d..0b98f27f11 100644 --- a/actionpack/lib/action_dispatch/testing/test_process.rb +++ b/actionpack/lib/action_dispatch/testing/test_process.rb @@ -8,12 +8,12 @@ module ActionDispatch module FixtureFile # 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') + # post :change_avatar, params: { avatar: fixture_file_upload('files/spongebob.png', 'image/png') } # # To upload binary files on Windows, pass <tt>:binary</tt> as the last parameter. # This will not affect other platforms: # - # post :change_avatar, avatar: fixture_file_upload('files/spongebob.png', 'image/png', :binary) + # post :change_avatar, params: { avatar: fixture_file_upload('files/spongebob.png', 'image/png', :binary) } def fixture_file_upload(path, mime_type = nil, binary = false) if self.class.respond_to?(:fixture_path) && self.class.fixture_path && !File.exist?(path) diff --git a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb index fe0e5e368d..974612fb7b 100644 --- a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb +++ b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb @@ -20,7 +20,7 @@ class AlwaysPermittedParametersTest < ActiveSupport::TestCase end end - test "permits parameters that are whitelisted" do + test "allows both explicitly listed and always-permitted parameters" do params = ActionController::Parameters.new( book: { pages: 65 }, format: "json") diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 2959dc3e4d..461e627154 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -5,6 +5,12 @@ require "abstract_unit" class Workshop extend ActiveModel::Naming include ActiveModel::Conversion + + OUT_OF_SCOPE_BLOCK = proc do + raise "Not executed in controller's context" unless RedirectController === self + request.original_url + end + attr_accessor :id def initialize(id) @@ -119,6 +125,10 @@ class RedirectController < ActionController::Base redirect_to proc { { action: "hello_world" } } end + def redirect_to_out_of_scope_block + redirect_to Workshop::OUT_OF_SCOPE_BLOCK + end + def redirect_with_header_break redirect_to "/lol\r\nwat" end @@ -326,6 +336,12 @@ class RedirectTest < ActionController::TestCase assert_redirected_to "http://www.rubyonrails.org/" end + def test_redirect_to_out_of_scope_block + get :redirect_to_out_of_scope_block + assert_response :redirect + assert_redirected_to "http://test.host/redirect/redirect_to_out_of_scope_block" + end + def test_redirect_to_with_block_and_accepted_options with_routing do |set| set.draw do diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index 34ead0a4c0..6637c2cae9 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -1405,8 +1405,7 @@ class CookiesTest < ActionController::TestCase assert_equal "5-2-Stable Chocolate Cookies", cookies.encrypted[:favorite] - freeze_time do - travel 1001.years + travel 1001.years do assert_nil cookies.encrypted[:favorite] end @@ -1422,8 +1421,7 @@ class CookiesTest < ActionController::TestCase assert_equal "5-2-Stable Choco Chip Cookie", cookies.signed[:favorite] - freeze_time do - travel 1001.years + travel 1001.years do assert_nil cookies.signed[:favorite] end @@ -1439,8 +1437,7 @@ class CookiesTest < ActionController::TestCase assert_equal "5-2-Stable Chocolate Cookies", cookies.encrypted[:favorite] - freeze_time do - travel 1001.years + travel 1001.years do assert_nil cookies.encrypted[:favorite] end @@ -1456,8 +1453,7 @@ class CookiesTest < ActionController::TestCase assert_equal "5-2-Stable Choco Chip Cookie", cookies.signed[:favorite] - freeze_time do - travel 1001.years + travel 1001.years do assert_nil cookies.signed[:favorite] end diff --git a/actionpack/test/dispatch/exception_wrapper_test.rb b/actionpack/test/dispatch/exception_wrapper_test.rb index 600280d6b3..668469a01d 100644 --- a/actionpack/test/dispatch/exception_wrapper_test.rb +++ b/actionpack/test/dispatch/exception_wrapper_test.rb @@ -20,6 +20,7 @@ module ActionDispatch setup do @cleaner = ActiveSupport::BacktraceCleaner.new + @cleaner.remove_filters! @cleaner.add_silencer { |line| line !~ /^lib/ } end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 84a2d1f69e..0ac8713527 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -1078,10 +1078,13 @@ class RequestParameterFilter < BaseRequestTest filter_words << lambda { |key, value| value.reverse! if key =~ /bargain/ } + filter_words << lambda { |key, value, original_params| + value.replace("world!") if original_params["barg"]["blah"] == "bar" && key == "hello" + } parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words) - before_filter["barg"] = { :bargain => "gain", "blah" => "bar", "bar" => { "bargain" => { "blah" => "foo" } } } - after_filter["barg"] = { :bargain => "niag", "blah" => "[FILTERED]", "bar" => { "bargain" => { "blah" => "[FILTERED]" } } } + before_filter["barg"] = { :bargain => "gain", "blah" => "bar", "bar" => { "bargain" => { "blah" => "foo", "hello" => "world" } } } + after_filter["barg"] = { :bargain => "niag", "blah" => "[FILTERED]", "bar" => { "bargain" => { "blah" => "[FILTERED]", "hello" => "world!" } } } assert_equal after_filter, parameter_filter.filter(before_filter) end |