actionpack 5.2.4.4 → 6.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +264 -322
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/base.rb +38 -4
- data/lib/abstract_controller/caching.rb +1 -1
- data/lib/abstract_controller/caching/fragments.rb +6 -22
- data/lib/abstract_controller/callbacks.rb +14 -2
- data/lib/abstract_controller/collector.rb +1 -2
- data/lib/abstract_controller/helpers.rb +106 -90
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -1
- data/lib/abstract_controller/rendering.rb +9 -9
- data/lib/abstract_controller/translation.rb +11 -5
- data/lib/action_controller.rb +7 -4
- data/lib/action_controller/api.rb +4 -3
- data/lib/action_controller/base.rb +6 -9
- data/lib/action_controller/caching.rb +1 -3
- data/lib/action_controller/log_subscriber.rb +10 -7
- data/lib/action_controller/metal.rb +10 -8
- data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
- data/lib/action_controller/metal/conditional_get.rb +19 -5
- data/lib/action_controller/metal/content_security_policy.rb +1 -2
- data/lib/action_controller/metal/cookies.rb +3 -1
- data/lib/action_controller/metal/data_streaming.rb +6 -7
- data/lib/action_controller/metal/default_headers.rb +17 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +3 -5
- data/lib/action_controller/metal/exceptions.rb +56 -2
- data/lib/action_controller/metal/flash.rb +5 -5
- data/lib/action_controller/metal/head.rb +7 -4
- data/lib/action_controller/metal/helpers.rb +14 -5
- data/lib/action_controller/metal/http_authentication.rb +24 -23
- data/lib/action_controller/metal/implicit_render.rb +5 -15
- data/lib/action_controller/metal/instrumentation.rb +13 -14
- data/lib/action_controller/metal/live.rb +30 -32
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +19 -4
- data/lib/action_controller/metal/parameter_encoding.rb +35 -4
- data/lib/action_controller/metal/params_wrapper.rb +31 -22
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +6 -6
- data/lib/action_controller/metal/renderers.rb +4 -4
- data/lib/action_controller/metal/rendering.rb +8 -3
- data/lib/action_controller/metal/request_forgery_protection.rb +62 -34
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/streaming.rb +0 -1
- data/lib/action_controller/metal/strong_parameters.rb +167 -58
- data/lib/action_controller/metal/url_for.rb +1 -1
- data/lib/action_controller/railties/helpers.rb +1 -1
- data/lib/action_controller/renderer.rb +37 -13
- data/lib/action_controller/template_assertions.rb +1 -1
- data/lib/action_controller/test_case.rb +70 -65
- data/lib/action_dispatch.rb +9 -3
- data/lib/action_dispatch/http/cache.rb +26 -21
- data/lib/action_dispatch/http/content_disposition.rb +45 -0
- data/lib/action_dispatch/http/content_security_policy.rb +33 -19
- data/lib/action_dispatch/http/filter_parameters.rb +9 -8
- data/lib/action_dispatch/http/filter_redirect.rb +2 -3
- data/lib/action_dispatch/http/headers.rb +4 -4
- data/lib/action_dispatch/http/mime_negotiation.rb +26 -13
- data/lib/action_dispatch/http/mime_type.rb +42 -23
- data/lib/action_dispatch/http/parameters.rb +14 -23
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/request.rb +45 -22
- data/lib/action_dispatch/http/response.rb +45 -25
- data/lib/action_dispatch/http/upload.rb +9 -1
- data/lib/action_dispatch/http/url.rb +82 -82
- data/lib/action_dispatch/journey.rb +0 -2
- data/lib/action_dispatch/journey/formatter.rb +54 -30
- data/lib/action_dispatch/journey/gtg/builder.rb +22 -37
- data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -5
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
- data/lib/action_dispatch/journey/nodes/node.rb +13 -11
- data/lib/action_dispatch/journey/parser.rb +13 -13
- data/lib/action_dispatch/journey/parser.y +1 -1
- data/lib/action_dispatch/journey/path/pattern.rb +19 -21
- data/lib/action_dispatch/journey/route.rb +10 -20
- data/lib/action_dispatch/journey/router.rb +26 -34
- data/lib/action_dispatch/journey/router/utils.rb +14 -12
- data/lib/action_dispatch/journey/routes.rb +0 -2
- data/lib/action_dispatch/journey/scanner.rb +10 -4
- data/lib/action_dispatch/journey/visitors.rb +1 -4
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -4
- data/lib/action_dispatch/middleware/cookies.rb +128 -109
- data/lib/action_dispatch/middleware/debug_exceptions.rb +43 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
- data/lib/action_dispatch/middleware/debug_view.rb +66 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -30
- data/lib/action_dispatch/middleware/flash.rb +1 -1
- data/lib/action_dispatch/middleware/host_authorization.rb +121 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +14 -16
- data/lib/action_dispatch/middleware/request_id.rb +5 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +3 -9
- data/lib/action_dispatch/middleware/show_exceptions.rb +3 -2
- data/lib/action_dispatch/middleware/ssl.rb +20 -15
- data/lib/action_dispatch/middleware/stack.rb +56 -2
- data/lib/action_dispatch/middleware/static.rb +153 -93
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +6 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +104 -8
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +24 -1
- data/lib/action_dispatch/railtie.rb +8 -2
- data/lib/action_dispatch/request/session.rb +10 -9
- data/lib/action_dispatch/request/utils.rb +26 -2
- data/lib/action_dispatch/routing.rb +21 -20
- data/lib/action_dispatch/routing/inspector.rb +100 -52
- data/lib/action_dispatch/routing/mapper.rb +155 -103
- data/lib/action_dispatch/routing/polymorphic_routes.rb +13 -15
- data/lib/action_dispatch/routing/redirection.rb +3 -3
- data/lib/action_dispatch/routing/route_set.rb +71 -69
- data/lib/action_dispatch/routing/url_for.rb +2 -2
- data/lib/action_dispatch/system_test_case.rb +54 -11
- data/lib/action_dispatch/system_testing/browser.rb +53 -16
- data/lib/action_dispatch/system_testing/driver.rb +11 -3
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +49 -7
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -10
- data/lib/action_dispatch/testing/assertion_response.rb +0 -1
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +4 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +20 -8
- data/lib/action_dispatch/testing/integration.rb +61 -28
- data/lib/action_dispatch/testing/request_encoder.rb +2 -2
- data/lib/action_dispatch/testing/test_process.rb +29 -4
- data/lib/action_dispatch/testing/test_request.rb +3 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -32
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/gem_version.rb +4 -4
- metadata +38 -26
- data/lib/action_controller/metal/force_ssl.rb +0 -99
- data/lib/action_dispatch/http/parameter_filter.rb +0 -86
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -49
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -120
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -7,7 +7,7 @@ module AbstractController
|
|
7
7
|
Module.new do
|
8
8
|
define_method(:inherited) do |klass|
|
9
9
|
super(klass)
|
10
|
-
if namespace = klass.
|
10
|
+
if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
|
11
11
|
klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
|
12
12
|
else
|
13
13
|
klass.include(routes.url_helpers(include_path_helpers))
|
@@ -28,6 +28,7 @@ module AbstractController
|
|
28
28
|
else
|
29
29
|
_set_rendered_content_type rendered_format
|
30
30
|
end
|
31
|
+
_set_vary_header
|
31
32
|
self.response_body = rendered_body
|
32
33
|
end
|
33
34
|
|
@@ -55,20 +56,16 @@ module AbstractController
|
|
55
56
|
Mime[:text]
|
56
57
|
end
|
57
58
|
|
58
|
-
DEFAULT_PROTECTED_INSTANCE_VARIABLES =
|
59
|
-
@_action_name @_response_body @_formats @_prefixes
|
60
|
-
)
|
59
|
+
DEFAULT_PROTECTED_INSTANCE_VARIABLES = %i(@_action_name @_response_body @_formats @_prefixes)
|
61
60
|
|
62
61
|
# This method should return a hash with assigns.
|
63
62
|
# You can overwrite this configuration per controller.
|
64
63
|
def view_assigns
|
65
|
-
|
66
|
-
variables = instance_variables
|
64
|
+
variables = instance_variables - _protected_ivars
|
67
65
|
|
68
|
-
variables.
|
69
|
-
variables.each_with_object({}) { |name, hash|
|
66
|
+
variables.each_with_object({}) do |name, hash|
|
70
67
|
hash[name.slice(1, name.length)] = instance_variable_get(name)
|
71
|
-
|
68
|
+
end
|
72
69
|
end
|
73
70
|
|
74
71
|
private
|
@@ -109,6 +106,9 @@ module AbstractController
|
|
109
106
|
def _set_html_content_type # :nodoc:
|
110
107
|
end
|
111
108
|
|
109
|
+
def _set_vary_header # :nodoc:
|
110
|
+
end
|
111
|
+
|
112
112
|
def _set_rendered_content_type(format) # :nodoc:
|
113
113
|
end
|
114
114
|
|
@@ -120,7 +120,7 @@ module AbstractController
|
|
120
120
|
options
|
121
121
|
end
|
122
122
|
|
123
|
-
def _protected_ivars
|
123
|
+
def _protected_ivars
|
124
124
|
DEFAULT_PROTECTED_INSTANCE_VARIABLES
|
125
125
|
end
|
126
126
|
end
|
@@ -1,7 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
4
|
+
|
3
5
|
module AbstractController
|
4
6
|
module Translation
|
7
|
+
mattr_accessor :raise_on_missing_translations, default: false
|
8
|
+
|
5
9
|
# Delegates to <tt>I18n.translate</tt>. Also aliased as <tt>t</tt>.
|
6
10
|
#
|
7
11
|
# When the given key starts with a period, it will be scoped by the current
|
@@ -10,21 +14,23 @@ module AbstractController
|
|
10
14
|
# <tt>I18n.translate("people.index.foo")</tt>. This makes it less repetitive
|
11
15
|
# to translate many keys within the same controller / action and gives you a
|
12
16
|
# simple framework for scoping them consistently.
|
13
|
-
def translate(key, options
|
14
|
-
if key
|
17
|
+
def translate(key, **options)
|
18
|
+
if key&.start_with?(".")
|
15
19
|
path = controller_path.tr("/", ".")
|
16
20
|
defaults = [:"#{path}#{key}"]
|
17
21
|
defaults << options[:default] if options[:default]
|
18
22
|
options[:default] = defaults.flatten
|
19
23
|
key = "#{path}.#{action_name}#{key}"
|
20
24
|
end
|
21
|
-
|
25
|
+
|
26
|
+
i18n_raise = options.fetch(:raise, self.raise_on_missing_translations)
|
27
|
+
I18n.translate(key, **options, raise: i18n_raise)
|
22
28
|
end
|
23
29
|
alias :t :translate
|
24
30
|
|
25
31
|
# Delegates to <tt>I18n.localize</tt>. Also aliased as <tt>l</tt>.
|
26
|
-
def localize(
|
27
|
-
I18n.localize(
|
32
|
+
def localize(object, **options)
|
33
|
+
I18n.localize(object, **options)
|
28
34
|
end
|
29
35
|
alias :l :localize
|
30
36
|
end
|
data/lib/action_controller.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/rails"
|
4
3
|
require "abstract_controller"
|
5
4
|
require "action_dispatch"
|
6
|
-
require "action_controller/metal/live"
|
7
5
|
require "action_controller/metal/strong_parameters"
|
8
6
|
|
9
7
|
module ActionController
|
@@ -12,7 +10,6 @@ module ActionController
|
|
12
10
|
autoload :API
|
13
11
|
autoload :Base
|
14
12
|
autoload :Metal
|
15
|
-
autoload :Middleware
|
16
13
|
autoload :Renderer
|
17
14
|
autoload :FormBuilder
|
18
15
|
|
@@ -21,20 +18,26 @@ module ActionController
|
|
21
18
|
end
|
22
19
|
|
23
20
|
autoload_under "metal" do
|
21
|
+
eager_autoload do
|
22
|
+
autoload :Live
|
23
|
+
end
|
24
|
+
|
24
25
|
autoload :ConditionalGet
|
25
26
|
autoload :ContentSecurityPolicy
|
26
27
|
autoload :Cookies
|
27
28
|
autoload :DataStreaming
|
29
|
+
autoload :DefaultHeaders
|
28
30
|
autoload :EtagWithTemplateDigest
|
29
31
|
autoload :EtagWithFlash
|
32
|
+
autoload :PermissionsPolicy
|
30
33
|
autoload :Flash
|
31
|
-
autoload :ForceSSL
|
32
34
|
autoload :Head
|
33
35
|
autoload :Helpers
|
34
36
|
autoload :HttpAuthentication
|
35
37
|
autoload :BasicImplicitRender
|
36
38
|
autoload :ImplicitRender
|
37
39
|
autoload :Instrumentation
|
40
|
+
autoload :Logging
|
38
41
|
autoload :MimeResponds
|
39
42
|
autoload :ParamsWrapper
|
40
43
|
autoload :Redirecting
|
@@ -12,7 +12,7 @@ module ActionController
|
|
12
12
|
#
|
13
13
|
# An API Controller is different from a normal controller in the sense that
|
14
14
|
# by default it doesn't include a number of features that are usually required
|
15
|
-
# by browser access only: layouts and templates rendering,
|
15
|
+
# by browser access only: layouts and templates rendering,
|
16
16
|
# flash, assets, and so on. This makes the entire controller stack thinner,
|
17
17
|
# suitable for API applications. It doesn't mean you won't have such
|
18
18
|
# features if you need them: they're all available for you to include in
|
@@ -93,7 +93,7 @@ module ActionController
|
|
93
93
|
# the ones passed as arguments:
|
94
94
|
#
|
95
95
|
# class MyAPIBaseController < ActionController::Metal
|
96
|
-
# ActionController::API.without_modules(:
|
96
|
+
# ActionController::API.without_modules(:UrlFor).each do |left|
|
97
97
|
# include left
|
98
98
|
# end
|
99
99
|
# end
|
@@ -120,8 +120,9 @@ module ActionController
|
|
120
120
|
BasicImplicitRender,
|
121
121
|
StrongParameters,
|
122
122
|
|
123
|
-
ForceSSL,
|
124
123
|
DataStreaming,
|
124
|
+
DefaultHeaders,
|
125
|
+
Logging,
|
125
126
|
|
126
127
|
# Before callbacks should also be executed as early as possible, so
|
127
128
|
# also include them at the bottom.
|
@@ -78,7 +78,7 @@ module ActionController
|
|
78
78
|
#
|
79
79
|
# You can retrieve it again through the same hash:
|
80
80
|
#
|
81
|
-
# Hello #{session[:person]}
|
81
|
+
# "Hello #{session[:person]}"
|
82
82
|
#
|
83
83
|
# For removing objects from the session, you can either assign a single key to +nil+:
|
84
84
|
#
|
@@ -226,12 +226,14 @@ module ActionController
|
|
226
226
|
FormBuilder,
|
227
227
|
RequestForgeryProtection,
|
228
228
|
ContentSecurityPolicy,
|
229
|
-
|
229
|
+
PermissionsPolicy,
|
230
230
|
Streaming,
|
231
231
|
DataStreaming,
|
232
232
|
HttpAuthentication::Basic::ControllerMethods,
|
233
233
|
HttpAuthentication::Digest::ControllerMethods,
|
234
234
|
HttpAuthentication::Token::ControllerMethods,
|
235
|
+
DefaultHeaders,
|
236
|
+
Logging,
|
235
237
|
|
236
238
|
# Before callbacks should also be executed as early as possible, so
|
237
239
|
# also include them at the bottom.
|
@@ -260,15 +262,10 @@ module ActionController
|
|
260
262
|
@_view_renderer @_lookup_context @_routes @_view_runtime @_db_runtime @_helper_proxy
|
261
263
|
)
|
262
264
|
|
263
|
-
def _protected_ivars
|
265
|
+
def _protected_ivars
|
264
266
|
PROTECTED_IVARS
|
265
267
|
end
|
266
|
-
|
267
|
-
def self.make_response!(request)
|
268
|
-
ActionDispatch::Response.create.tap do |res|
|
269
|
-
res.request = request
|
270
|
-
end
|
271
|
-
end
|
268
|
+
private :_protected_ivars
|
272
269
|
|
273
270
|
ActiveSupport.run_load_hooks(:action_controller_base, self)
|
274
271
|
ActiveSupport.run_load_hooks(:action_controller, self)
|
@@ -22,7 +22,6 @@ module ActionController
|
|
22
22
|
# config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new('localhost:11211')
|
23
23
|
# config.action_controller.cache_store = MyOwnStore.new('parameter')
|
24
24
|
module Caching
|
25
|
-
extend ActiveSupport::Autoload
|
26
25
|
extend ActiveSupport::Concern
|
27
26
|
|
28
27
|
included do
|
@@ -30,7 +29,6 @@ module ActionController
|
|
30
29
|
end
|
31
30
|
|
32
31
|
private
|
33
|
-
|
34
32
|
def instrument_payload(key)
|
35
33
|
{
|
36
34
|
controller: controller_name,
|
@@ -40,7 +38,7 @@ module ActionController
|
|
40
38
|
end
|
41
39
|
|
42
40
|
def instrument_name
|
43
|
-
"action_controller"
|
41
|
+
"action_controller"
|
44
42
|
end
|
45
43
|
end
|
46
44
|
end
|
@@ -11,6 +11,7 @@ module ActionController
|
|
11
11
|
params = payload[:params].except(*INTERNAL_PARAMS)
|
12
12
|
format = payload[:format]
|
13
13
|
format = format.to_s.upcase if format.is_a?(Symbol)
|
14
|
+
format = "*/*" if format.nil?
|
14
15
|
|
15
16
|
info "Processing by #{payload[:controller]}##{payload[:action]} as #{format}"
|
16
17
|
info " Parameters: #{params.inspect}" unless params.empty?
|
@@ -18,16 +19,18 @@ module ActionController
|
|
18
19
|
|
19
20
|
def process_action(event)
|
20
21
|
info do
|
21
|
-
payload
|
22
|
+
payload = event.payload
|
22
23
|
additions = ActionController::Base.log_process_action(payload)
|
23
|
-
|
24
24
|
status = payload[:status]
|
25
|
-
|
26
|
-
|
25
|
+
|
26
|
+
if status.nil? && (exception_class_name = payload[:exception].first)
|
27
27
|
status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
|
28
28
|
end
|
29
|
-
|
30
|
-
|
29
|
+
|
30
|
+
additions << "Allocations: #{event.allocations}"
|
31
|
+
|
32
|
+
message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
|
33
|
+
message << " (#{additions.join(" | ")})"
|
31
34
|
message << "\n\n" if defined?(Rails.env) && Rails.env.development?
|
32
35
|
|
33
36
|
message
|
@@ -53,7 +56,7 @@ module ActionController
|
|
53
56
|
def unpermitted_parameters(event)
|
54
57
|
debug do
|
55
58
|
unpermitted_keys = event.payload[:keys]
|
56
|
-
"Unpermitted parameter#{'s' if unpermitted_keys.size > 1}: #{unpermitted_keys.map { |e| ":#{e}" }.join(", ")}"
|
59
|
+
color("Unpermitted parameter#{'s' if unpermitted_keys.size > 1}: #{unpermitted_keys.map { |e| ":#{e}" }.join(", ")}", RED)
|
57
60
|
end
|
58
61
|
end
|
59
62
|
|
@@ -35,7 +35,6 @@ module ActionController
|
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
38
|
-
|
39
38
|
INCLUDE = ->(list, action) { list.include? action }
|
40
39
|
EXCLUDE = ->(list, action) { !list.include? action }
|
41
40
|
NULL = ->(list, action) { true }
|
@@ -127,7 +126,7 @@ module ActionController
|
|
127
126
|
# ==== Returns
|
128
127
|
# * <tt>string</tt>
|
129
128
|
def self.controller_name
|
130
|
-
@controller_name ||= name.demodulize.
|
129
|
+
@controller_name ||= (name.demodulize.delete_suffix("Controller").underscore unless anonymous?)
|
131
130
|
end
|
132
131
|
|
133
132
|
def self.make_response!(request)
|
@@ -136,7 +135,7 @@ module ActionController
|
|
136
135
|
end
|
137
136
|
end
|
138
137
|
|
139
|
-
def self.
|
138
|
+
def self.action_encoding_template(action) # :nodoc:
|
140
139
|
false
|
141
140
|
end
|
142
141
|
|
@@ -148,7 +147,7 @@ module ActionController
|
|
148
147
|
attr_internal :response, :request
|
149
148
|
delegate :session, to: "@_request"
|
150
149
|
delegate :headers, :status=, :location=, :content_type=,
|
151
|
-
:status, :location, :content_type, to: "@_response"
|
150
|
+
:status, :location, :content_type, :media_type, to: "@_response"
|
152
151
|
|
153
152
|
def initialize
|
154
153
|
@_request = nil
|
@@ -217,10 +216,13 @@ module ActionController
|
|
217
216
|
super
|
218
217
|
end
|
219
218
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
219
|
+
class << self
|
220
|
+
# Pushes the given Rack middleware and its arguments to the bottom of the
|
221
|
+
# middleware stack.
|
222
|
+
def use(*args, &block)
|
223
|
+
middleware_stack.use(*args, &block)
|
224
|
+
end
|
225
|
+
ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
|
224
226
|
end
|
225
227
|
|
226
228
|
# Alias for +middleware_stack+.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/
|
3
|
+
require "active_support/core_ext/object/try"
|
4
|
+
require "active_support/core_ext/integer/time"
|
4
5
|
|
5
6
|
module ActionController
|
6
7
|
module ConditionalGet
|
@@ -19,12 +20,12 @@ module ActionController
|
|
19
20
|
# of cached pages.
|
20
21
|
#
|
21
22
|
# class InvoicesController < ApplicationController
|
22
|
-
# etag { current_user
|
23
|
+
# etag { current_user&.id }
|
23
24
|
#
|
24
25
|
# def show
|
25
26
|
# # Etag will differ even for the same invoice when it's viewed by a different current_user
|
26
27
|
# @invoice = Invoice.find(params[:id])
|
27
|
-
# fresh_when
|
28
|
+
# fresh_when etag: @invoice
|
28
29
|
# end
|
29
30
|
# end
|
30
31
|
def etag(&etagger)
|
@@ -181,7 +182,7 @@ module ActionController
|
|
181
182
|
#
|
182
183
|
# You can also pass an object that responds to +maximum+, such as a
|
183
184
|
# collection of active records. In this case +last_modified+ will be set by
|
184
|
-
# calling
|
185
|
+
# calling <tt>maximum(:updated_at)</tt> on the collection (the timestamp of the
|
185
186
|
# most recently updated record) and the +etag+ by passing the object itself.
|
186
187
|
#
|
187
188
|
# def index
|
@@ -230,12 +231,25 @@ module ActionController
|
|
230
231
|
# This method will overwrite an existing Cache-Control header.
|
231
232
|
# See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
|
232
233
|
#
|
234
|
+
# HTTP Cache-Control Extensions for Stale Content. See https://tools.ietf.org/html/rfc5861
|
235
|
+
# It helps to cache an asset and serve it while is being revalidated and/or returning with an error.
|
236
|
+
#
|
237
|
+
# expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds
|
238
|
+
# expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds, stale_if_error: 5.minutes
|
239
|
+
#
|
240
|
+
# HTTP Cache-Control Extensions other values: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
241
|
+
# Any additional key-value pairs are concatenated onto the `Cache-Control` header in the response:
|
242
|
+
#
|
243
|
+
# expires_in 3.hours, public: true, "s-maxage": 3.hours, "no-transform": true
|
244
|
+
#
|
233
245
|
# The method will also ensure an HTTP Date header for client compatibility.
|
234
246
|
def expires_in(seconds, options = {})
|
235
247
|
response.cache_control.merge!(
|
236
248
|
max_age: seconds,
|
237
249
|
public: options.delete(:public),
|
238
|
-
must_revalidate: options.delete(:must_revalidate)
|
250
|
+
must_revalidate: options.delete(:must_revalidate),
|
251
|
+
stale_while_revalidate: options.delete(:stale_while_revalidate),
|
252
|
+
stale_if_error: options.delete(:stale_if_error),
|
239
253
|
)
|
240
254
|
options.delete(:private)
|
241
255
|
|
@@ -36,7 +36,6 @@ module ActionController #:nodoc:
|
|
36
36
|
end
|
37
37
|
|
38
38
|
private
|
39
|
-
|
40
39
|
def content_security_policy?
|
41
40
|
request.content_security_policy
|
42
41
|
end
|
@@ -46,7 +45,7 @@ module ActionController #:nodoc:
|
|
46
45
|
end
|
47
46
|
|
48
47
|
def current_content_security_policy
|
49
|
-
request.content_security_policy
|
48
|
+
request.content_security_policy&.clone || ActionDispatch::ContentSecurityPolicy.new
|
50
49
|
end
|
51
50
|
end
|
52
51
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "action_controller/metal/exceptions"
|
4
|
+
require "action_dispatch/http/content_disposition"
|
4
5
|
|
5
6
|
module ActionController #:nodoc:
|
6
7
|
# Methods for sending arbitrary data and for streaming files to the browser,
|
@@ -10,8 +11,8 @@ module ActionController #:nodoc:
|
|
10
11
|
|
11
12
|
include ActionController::Rendering
|
12
13
|
|
13
|
-
DEFAULT_SEND_FILE_TYPE = "application/octet-stream"
|
14
|
-
DEFAULT_SEND_FILE_DISPOSITION = "attachment"
|
14
|
+
DEFAULT_SEND_FILE_TYPE = "application/octet-stream" #:nodoc:
|
15
|
+
DEFAULT_SEND_FILE_DISPOSITION = "attachment" #:nodoc:
|
15
16
|
|
16
17
|
private
|
17
18
|
# Sends the file. This uses a server-appropriate method (such as X-Sendfile)
|
@@ -52,7 +53,7 @@ module ActionController #:nodoc:
|
|
52
53
|
#
|
53
54
|
# Show a 404 page in the browser:
|
54
55
|
#
|
55
|
-
# send_file '/path/to/404.html', type: 'text/html; charset=utf-8', status: 404
|
56
|
+
# send_file '/path/to/404.html', type: 'text/html; charset=utf-8', disposition: 'inline', status: 404
|
56
57
|
#
|
57
58
|
# Read about the other Content-* HTTP headers if you'd like to
|
58
59
|
# provide the user with more information (such as Content-Description) in
|
@@ -132,10 +133,8 @@ module ActionController #:nodoc:
|
|
132
133
|
end
|
133
134
|
|
134
135
|
disposition = options.fetch(:disposition, DEFAULT_SEND_FILE_DISPOSITION)
|
135
|
-
|
136
|
-
|
137
|
-
disposition += %(; filename="#{options[:filename]}") if options[:filename]
|
138
|
-
headers["Content-Disposition"] = disposition
|
136
|
+
if disposition
|
137
|
+
headers["Content-Disposition"] = ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: options[:filename])
|
139
138
|
end
|
140
139
|
|
141
140
|
headers["Content-Transfer-Encoding"] = "binary"
|