actionpack 6.0.3.3 → 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 +267 -222
- data/MIT-LICENSE +1 -1
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/base.rb +35 -2
- data/lib/abstract_controller/callbacks.rb +2 -2
- data/lib/abstract_controller/helpers.rb +105 -90
- data/lib/abstract_controller/rendering.rb +9 -9
- data/lib/abstract_controller/translation.rb +8 -2
- data/lib/action_controller.rb +2 -3
- data/lib/action_controller/api.rb +2 -2
- data/lib/action_controller/base.rb +4 -2
- data/lib/action_controller/caching.rb +0 -1
- data/lib/action_controller/log_subscriber.rb +3 -3
- data/lib/action_controller/metal.rb +2 -2
- data/lib/action_controller/metal/conditional_get.rb +11 -3
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/cookies.rb +3 -1
- data/lib/action_controller/metal/data_streaming.rb +1 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -4
- data/lib/action_controller/metal/exceptions.rb +33 -0
- data/lib/action_controller/metal/head.rb +7 -4
- data/lib/action_controller/metal/helpers.rb +11 -1
- data/lib/action_controller/metal/http_authentication.rb +4 -2
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +11 -9
- data/lib/action_controller/metal/live.rb +1 -1
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +6 -2
- data/lib/action_controller/metal/parameter_encoding.rb +35 -4
- data/lib/action_controller/metal/params_wrapper.rb +14 -8
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +1 -1
- data/lib/action_controller/metal/rendering.rb +6 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +48 -24
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/strong_parameters.rb +103 -15
- data/lib/action_controller/renderer.rb +24 -13
- data/lib/action_controller/test_case.rb +62 -56
- data/lib/action_dispatch.rb +3 -2
- data/lib/action_dispatch/http/cache.rb +12 -10
- data/lib/action_dispatch/http/content_disposition.rb +2 -2
- data/lib/action_dispatch/http/content_security_policy.rb +5 -1
- data/lib/action_dispatch/http/filter_parameters.rb +1 -1
- data/lib/action_dispatch/http/filter_redirect.rb +1 -1
- data/lib/action_dispatch/http/headers.rb +3 -2
- data/lib/action_dispatch/http/mime_negotiation.rb +20 -8
- data/lib/action_dispatch/http/mime_type.rb +28 -15
- data/lib/action_dispatch/http/parameters.rb +1 -19
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/request.rb +26 -8
- data/lib/action_dispatch/http/response.rb +17 -16
- data/lib/action_dispatch/http/url.rb +3 -2
- data/lib/action_dispatch/journey.rb +0 -2
- data/lib/action_dispatch/journey/formatter.rb +53 -28
- data/lib/action_dispatch/journey/gtg/builder.rb +22 -36
- data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -4
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
- data/lib/action_dispatch/journey/nodes/node.rb +4 -3
- 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 +13 -18
- data/lib/action_dispatch/journey/route.rb +7 -18
- data/lib/action_dispatch/journey/router.rb +26 -30
- data/lib/action_dispatch/journey/router/utils.rb +6 -4
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +9 -2
- data/lib/action_dispatch/middleware/cookies.rb +74 -33
- data/lib/action_dispatch/middleware/debug_exceptions.rb +10 -17
- data/lib/action_dispatch/middleware/debug_view.rb +1 -1
- data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -17
- data/lib/action_dispatch/middleware/host_authorization.rb +25 -5
- data/lib/action_dispatch/middleware/public_exceptions.rb +1 -1
- data/lib/action_dispatch/middleware/remote_ip.rb +5 -4
- data/lib/action_dispatch/middleware/request_id.rb +4 -5
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -2
- data/lib/action_dispatch/middleware/session/cookie_store.rb +2 -2
- data/lib/action_dispatch/middleware/show_exceptions.rb +2 -0
- data/lib/action_dispatch/middleware/ssl.rb +12 -7
- data/lib/action_dispatch/middleware/stack.rb +18 -0
- data/lib/action_dispatch/middleware/static.rb +154 -93
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +2 -5
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +100 -8
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +21 -1
- data/lib/action_dispatch/railtie.rb +3 -2
- data/lib/action_dispatch/request/session.rb +2 -8
- data/lib/action_dispatch/request/utils.rb +26 -2
- data/lib/action_dispatch/routing/inspector.rb +8 -7
- data/lib/action_dispatch/routing/mapper.rb +102 -71
- data/lib/action_dispatch/routing/polymorphic_routes.rb +12 -11
- data/lib/action_dispatch/routing/redirection.rb +3 -3
- data/lib/action_dispatch/routing/route_set.rb +49 -41
- data/lib/action_dispatch/routing/url_for.rb +1 -0
- data/lib/action_dispatch/system_test_case.rb +29 -24
- data/lib/action_dispatch/system_testing/browser.rb +33 -27
- data/lib/action_dispatch/system_testing/driver.rb +6 -7
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +47 -6
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +4 -7
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +2 -4
- data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
- data/lib/action_dispatch/testing/integration.rb +38 -27
- data/lib/action_dispatch/testing/test_process.rb +29 -4
- data/lib/action_dispatch/testing/test_request.rb +3 -3
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/gem_version.rb +3 -3
- metadata +21 -22
- data/lib/action_controller/metal/force_ssl.rb +0 -58
- data/lib/action_dispatch/http/parameter_filter.rb +0 -12
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -119
@@ -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,9 +120,9 @@ module ActionController
|
|
120
120
|
BasicImplicitRender,
|
121
121
|
StrongParameters,
|
122
122
|
|
123
|
-
ForceSSL,
|
124
123
|
DataStreaming,
|
125
124
|
DefaultHeaders,
|
125
|
+
Logging,
|
126
126
|
|
127
127
|
# Before callbacks should also be executed as early as possible, so
|
128
128
|
# also include them at the bottom.
|
@@ -226,13 +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
235
|
DefaultHeaders,
|
236
|
+
Logging,
|
236
237
|
|
237
238
|
# Before callbacks should also be executed as early as possible, so
|
238
239
|
# also include them at the bottom.
|
@@ -261,9 +262,10 @@ module ActionController
|
|
261
262
|
@_view_renderer @_lookup_context @_routes @_view_runtime @_db_runtime @_helper_proxy
|
262
263
|
)
|
263
264
|
|
264
|
-
def _protected_ivars
|
265
|
+
def _protected_ivars
|
265
266
|
PROTECTED_IVARS
|
266
267
|
end
|
268
|
+
private :_protected_ivars
|
267
269
|
|
268
270
|
ActiveSupport.run_load_hooks(:action_controller_base, self)
|
269
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
|
@@ -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?
|
@@ -22,15 +23,14 @@ module ActionController
|
|
22
23
|
additions = ActionController::Base.log_process_action(payload)
|
23
24
|
status = payload[:status]
|
24
25
|
|
25
|
-
if status.nil? && payload[:exception].
|
26
|
-
exception_class_name = payload[:exception].first
|
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
29
|
|
30
30
|
additions << "Allocations: #{event.allocations}"
|
31
31
|
|
32
32
|
message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
|
33
|
-
message << " (#{additions.join(" | ")})"
|
33
|
+
message << " (#{additions.join(" | ")})"
|
34
34
|
message << "\n\n" if defined?(Rails.env) && Rails.env.development?
|
35
35
|
|
36
36
|
message
|
@@ -126,7 +126,7 @@ module ActionController
|
|
126
126
|
# ==== Returns
|
127
127
|
# * <tt>string</tt>
|
128
128
|
def self.controller_name
|
129
|
-
@controller_name ||= name.demodulize.
|
129
|
+
@controller_name ||= (name.demodulize.delete_suffix("Controller").underscore unless anonymous?)
|
130
130
|
end
|
131
131
|
|
132
132
|
def self.make_response!(request)
|
@@ -135,7 +135,7 @@ module ActionController
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
-
def self.
|
138
|
+
def self.action_encoding_template(action) # :nodoc:
|
139
139
|
false
|
140
140
|
end
|
141
141
|
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/object/try"
|
4
|
+
require "active_support/core_ext/integer/time"
|
5
|
+
|
3
6
|
module ActionController
|
4
7
|
module ConditionalGet
|
5
8
|
extend ActiveSupport::Concern
|
@@ -17,12 +20,12 @@ module ActionController
|
|
17
20
|
# of cached pages.
|
18
21
|
#
|
19
22
|
# class InvoicesController < ApplicationController
|
20
|
-
# etag { current_user
|
23
|
+
# etag { current_user&.id }
|
21
24
|
#
|
22
25
|
# def show
|
23
26
|
# # Etag will differ even for the same invoice when it's viewed by a different current_user
|
24
27
|
# @invoice = Invoice.find(params[:id])
|
25
|
-
# fresh_when
|
28
|
+
# fresh_when etag: @invoice
|
26
29
|
# end
|
27
30
|
# end
|
28
31
|
def etag(&etagger)
|
@@ -179,7 +182,7 @@ module ActionController
|
|
179
182
|
#
|
180
183
|
# You can also pass an object that responds to +maximum+, such as a
|
181
184
|
# collection of active records. In this case +last_modified+ will be set by
|
182
|
-
# calling
|
185
|
+
# calling <tt>maximum(:updated_at)</tt> on the collection (the timestamp of the
|
183
186
|
# most recently updated record) and the +etag+ by passing the object itself.
|
184
187
|
#
|
185
188
|
# def index
|
@@ -234,6 +237,11 @@ module ActionController
|
|
234
237
|
# expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds
|
235
238
|
# expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds, stale_if_error: 5.minutes
|
236
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
|
+
#
|
237
245
|
# The method will also ensure an HTTP Date header for client compatibility.
|
238
246
|
def expires_in(seconds, options = {})
|
239
247
|
response.cache_control.merge!(
|
@@ -45,7 +45,7 @@ module ActionController #:nodoc:
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def current_content_security_policy
|
48
|
-
request.content_security_policy
|
48
|
+
request.content_security_policy&.clone || ActionDispatch::ContentSecurityPolicy.new
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
@@ -53,7 +53,7 @@ module ActionController #:nodoc:
|
|
53
53
|
#
|
54
54
|
# Show a 404 page in the browser:
|
55
55
|
#
|
56
|
-
# 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
|
57
57
|
#
|
58
58
|
# Read about the other Content-* HTTP headers if you'd like to
|
59
59
|
# provide the user with more information (such as Content-Description) in
|
@@ -26,10 +26,8 @@ module ActionController
|
|
26
26
|
included do
|
27
27
|
class_attribute :etag_with_template_digest, default: true
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
determine_template_etag(options) if etag_with_template_digest
|
32
|
-
end
|
29
|
+
etag do |options|
|
30
|
+
determine_template_etag(options) if etag_with_template_digest
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -23,6 +23,39 @@ module ActionController
|
|
23
23
|
end
|
24
24
|
|
25
25
|
class UrlGenerationError < ActionControllerError #:nodoc:
|
26
|
+
attr_reader :routes, :route_name, :method_name
|
27
|
+
|
28
|
+
def initialize(message, routes = nil, route_name = nil, method_name = nil)
|
29
|
+
@routes = routes
|
30
|
+
@route_name = route_name
|
31
|
+
@method_name = method_name
|
32
|
+
|
33
|
+
super(message)
|
34
|
+
end
|
35
|
+
|
36
|
+
class Correction
|
37
|
+
def initialize(error)
|
38
|
+
@error = error
|
39
|
+
end
|
40
|
+
|
41
|
+
def corrections
|
42
|
+
if @error.method_name
|
43
|
+
maybe_these = @error.routes.named_routes.helper_names.grep(/#{@error.route_name}/)
|
44
|
+
maybe_these -= [@error.method_name.to_s] # remove exact match
|
45
|
+
|
46
|
+
maybe_these.sort_by { |n|
|
47
|
+
DidYouMean::Jaro.distance(@error.route_name, n)
|
48
|
+
}.reverse.first(4)
|
49
|
+
else
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# We may not have DYM, and DYM might not let us register error handlers
|
56
|
+
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
57
|
+
DidYouMean.correct_error(self, Correction)
|
58
|
+
end
|
26
59
|
end
|
27
60
|
|
28
61
|
class MethodNotAllowed < ActionControllerError #:nodoc:
|
@@ -29,19 +29,22 @@ module ActionController
|
|
29
29
|
content_type = options.delete(:content_type)
|
30
30
|
|
31
31
|
options.each do |key, value|
|
32
|
-
headers[key.to_s.
|
32
|
+
headers[key.to_s.split(/[-_]/).each { |v| v[0] = v[0].upcase }.join("-")] = value.to_s
|
33
33
|
end
|
34
34
|
|
35
35
|
self.status = status
|
36
36
|
self.location = url_for(location) if location
|
37
37
|
|
38
|
-
self.response_body = ""
|
39
|
-
|
40
38
|
if include_content?(response_code)
|
41
|
-
self.
|
39
|
+
unless self.media_type
|
40
|
+
self.content_type = content_type || (Mime[formats.first] if formats) || Mime[:html]
|
41
|
+
end
|
42
|
+
|
42
43
|
response.charset = false
|
43
44
|
end
|
44
45
|
|
46
|
+
self.response_body = ""
|
47
|
+
|
45
48
|
true
|
46
49
|
end
|
47
50
|
|
@@ -11,7 +11,12 @@ module ActionController
|
|
11
11
|
#
|
12
12
|
# In previous versions of \Rails the controller will include a helper which
|
13
13
|
# matches the name of the controller, e.g., <tt>MyController</tt> will automatically
|
14
|
-
# include <tt>MyHelper</tt>.
|
14
|
+
# include <tt>MyHelper</tt>. You can revert to the old behavior with the following:
|
15
|
+
#
|
16
|
+
# # config/application.rb
|
17
|
+
# class Application < Rails::Application
|
18
|
+
# config.action_controller.include_all_helpers = false
|
19
|
+
# end
|
15
20
|
#
|
16
21
|
# Additional helpers can be specified using the +helper+ class method in ActionController::Base or any
|
17
22
|
# controller which inherits from it.
|
@@ -73,6 +78,11 @@ module ActionController
|
|
73
78
|
end
|
74
79
|
|
75
80
|
# Provides a proxy to access helper methods from outside the view.
|
81
|
+
#
|
82
|
+
# Note that the proxy is rendered under a different view context.
|
83
|
+
# This may cause incorrect behaviour with capture methods. Consider
|
84
|
+
# using {helper}[rdoc-ref:AbstractController::Helpers::ClassMethods#helper]
|
85
|
+
# instead when using +capture+.
|
76
86
|
def helpers
|
77
87
|
@helper_proxy ||= begin
|
78
88
|
proxy = ActionView::Base.empty
|
@@ -76,6 +76,8 @@ module ActionController
|
|
76
76
|
|
77
77
|
def http_basic_authenticate_or_request_with(name:, password:, realm: nil, message: nil)
|
78
78
|
authenticate_or_request_with_http_basic(realm, message) do |given_name, given_password|
|
79
|
+
# This comparison uses & so that it doesn't short circuit and
|
80
|
+
# uses `secure_compare` so that length information isn't leaked.
|
79
81
|
ActiveSupport::SecurityUtils.secure_compare(given_name, name) &
|
80
82
|
ActiveSupport::SecurityUtils.secure_compare(given_password, password)
|
81
83
|
end
|
@@ -136,7 +138,7 @@ module ActionController
|
|
136
138
|
#
|
137
139
|
# === Simple \Digest example
|
138
140
|
#
|
139
|
-
# require
|
141
|
+
# require "digest/md5"
|
140
142
|
# class PostsController < ApplicationController
|
141
143
|
# REALM = "SuperSecret"
|
142
144
|
# USERS = {"dhh" => "secret", #plain text password
|
@@ -482,7 +484,7 @@ module ActionController
|
|
482
484
|
def raw_params(auth)
|
483
485
|
_raw_params = auth.sub(TOKEN_REGEX, "").split(/\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
|
484
486
|
|
485
|
-
if !
|
487
|
+
if !_raw_params.first.start_with?(TOKEN_KEY)
|
486
488
|
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
|
487
489
|
end
|
488
490
|
|
@@ -22,7 +22,7 @@ module ActionController
|
|
22
22
|
# Third, if we DON'T find a template AND the request is a page load in a web
|
23
23
|
# browser (technically, a non-XHR GET request for an HTML response) where
|
24
24
|
# you reasonably expect to have rendered a template, then we raise
|
25
|
-
# <tt>
|
25
|
+
# <tt>ActionController::MissingExactTemplate</tt> with an explanation.
|
26
26
|
#
|
27
27
|
# Finally, if we DON'T find a template AND the request isn't a browser page
|
28
28
|
# load, then we implicitly respond with <tt>204 No Content</tt>.
|
@@ -16,10 +16,11 @@ module ActionController
|
|
16
16
|
|
17
17
|
attr_internal :view_runtime
|
18
18
|
|
19
|
-
def process_action(*
|
19
|
+
def process_action(*)
|
20
20
|
raw_payload = {
|
21
21
|
controller: self.class.name,
|
22
22
|
action: action_name,
|
23
|
+
request: request,
|
23
24
|
params: request.filtered_parameters,
|
24
25
|
headers: request.headers,
|
25
26
|
format: request.format.ref,
|
@@ -27,18 +28,19 @@ module ActionController
|
|
27
28
|
path: request.fullpath
|
28
29
|
}
|
29
30
|
|
30
|
-
ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload
|
31
|
+
ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload)
|
31
32
|
|
32
33
|
ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
|
33
|
-
super
|
34
|
-
|
35
|
-
|
34
|
+
result = super
|
35
|
+
payload[:response] = response
|
36
|
+
payload[:status] = response.status
|
37
|
+
result
|
36
38
|
ensure
|
37
39
|
append_info_to_payload(payload)
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
def render(*
|
43
|
+
def render(*)
|
42
44
|
render_output = nil
|
43
45
|
self.view_runtime = cleanup_view_runtime do
|
44
46
|
Benchmark.ms { render_output = super }
|
@@ -59,8 +61,8 @@ module ActionController
|
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
62
|
-
def redirect_to(*
|
63
|
-
ActiveSupport::Notifications.instrument("redirect_to.action_controller") do |payload|
|
64
|
+
def redirect_to(*)
|
65
|
+
ActiveSupport::Notifications.instrument("redirect_to.action_controller", request: request) do |payload|
|
64
66
|
result = super
|
65
67
|
payload[:status] = response.status
|
66
68
|
payload[:location] = response.filtered_location
|
@@ -70,7 +72,7 @@ module ActionController
|
|
70
72
|
|
71
73
|
private
|
72
74
|
# A hook invoked every time a before callback is halted.
|
73
|
-
def halted_callback_hook(filter)
|
75
|
+
def halted_callback_hook(filter, _)
|
74
76
|
ActiveSupport::Notifications.instrument("halted_callback.action_controller", filter: filter)
|
75
77
|
end
|
76
78
|
|
@@ -136,11 +136,11 @@ module ActionController
|
|
136
136
|
attr_accessor :ignore_disconnect
|
137
137
|
|
138
138
|
def initialize(response)
|
139
|
+
super(response, SizedQueue.new(10))
|
139
140
|
@error_callback = lambda { true }
|
140
141
|
@cv = new_cond
|
141
142
|
@aborted = false
|
142
143
|
@ignore_disconnect = false
|
143
|
-
super(response, SizedQueue.new(10))
|
144
144
|
end
|
145
145
|
|
146
146
|
def write(string)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
module Logging
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# Set a different log level per request.
|
9
|
+
#
|
10
|
+
# # Use the debug log level if a particular cookie is set.
|
11
|
+
# class ApplicationController < ActionController::Base
|
12
|
+
# log_at :debug, if: -> { cookies[:debug] }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
def log_at(level, **options)
|
16
|
+
around_action ->(_, action) { logger.log_at(level, &action) }, **options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -142,7 +142,7 @@ module ActionController #:nodoc:
|
|
142
142
|
#
|
143
143
|
# You can set the variant in a +before_action+:
|
144
144
|
#
|
145
|
-
# request.variant = :tablet if request.user_agent
|
145
|
+
# request.variant = :tablet if /iPad/.match?(request.user_agent)
|
146
146
|
#
|
147
147
|
# Respond to variants in the action just like you respond to formats:
|
148
148
|
#
|
@@ -209,7 +209,7 @@ module ActionController #:nodoc:
|
|
209
209
|
raise ActionController::RespondToMismatchError
|
210
210
|
end
|
211
211
|
_process_format(format)
|
212
|
-
_set_rendered_content_type
|
212
|
+
_set_rendered_content_type(format) unless collector.any_response?
|
213
213
|
response = collector.response
|
214
214
|
response.call if response
|
215
215
|
else
|
@@ -268,6 +268,10 @@ module ActionController #:nodoc:
|
|
268
268
|
end
|
269
269
|
end
|
270
270
|
|
271
|
+
def any_response?
|
272
|
+
!@responses.fetch(format, false) && @responses[Mime::ALL]
|
273
|
+
end
|
274
|
+
|
271
275
|
def response
|
272
276
|
response = @responses.fetch(format, @responses[Mime::ALL])
|
273
277
|
if response.is_a?(VariantCollector) # `format.html.phone` - variant inline syntax
|
@@ -12,11 +12,13 @@ module ActionController
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def setup_param_encode # :nodoc:
|
15
|
-
@_parameter_encodings = {}
|
15
|
+
@_parameter_encodings = Hash.new { |h, k| h[k] = {} }
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
@_parameter_encodings
|
18
|
+
def action_encoding_template(action) # :nodoc:
|
19
|
+
if @_parameter_encodings.has_key?(action.to_s)
|
20
|
+
@_parameter_encodings[action.to_s]
|
21
|
+
end
|
20
22
|
end
|
21
23
|
|
22
24
|
# Specify that a given action's parameters should all be encoded as
|
@@ -44,7 +46,36 @@ module ActionController
|
|
44
46
|
# encoded as ASCII-8BIT. This is useful in the case where an application
|
45
47
|
# must handle data but encoding of the data is unknown, like file system data.
|
46
48
|
def skip_parameter_encoding(action)
|
47
|
-
@_parameter_encodings[action.to_s] =
|
49
|
+
@_parameter_encodings[action.to_s] = Hash.new { Encoding::ASCII_8BIT }
|
50
|
+
end
|
51
|
+
|
52
|
+
# Specify the encoding for a parameter on an action.
|
53
|
+
# If not specified the default is UTF-8.
|
54
|
+
#
|
55
|
+
# You can specify a binary (ASCII_8BIT) parameter with:
|
56
|
+
#
|
57
|
+
# class RepositoryController < ActionController::Base
|
58
|
+
# # This specifies that file_path is not UTF-8 and is instead ASCII_8BIT
|
59
|
+
# param_encoding :show, :file_path, Encoding::ASCII_8BIT
|
60
|
+
#
|
61
|
+
# def show
|
62
|
+
# @repo = Repository.find_by_filesystem_path params[:file_path]
|
63
|
+
#
|
64
|
+
# # params[:repo_name] remains UTF-8 encoded
|
65
|
+
# @repo_name = params[:repo_name]
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# def index
|
69
|
+
# @repositories = Repository.all
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# The file_path parameter on the show action would be encoded as ASCII-8BIT,
|
74
|
+
# but all other arguments will remain UTF-8 encoded.
|
75
|
+
# This is useful in the case where an application must handle data
|
76
|
+
# but encoding of the data is unknown, like file system data.
|
77
|
+
def param_encoding(action, param, encoding)
|
78
|
+
@_parameter_encodings[action.to_s][param.to_s] = encoding
|
48
79
|
end
|
49
80
|
end
|
50
81
|
end
|