aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/http/filter_parameters.rb12
-rw-r--r--actionpack/lib/action_dispatch/http/headers.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb21
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb4
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb7
-rw-r--r--actionpack/lib/action_dispatch/middleware/callbacks.rb11
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/executor.rb19
-rw-r--r--actionpack/lib/action_dispatch/middleware/load_interlock.rb21
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/reloader.rb66
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb22
-rw-r--r--actionpack/lib/action_dispatch/railtie.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing.rb8
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb15
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb57
19 files changed, 157 insertions, 122 deletions
diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb
index 9dcab79c3a..041eca48ca 100644
--- a/actionpack/lib/action_dispatch/http/filter_parameters.rb
+++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb
@@ -4,9 +4,11 @@ module ActionDispatch
module Http
# Allows you to specify sensitive parameters which will be replaced from
# the request log by looking in the query string of the request and all
- # sub-hashes of the params hash to filter. If a block is given, each key and
- # value of the params hash and all sub-hashes is passed to it, the value
- # or key can be replaced using String#replace or similar method.
+ # sub-hashes of the params hash to filter. Filtering only certain sub-keys
+ # from a hash is possible by using the dot notation: 'credit_card.number'.
+ # If a block is given, each key and value of the params hash and all
+ # sub-hashes is passed to it, the value or key can be replaced using
+ # String#replace or similar method.
#
# env["action_dispatch.parameter_filter"] = [:password]
# => replaces the value to all keys matching /password/i with "[FILTERED]"
@@ -14,6 +16,10 @@ module ActionDispatch
# env["action_dispatch.parameter_filter"] = [:foo, "bar"]
# => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
#
+ # env["action_dispatch.parameter_filter"] = [ "credit_card.code" ]
+ # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
+ # change { file: { code: "xxxx"} }
+ #
# env["action_dispatch.parameter_filter"] = -> (k, v) do
# v.reverse! if k =~ /secret/i
# end
diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb
index 8e899174c6..5c3b7245d6 100644
--- a/actionpack/lib/action_dispatch/http/headers.rb
+++ b/actionpack/lib/action_dispatch/http/headers.rb
@@ -115,7 +115,7 @@ module ActionDispatch
private
- # Converts a HTTP header name to an environment variable name if it is
+ # Converts an HTTP header name to an environment variable name if it is
# not contained within the headers hash.
def env_name(key)
key = key.to_s
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index cca7376ffa..ff5031d7d5 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -1,22 +1,31 @@
module ActionDispatch
module Http
module Parameters
+ extend ActiveSupport::Concern
+
PARAMETERS_KEY = 'action_dispatch.request.path_parameters'
DEFAULT_PARSERS = {
- Mime[:json] => lambda { |raw_post|
+ Mime[:json].symbol => -> (raw_post) {
data = ActiveSupport::JSON.decode(raw_post)
data.is_a?(Hash) ? data : {:_json => data}
}
}
- def self.included(klass)
- class << klass
- attr_accessor :parameter_parsers
+ included do
+ class << self
+ attr_reader :parameter_parsers
end
- klass.parameter_parsers = DEFAULT_PARSERS
+ self.parameter_parsers = DEFAULT_PARSERS
end
+
+ module ClassMethods
+ def parameter_parsers=(parsers) # :nodoc:
+ @parameter_parsers = parsers.transform_keys { |key| key.respond_to?(:symbol) ? key.symbol : key }
+ end
+ end
+
# Returns both GET and POST \parameters in a single hash.
def parameters
params = get_header("action_dispatch.request.parameters")
@@ -51,7 +60,7 @@ module ActionDispatch
def parse_formatted_parameters(parsers)
return yield if content_length.zero?
- strategy = parsers.fetch(content_mime_type) { return yield }
+ strategy = parsers.fetch(content_mime_type.symbol) { return yield }
begin
strategy.call(raw_post)
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 5427425ef7..316a9f08b7 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -403,6 +403,10 @@ module ActionDispatch
def commit_flash
end
+ def ssl?
+ super || scheme == 'wss'.freeze
+ end
+
private
def check_method(name)
HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS[0...-1].join(', ')}, and #{HTTP_METHODS[-1]}")
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
index 35c2b1b86e..cfd6681dd1 100644
--- a/actionpack/lib/action_dispatch/journey/route.rb
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -3,7 +3,7 @@ module ActionDispatch
class Route # :nodoc:
attr_reader :app, :path, :defaults, :name, :precedence
- attr_reader :constraints
+ attr_reader :constraints, :internal
alias :conditions :constraints
module VerbMatchers
@@ -55,7 +55,7 @@ module ActionDispatch
##
# +path+ is a path constraint.
# +constraints+ is a hash of constraints to be applied to this route.
- def initialize(name, app, path, constraints, required_defaults, defaults, request_method_match, precedence)
+ def initialize(name, app, path, constraints, required_defaults, defaults, request_method_match, precedence, internal = false)
@name = name
@app = app
@path = path
@@ -70,6 +70,7 @@ module ActionDispatch
@decorated_ast = nil
@precedence = precedence
@path_formatter = @path.build_formatter
+ @internal = internal
end
def ast
@@ -81,7 +82,7 @@ module ActionDispatch
end
def requirements # :nodoc:
- # needed for rails `rake routes`
+ # needed for rails `rails routes`
@defaults.merge(path.requirements).delete_if { |_,v|
/.+?/ == v
}
diff --git a/actionpack/lib/action_dispatch/middleware/callbacks.rb b/actionpack/lib/action_dispatch/middleware/callbacks.rb
index f80df78582..c782779b34 100644
--- a/actionpack/lib/action_dispatch/middleware/callbacks.rb
+++ b/actionpack/lib/action_dispatch/middleware/callbacks.rb
@@ -7,7 +7,16 @@ module ActionDispatch
define_callbacks :call
class << self
- delegate :to_prepare, :to_cleanup, :to => "ActionDispatch::Reloader"
+ def to_prepare(*args, &block)
+ ActiveSupport::Reloader.to_prepare(*args, &block)
+ end
+
+ def to_cleanup(*args, &block)
+ ActiveSupport::Reloader.to_complete(*args, &block)
+ end
+
+ deprecate to_prepare: 'use ActiveSupport::Reloader.to_prepare instead',
+ to_cleanup: 'use ActiveSupport::Reloader.to_complete instead'
def before(*args, &block)
set_callback(:call, :before, *args, &block)
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 3b61824cc9..59edc66086 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -1,4 +1,3 @@
-require 'action_controller/metal/exceptions'
require 'active_support/core_ext/module/attribute_accessors'
require 'rack/utils'
diff --git a/actionpack/lib/action_dispatch/middleware/executor.rb b/actionpack/lib/action_dispatch/middleware/executor.rb
new file mode 100644
index 0000000000..06245b403b
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/executor.rb
@@ -0,0 +1,19 @@
+require 'rack/body_proxy'
+
+module ActionDispatch
+ class Executor
+ def initialize(app, executor)
+ @app, @executor = app, executor
+ end
+
+ def call(env)
+ state = @executor.run!
+ begin
+ response = @app.call(env)
+ returned = response << ::Rack::BodyProxy.new(response.pop) { state.complete! }
+ ensure
+ state.complete! unless returned
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/middleware/load_interlock.rb b/actionpack/lib/action_dispatch/middleware/load_interlock.rb
deleted file mode 100644
index 07f498319c..0000000000
--- a/actionpack/lib/action_dispatch/middleware/load_interlock.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'active_support/dependencies'
-require 'rack/body_proxy'
-
-module ActionDispatch
- class LoadInterlock
- def initialize(app)
- @app = app
- end
-
- def call(env)
- interlock = ActiveSupport::Dependencies.interlock
- interlock.start_running
- response = @app.call(env)
- body = Rack::BodyProxy.new(response[2]) { interlock.done_running }
- response[2] = body
- response
- ensure
- interlock.done_running unless body
- end
- end
-end
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index c2a4f46e67..5841c978af 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -37,6 +37,7 @@ module ActionDispatch
# The +parsers+ argument can take Hash of parsers where key is identifying
# content mime type, and value is a lambda that is going to process data.
def self.new(app, parsers = {})
+ parsers = parsers.transform_keys { |key| key.respond_to?(:symbol) ? key.symbol : key }
ActionDispatch::Request.parameter_parsers = ActionDispatch::Request::DEFAULT_PARSERS.merge(parsers)
app
end
diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb
index af9a29eb07..112bde6596 100644
--- a/actionpack/lib/action_dispatch/middleware/reloader.rb
+++ b/actionpack/lib/action_dispatch/middleware/reloader.rb
@@ -23,74 +23,32 @@ module ActionDispatch
# middleware stack, but are executed only when <tt>ActionDispatch::Reloader.prepare!</tt>
# or <tt>ActionDispatch::Reloader.cleanup!</tt> are called manually.
#
- class Reloader
- include ActiveSupport::Callbacks
- include ActiveSupport::Deprecation::Reporting
-
- define_callbacks :prepare
- define_callbacks :cleanup
-
- # Add a prepare callback. Prepare callbacks are run before each request, prior
- # to ActionDispatch::Callback's before callbacks.
+ class Reloader < Executor
def self.to_prepare(*args, &block)
- unless block_given?
- warn "to_prepare without a block is deprecated. Please use a block"
- end
- set_callback(:prepare, *args, &block)
+ ActiveSupport::Reloader.to_prepare(*args, &block)
end
- # Add a cleanup callback. Cleanup callbacks are run after each request is
- # complete (after #close is called on the response body).
def self.to_cleanup(*args, &block)
- unless block_given?
- warn "to_cleanup without a block is deprecated. Please use a block"
- end
- set_callback(:cleanup, *args, &block)
+ ActiveSupport::Reloader.to_complete(*args, &block)
end
- # Execute all prepare callbacks.
def self.prepare!
- new(nil).prepare!
+ default_reloader.prepare!
end
- # Execute all cleanup callbacks.
def self.cleanup!
- new(nil).cleanup!
- end
-
- def initialize(app, condition=nil)
- @app = app
- @condition = condition || lambda { true }
- @validated = true
+ default_reloader.reload!
end
- def call(env)
- @validated = @condition.call
- prepare!
-
- response = @app.call(env)
- response[2] = ::Rack::BodyProxy.new(response[2]) { cleanup! }
+ class << self
+ attr_accessor :default_reloader # :nodoc:
- response
- rescue Exception
- cleanup!
- raise
+ deprecate to_prepare: 'use ActiveSupport::Reloader.to_prepare instead',
+ to_cleanup: 'use ActiveSupport::Reloader.to_complete instead',
+ prepare!: 'use Rails.application.reloader.prepare! instead',
+ cleanup!: 'use Rails.application.reloader.reload! instead of cleanup + prepare'
end
- def prepare! #:nodoc:
- run_callbacks :prepare if validated?
- end
-
- def cleanup! #:nodoc:
- run_callbacks :cleanup if validated?
- ensure
- @validated = true
- end
-
- private
-
- def validated? #:nodoc:
- @validated
- end
+ self.default_reloader = ActiveSupport::Reloader
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 735b5939dd..ab3077b308 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -23,7 +23,7 @@ module ActionDispatch
# preload lists is `18.weeks`.
# * `subdomains`: Set to `true` to tell the browser to apply these settings
# to all subdomains. This protects your cookies from interception by a
- # vulnerable site on a subdomain. Defaults to `false`.
+ # vulnerable site on a subdomain. Defaults to `true`.
# * `preload`: Advertise that this site may be included in browsers'
# preloaded HSTS lists. HSTS protects your site on every visit *except the
# first visit* since it hasn't seen your HSTS header yet. To close this
@@ -34,6 +34,10 @@ module ActionDispatch
# 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 }`.
+ #
+ # Requests can opt-out of redirection with `exclude`:
+ #
+ # config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } }
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.
@@ -49,14 +53,26 @@ module ActionDispatch
if options[:host] || options[:port]
ActiveSupport::Deprecation.warn <<-end_warning.strip_heredoc
The `:host` and `:port` options are moving within `:redirect`:
- `config.ssl_options = { redirect: { host: …, port: … }}`.
+ `config.ssl_options = { redirect: { host: …, port: … } }`.
end_warning
@redirect = options.slice(:host, :port)
else
@redirect = redirect
end
+ @exclude = @redirect && @redirect[:exclude] || proc { !@redirect }
@secure_cookies = secure_cookies
+
+ if hsts != true && hsts != false && hsts[:subdomains].nil?
+ hsts[:subdomains] = false
+
+ ActiveSupport::Deprecation.warn <<-end_warning.strip_heredoc
+ In Rails 5.1, The `:subdomains` option of HSTS config will be treated as true if
+ unspecified. Set `config.ssl_options = { hsts: { subdomains: false } }` to opt out
+ of this behavior.
+ end_warning
+ end
+
@hsts_header = build_hsts_header(normalize_hsts_options(hsts))
end
@@ -69,7 +85,7 @@ module ActionDispatch
flag_cookies_as_secure! headers if @secure_cookies
end
else
- return redirect_to_https request if @redirect
+ return redirect_to_https request unless @exclude.call(request)
@app.call(env)
end
end
diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb
index ddeea24bb3..e9e6a2e597 100644
--- a/actionpack/lib/action_dispatch/railtie.rb
+++ b/actionpack/lib/action_dispatch/railtie.rb
@@ -39,6 +39,8 @@ module ActionDispatch
config.action_dispatch.always_write_cookie = Rails.env.development? if config.action_dispatch.always_write_cookie.nil?
ActionDispatch::Cookies::CookieJar.always_write_cookie = config.action_dispatch.always_write_cookie
+ ActionDispatch::Reloader.default_reloader = app.reloader
+
ActionDispatch.test_app = app
end
end
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 79f9283f83..79d2f1f13c 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -73,14 +73,14 @@ module ActionDispatch
# get 'post/:id' => 'posts#show'
# post 'post/:id' => 'posts#create_comment'
#
+ # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
+ # URL will route to the <tt>show</tt> action.
+ #
# If your route needs to respond to more than one HTTP method (or all methods) then using the
# <tt>:via</tt> option on <tt>match</tt> is preferable.
#
# match 'post/:id' => 'posts#show', via: [:get, :post]
#
- # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
- # URL will route to the <tt>show</tt> action.
- #
# == Named routes
#
# Routes can be named by passing an <tt>:as</tt> option,
@@ -159,7 +159,7 @@ module ActionDispatch
#
# controller 'geocode' do
# get 'geocode/:postalcode' => :show, constraints: {
- # postalcode: /# Postcode format
+ # postalcode: /# Postalcode format
# \d{5} #Prefix
# (-\d{4})? #Suffix
# /x
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index 983f1daeb3..5d30a545a2 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -41,7 +41,7 @@ module ActionDispatch
end
def internal?
- controller.to_s =~ %r{\Arails/(info|mailers|welcome)}
+ internal
end
def engine?
@@ -51,7 +51,7 @@ module ActionDispatch
##
# This class is just used for displaying route information when someone
- # executes `rake routes` or looks at the RoutingError page.
+ # executes `rails routes` or looks at the RoutingError page.
# People should not use this class.
class RoutesInspector # :nodoc:
def initialize(routes)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index afbaa45d20..16b430c36e 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -107,6 +107,7 @@ module ActionDispatch
@ast = ast
@anchor = anchor
@via = via
+ @internal = options[:internal]
path_params = ast.find_all(&:symbol?).map(&:to_sym)
@@ -148,7 +149,8 @@ module ActionDispatch
required_defaults,
defaults,
request_method,
- precedence)
+ precedence,
+ @internal)
route
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 310e98f584..85f202b823 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -513,6 +513,21 @@ module ActionDispatch
route = @set.add_route(name, mapping)
named_routes[name] = route if name
+
+ if route.segment_keys.include?(:controller)
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Using a dynamic :controller segment in a route is deprecated and
+ will be removed in Rails 5.1
+ MSG
+ end
+
+ if route.segment_keys.include?(:action)
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Using a dynamic :action segment in a route is deprecated and
+ will be removed in Rails 5.1
+ MSG
+ end
+
route
end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index e7af27463c..44ad2c10d8 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -117,7 +117,7 @@ module ActionDispatch
# # Tests a route, providing a defaults hash
# assert_routing 'controller/action/9', {id: "9", item: "square"}, {controller: "controller", action: "action"}, {}, {item: "square"}
#
- # # Tests a route with a HTTP method
+ # # Tests a route with an HTTP method
# assert_routing({ method: 'put', path: '/product/321' }, { controller: "product", action: "update", id: "321" })
def assert_routing(path, options, defaults={}, extras={}, message=nil)
assert_recognizes(options, path, extras, message)
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index f4534b4173..60c562d7cd 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -735,34 +735,49 @@ module ActionDispatch
# Consult the Rails Testing Guide for more.
class IntegrationTest < ActiveSupport::TestCase
- include Integration::Runner
- include ActionController::TemplateAssertions
- include ActionDispatch::Routing::UrlFor
+ module UrlOptions
+ extend ActiveSupport::Concern
+ def url_options
+ integration_session.url_options
+ end
+ end
- @@app = nil
+ module Behavior
+ extend ActiveSupport::Concern
- def self.app
- @@app || ActionDispatch.test_app
- end
+ include Integration::Runner
+ include ActionController::TemplateAssertions
- def self.app=(app)
- @@app = app
- end
+ included do
+ include ActionDispatch::Routing::UrlFor
+ include UrlOptions # don't let UrlFor override the url_options method
+ ActiveSupport.run_load_hooks(:action_dispatch_integration_test, self)
+ @@app = nil
+ end
- def app
- super || self.class.app
- end
+ module ClassMethods
+ def app
+ defined?(@@app) ? @@app : ActionDispatch.test_app
+ end
- def url_options
- integration_session.url_options
- end
+ def app=(app)
+ @@app = app
+ end
- def document_root_element
- html_document.root
- end
+ def register_encoder(*args)
+ Integration::Session::RequestEncoder.register_encoder(*args)
+ end
+ end
- def self.register_encoder(*args)
- Integration::Session::RequestEncoder.register_encoder(*args)
+ def app
+ super || self.class.app
+ end
+
+ def document_root_element
+ html_document.root
+ end
end
+
+ include Behavior
end
end