actionpack 7.0.8.1 → 7.1.3.4
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 +365 -353
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -2
- data/lib/abstract_controller/base.rb +20 -11
- data/lib/abstract_controller/caching/fragments.rb +2 -0
- data/lib/abstract_controller/callbacks.rb +31 -6
- data/lib/abstract_controller/deprecator.rb +7 -0
- data/lib/abstract_controller/helpers.rb +61 -18
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -16
- data/lib/abstract_controller/rendering.rb +3 -3
- data/lib/abstract_controller/translation.rb +1 -20
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/abstract_controller.rb +6 -0
- data/lib/action_controller/api.rb +5 -3
- data/lib/action_controller/base.rb +3 -17
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/deprecator.rb +7 -0
- data/lib/action_controller/form_builder.rb +2 -0
- data/lib/action_controller/log_subscriber.rb +16 -4
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +2 -0
- data/lib/action_controller/metal/default_headers.rb +2 -0
- data/lib/action_controller/metal/etag_with_flash.rb +2 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
- data/lib/action_controller/metal/exceptions.rb +8 -0
- data/lib/action_controller/metal/head.rb +8 -6
- data/lib/action_controller/metal/helpers.rb +3 -14
- data/lib/action_controller/metal/http_authentication.rb +17 -8
- data/lib/action_controller/metal/implicit_render.rb +5 -3
- data/lib/action_controller/metal/instrumentation.rb +8 -1
- data/lib/action_controller/metal/live.rb +24 -0
- data/lib/action_controller/metal/mime_responds.rb +2 -2
- data/lib/action_controller/metal/params_wrapper.rb +4 -2
- data/lib/action_controller/metal/permissions_policy.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +7 -7
- data/lib/action_controller/metal/renderers.rb +2 -2
- data/lib/action_controller/metal/rendering.rb +0 -7
- data/lib/action_controller/metal/request_forgery_protection.rb +139 -50
- data/lib/action_controller/metal/rescue.rb +2 -0
- data/lib/action_controller/metal/streaming.rb +70 -30
- data/lib/action_controller/metal/strong_parameters.rb +132 -52
- data/lib/action_controller/metal/url_for.rb +7 -0
- data/lib/action_controller/metal.rb +79 -21
- data/lib/action_controller/railtie.rb +22 -9
- data/lib/action_controller/renderer.rb +98 -65
- data/lib/action_controller/test_case.rb +15 -5
- data/lib/action_controller.rb +8 -1
- data/lib/action_dispatch/constants.rb +32 -0
- data/lib/action_dispatch/deprecator.rb +7 -0
- data/lib/action_dispatch/http/cache.rb +1 -3
- data/lib/action_dispatch/http/content_security_policy.rb +9 -8
- data/lib/action_dispatch/http/filter_parameters.rb +11 -5
- data/lib/action_dispatch/http/headers.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -22
- data/lib/action_dispatch/http/mime_type.rb +35 -12
- data/lib/action_dispatch/http/mime_types.rb +3 -1
- data/lib/action_dispatch/http/parameters.rb +1 -1
- data/lib/action_dispatch/http/permissions_policy.rb +38 -23
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +48 -14
- data/lib/action_dispatch/http/response.rb +80 -59
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/journey/formatter.rb +8 -2
- data/lib/action_dispatch/journey/path/pattern.rb +14 -14
- data/lib/action_dispatch/journey/route.rb +3 -2
- data/lib/action_dispatch/journey/router.rb +9 -8
- data/lib/action_dispatch/journey/routes.rb +2 -2
- data/lib/action_dispatch/log_subscriber.rb +23 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -6
- data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +81 -98
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -25
- data/lib/action_dispatch/middleware/debug_locks.rb +4 -1
- data/lib/action_dispatch/middleware/debug_view.rb +7 -2
- data/lib/action_dispatch/middleware/exception_wrapper.rb +186 -27
- data/lib/action_dispatch/middleware/executor.rb +1 -1
- data/lib/action_dispatch/middleware/flash.rb +7 -0
- data/lib/action_dispatch/middleware/host_authorization.rb +6 -3
- data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
- data/lib/action_dispatch/middleware/reloader.rb +7 -5
- data/lib/action_dispatch/middleware/remote_ip.rb +17 -16
- data/lib/action_dispatch/middleware/request_id.rb +2 -0
- data/lib/action_dispatch/middleware/server_timing.rb +4 -4
- data/lib/action_dispatch/middleware/session/abstract_store.rb +5 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +11 -5
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +19 -15
- data/lib/action_dispatch/middleware/ssl.rb +18 -6
- data/lib/action_dispatch/middleware/stack.rb +7 -2
- data/lib/action_dispatch/middleware/static.rb +12 -8
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
- data/lib/action_dispatch/railtie.rb +14 -4
- data/lib/action_dispatch/request/session.rb +16 -6
- data/lib/action_dispatch/request/utils.rb +8 -3
- data/lib/action_dispatch/routing/inspector.rb +54 -6
- data/lib/action_dispatch/routing/mapper.rb +35 -24
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +15 -6
- data/lib/action_dispatch/routing/route_set.rb +52 -22
- data/lib/action_dispatch/routing/routes_proxy.rb +10 -15
- data/lib/action_dispatch/routing/url_for.rb +5 -1
- data/lib/action_dispatch/routing.rb +7 -7
- data/lib/action_dispatch/system_test_case.rb +3 -3
- data/lib/action_dispatch/system_testing/browser.rb +20 -19
- data/lib/action_dispatch/system_testing/driver.rb +13 -21
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
- data/lib/action_dispatch/testing/assertion_response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +13 -6
- data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
- data/lib/action_dispatch/testing/assertions.rb +3 -1
- data/lib/action_dispatch/testing/integration.rb +27 -17
- data/lib/action_dispatch/testing/request_encoder.rb +4 -1
- data/lib/action_dispatch/testing/test_process.rb +4 -3
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +23 -9
- data/lib/action_dispatch.rb +37 -4
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_pack.rb +1 -1
- metadata +64 -28
@@ -14,8 +14,13 @@ module ActionController
|
|
14
14
|
config.action_controller.log_query_tags_around_actions = true
|
15
15
|
config.action_controller.wrap_parameters_by_default = false
|
16
16
|
|
17
|
+
config.eager_load_namespaces << AbstractController
|
17
18
|
config.eager_load_namespaces << ActionController
|
18
19
|
|
20
|
+
initializer "action_controller.deprecator", before: :load_environment_config do |app|
|
21
|
+
app.deprecators[:action_controller] = ActionController.deprecator
|
22
|
+
end
|
23
|
+
|
19
24
|
initializer "action_controller.assets_config", group: :all do |app|
|
20
25
|
app.config.action_controller.assets_dir ||= app.config.paths["public"].first
|
21
26
|
end
|
@@ -37,10 +42,15 @@ module ActionController
|
|
37
42
|
action_on_unpermitted_parameters = options.action_on_unpermitted_parameters
|
38
43
|
|
39
44
|
if action_on_unpermitted_parameters.nil?
|
40
|
-
action_on_unpermitted_parameters =
|
45
|
+
action_on_unpermitted_parameters = Rails.env.local? ? :log : false
|
41
46
|
end
|
42
47
|
|
43
48
|
ActionController::Parameters.action_on_unpermitted_parameters = action_on_unpermitted_parameters
|
49
|
+
|
50
|
+
unless options.allow_deprecated_parameters_hash_equality.nil?
|
51
|
+
ActionController::Parameters.allow_deprecated_parameters_hash_equality =
|
52
|
+
options.allow_deprecated_parameters_hash_equality
|
53
|
+
end
|
44
54
|
end
|
45
55
|
end
|
46
56
|
|
@@ -71,7 +81,8 @@ module ActionController
|
|
71
81
|
:permit_all_parameters,
|
72
82
|
:action_on_unpermitted_parameters,
|
73
83
|
:always_permitted_parameters,
|
74
|
-
:wrap_parameters_by_default
|
84
|
+
:wrap_parameters_by_default,
|
85
|
+
:allow_deprecated_parameters_hash_equality
|
75
86
|
)
|
76
87
|
|
77
88
|
filtered_options.each do |k, v|
|
@@ -99,12 +110,6 @@ module ActionController
|
|
99
110
|
end
|
100
111
|
end
|
101
112
|
|
102
|
-
initializer "action_controller.eager_load_actions" do
|
103
|
-
ActiveSupport.on_load(:after_initialize) do
|
104
|
-
ActionController::Metal.descendants.each(&:action_methods) if config.eager_load
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
113
|
initializer "action_controller.query_log_tags" do |app|
|
109
114
|
query_logs_tags_enabled = app.config.respond_to?(:active_record) &&
|
110
115
|
app.config.active_record.query_log_tags_enabled &&
|
@@ -118,7 +123,15 @@ module ActionController
|
|
118
123
|
ActiveRecord::QueryLogs.taggings.merge!(
|
119
124
|
controller: ->(context) { context[:controller]&.controller_name },
|
120
125
|
action: ->(context) { context[:controller]&.action_name },
|
121
|
-
namespaced_controller: ->(context) {
|
126
|
+
namespaced_controller: ->(context) {
|
127
|
+
if context[:controller]
|
128
|
+
controller_class = context[:controller].class
|
129
|
+
# based on ActionController::Metal#controller_name, but does not demodulize
|
130
|
+
unless controller_class.anonymous?
|
131
|
+
controller_class.name.delete_suffix("Controller").underscore
|
132
|
+
end
|
133
|
+
end
|
134
|
+
}
|
122
135
|
)
|
123
136
|
end
|
124
137
|
end
|
@@ -1,78 +1,127 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionController
|
4
|
-
#
|
5
|
-
# without requirement of being in controller actions.
|
4
|
+
# = Action Controller \Renderer
|
6
5
|
#
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# ActionController::Renderer allows you to render arbitrary templates without
|
7
|
+
# being inside a controller action.
|
9
8
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# It allows you to call method #render directly.
|
13
|
-
#
|
14
|
-
# ApplicationController.renderer.render template: '...'
|
15
|
-
#
|
16
|
-
# You can use this shortcut in a controller, instead of the previous example:
|
17
|
-
#
|
18
|
-
# ApplicationController.render template: '...'
|
9
|
+
# You can get a renderer instance by calling +renderer+ on a controller class:
|
19
10
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# FooController.render :action, locals: { ... }, assigns: { ... }
|
24
|
-
#
|
25
|
-
# The template will be rendered in a Rack environment which is accessible through
|
26
|
-
# ActionController::Renderer#env. You can set it up in two ways:
|
11
|
+
# ApplicationController.renderer
|
12
|
+
# PostsController.renderer
|
27
13
|
#
|
28
|
-
#
|
14
|
+
# and render a template by calling the #render method:
|
29
15
|
#
|
30
|
-
#
|
16
|
+
# ApplicationController.renderer.render template: "posts/show", assigns: { post: Post.first }
|
17
|
+
# PostsController.renderer.render :show, assigns: { post: Post.first }
|
31
18
|
#
|
32
|
-
#
|
19
|
+
# As a shortcut, you can also call +render+ directly on the controller class itself:
|
33
20
|
#
|
34
|
-
#
|
21
|
+
# ApplicationController.render template: "posts/show", assigns: { post: Post.first }
|
22
|
+
# PostsController.render :show, assigns: { post: Post.first }
|
35
23
|
#
|
36
24
|
class Renderer
|
37
|
-
attr_reader :
|
25
|
+
attr_reader :controller
|
38
26
|
|
39
27
|
DEFAULTS = {
|
40
|
-
http_host: "example.org",
|
41
|
-
https: false,
|
42
28
|
method: "get",
|
43
|
-
script_name: "",
|
44
29
|
input: ""
|
45
30
|
}.freeze
|
46
31
|
|
47
|
-
|
48
|
-
|
32
|
+
def self.normalize_env(env) # :nodoc:
|
33
|
+
new_env = {}
|
34
|
+
|
35
|
+
env.each_pair do |key, value|
|
36
|
+
case key
|
37
|
+
when :https
|
38
|
+
value = value ? "on" : "off"
|
39
|
+
when :method
|
40
|
+
value = -value.upcase
|
41
|
+
end
|
42
|
+
|
43
|
+
key = RACK_KEY_TRANSLATION[key] || key.to_s
|
44
|
+
|
45
|
+
new_env[key] = value
|
46
|
+
end
|
47
|
+
|
48
|
+
if new_env["HTTP_HOST"]
|
49
|
+
new_env["HTTPS"] ||= "off"
|
50
|
+
new_env["SCRIPT_NAME"] ||= ""
|
51
|
+
end
|
52
|
+
|
53
|
+
if new_env["HTTPS"]
|
54
|
+
new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
|
55
|
+
end
|
56
|
+
|
57
|
+
new_env
|
58
|
+
end
|
59
|
+
|
60
|
+
# Creates a new renderer using the given controller class. See ::new.
|
61
|
+
def self.for(controller, env = nil, defaults = DEFAULTS)
|
49
62
|
new(controller, env, defaults)
|
50
63
|
end
|
51
64
|
|
52
|
-
#
|
53
|
-
|
54
|
-
|
65
|
+
# Creates a new renderer using the same controller, but with a new Rack env.
|
66
|
+
#
|
67
|
+
# ApplicationController.renderer.new(method: "post")
|
68
|
+
#
|
69
|
+
def new(env = nil)
|
70
|
+
self.class.new controller, env, @defaults
|
55
71
|
end
|
56
72
|
|
57
|
-
#
|
73
|
+
# Creates a new renderer using the same controller, but with the given
|
74
|
+
# defaults merged on top of the previous defaults.
|
58
75
|
def with_defaults(defaults)
|
59
|
-
self.class.new controller, @env,
|
76
|
+
self.class.new controller, @env, @defaults.merge(defaults)
|
60
77
|
end
|
61
78
|
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
79
|
+
# Initializes a new Renderer.
|
80
|
+
#
|
81
|
+
# ==== Parameters
|
82
|
+
#
|
83
|
+
# * +controller+ - The controller class to instantiate for rendering.
|
84
|
+
# * +env+ - The Rack env to use for mocking a request when rendering.
|
85
|
+
# Entries can be typical Rack env keys and values, or they can be any of
|
86
|
+
# the following, which will be converted appropriately:
|
87
|
+
# * +:http_host+ - The HTTP host for the incoming request. Converts to
|
88
|
+
# Rack's +HTTP_HOST+.
|
89
|
+
# * +:https+ - Boolean indicating whether the incoming request uses HTTPS.
|
90
|
+
# Converts to Rack's +HTTPS+.
|
91
|
+
# * +:method+ - The HTTP method for the incoming request, case-insensitive.
|
92
|
+
# Converts to Rack's +REQUEST_METHOD+.
|
93
|
+
# * +:script_name+ - The portion of the incoming request's URL path that
|
94
|
+
# corresponds to the application. Converts to Rack's +SCRIPT_NAME+.
|
95
|
+
# * +:input+ - The input stream. Converts to Rack's +rack.input+.
|
96
|
+
# * +defaults+ - Default values for the Rack env. Entries are specified in
|
97
|
+
# the same format as +env+. +env+ will be merged on top of these values.
|
98
|
+
# +defaults+ will be retained when calling #new on a renderer instance.
|
99
|
+
#
|
100
|
+
# If no +http_host+ is specified, the env HTTP host will be derived from the
|
101
|
+
# routes' +default_url_options+. In this case, the +https+ boolean and the
|
102
|
+
# +script_name+ will also be derived from +default_url_options+ if they were
|
103
|
+
# not specified. Additionally, the +https+ boolean will fall back to
|
104
|
+
# +Rails.application.config.force_ssl+ if +default_url_options+ does not
|
105
|
+
# specify a +protocol+.
|
65
106
|
def initialize(controller, env, defaults)
|
66
107
|
@controller = controller
|
67
108
|
@defaults = defaults
|
68
|
-
|
109
|
+
if env.blank? && @defaults == DEFAULTS
|
110
|
+
@env = DEFAULT_ENV
|
111
|
+
else
|
112
|
+
@env = normalize_env(@defaults)
|
113
|
+
@env.merge!(normalize_env(env)) unless env.blank?
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def defaults
|
118
|
+
@defaults = @defaults.dup if @defaults.frozen?
|
119
|
+
@defaults
|
69
120
|
end
|
70
121
|
|
71
122
|
# Renders a template to a string, just like ActionController::Rendering#render_to_string.
|
72
123
|
def render(*args)
|
73
|
-
|
74
|
-
|
75
|
-
request = ActionDispatch::Request.new @env
|
124
|
+
request = ActionDispatch::Request.new(env_for_request)
|
76
125
|
request.routes = controller._routes
|
77
126
|
|
78
127
|
instance = controller.new
|
@@ -83,19 +132,6 @@ module ActionController
|
|
83
132
|
alias_method :render_to_string, :render # :nodoc:
|
84
133
|
|
85
134
|
private
|
86
|
-
def normalize_keys(defaults, env)
|
87
|
-
new_env = {}
|
88
|
-
env.each_pair { |k, v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
|
89
|
-
|
90
|
-
defaults.each_pair do |k, v|
|
91
|
-
key = rack_key_for(k)
|
92
|
-
new_env[key] = rack_value_for(k, v) unless new_env.key?(key)
|
93
|
-
end
|
94
|
-
|
95
|
-
new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
|
96
|
-
new_env
|
97
|
-
end
|
98
|
-
|
99
135
|
RACK_KEY_TRANSLATION = {
|
100
136
|
http_host: "HTTP_HOST",
|
101
137
|
https: "HTTPS",
|
@@ -104,18 +140,15 @@ module ActionController
|
|
104
140
|
input: "rack.input"
|
105
141
|
}
|
106
142
|
|
107
|
-
|
108
|
-
RACK_KEY_TRANSLATION[key] || key.to_s
|
109
|
-
end
|
143
|
+
DEFAULT_ENV = normalize_env(DEFAULTS).freeze # :nodoc:
|
110
144
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
-value.upcase
|
145
|
+
delegate :normalize_env, to: :class
|
146
|
+
|
147
|
+
def env_for_request
|
148
|
+
if @env.key?("HTTP_HOST") || controller._routes.nil?
|
149
|
+
@env.dup
|
117
150
|
else
|
118
|
-
|
151
|
+
controller._routes.default_env.merge(@env)
|
119
152
|
end
|
120
153
|
end
|
121
154
|
end
|
@@ -127,6 +127,9 @@ module ActionController
|
|
127
127
|
fetch_header("PATH_INFO") do |k|
|
128
128
|
set_header k, generated_path
|
129
129
|
end
|
130
|
+
fetch_header("ORIGINAL_FULLPATH") do |k|
|
131
|
+
set_header k, fullpath
|
132
|
+
end
|
130
133
|
path_parameters[:controller] = controller_path
|
131
134
|
path_parameters[:action] = action
|
132
135
|
|
@@ -182,11 +185,12 @@ module ActionController
|
|
182
185
|
class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash # :nodoc:
|
183
186
|
DEFAULT_OPTIONS = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS
|
184
187
|
|
185
|
-
def initialize(session = {})
|
188
|
+
def initialize(session = {}, id = Rack::Session::SessionId.new(SecureRandom.hex(16)))
|
186
189
|
super(nil, nil)
|
187
|
-
@id =
|
190
|
+
@id = id
|
188
191
|
@data = stringify_keys(session)
|
189
192
|
@loaded = true
|
193
|
+
@initially_empty = @data.empty?
|
190
194
|
end
|
191
195
|
|
192
196
|
def exists?
|
@@ -218,21 +222,27 @@ module ActionController
|
|
218
222
|
true
|
219
223
|
end
|
220
224
|
|
225
|
+
def id_was
|
226
|
+
@id
|
227
|
+
end
|
228
|
+
|
221
229
|
private
|
222
230
|
def load!
|
223
231
|
@id
|
224
232
|
end
|
225
233
|
end
|
226
234
|
|
235
|
+
# = Action Controller Test Case
|
236
|
+
#
|
227
237
|
# Superclass for ActionController functional tests. Functional tests allow you to
|
228
238
|
# test a single controller action per test method.
|
229
239
|
#
|
230
240
|
# == Use integration style controller tests over functional style controller tests.
|
231
241
|
#
|
232
|
-
# Rails discourages the use of functional tests in favor of integration tests
|
242
|
+
# \Rails discourages the use of functional tests in favor of integration tests
|
233
243
|
# (use ActionDispatch::IntegrationTest).
|
234
244
|
#
|
235
|
-
# New Rails applications no longer generate functional style controller tests and they should
|
245
|
+
# New \Rails applications no longer generate functional style controller tests and they should
|
236
246
|
# only be used for backward compatibility. Integration style controller tests perform actual
|
237
247
|
# requests, whereas functional style controller tests merely simulate a request. Besides,
|
238
248
|
# integration tests are as fast as functional tests and provide lot of helpers such as +as+,
|
@@ -467,7 +477,7 @@ module ActionController
|
|
467
477
|
#
|
468
478
|
# It's not recommended to make more than one request in the same test. Instance
|
469
479
|
# variables that are set in one request will not persist to the next request,
|
470
|
-
# but it's not guaranteed that all Rails internal state will be reset. Prefer
|
480
|
+
# but it's not guaranteed that all \Rails internal state will be reset. Prefer
|
471
481
|
# ActionDispatch::IntegrationTest for making multiple requests in the same test.
|
472
482
|
#
|
473
483
|
# Note that the request method is not verified.
|
data/lib/action_controller.rb
CHANGED
@@ -2,9 +2,17 @@
|
|
2
2
|
|
3
3
|
require "abstract_controller"
|
4
4
|
require "action_dispatch"
|
5
|
+
require "action_controller/deprecator"
|
5
6
|
require "action_controller/metal/strong_parameters"
|
6
7
|
require "action_controller/metal/exceptions"
|
7
8
|
|
9
|
+
# = Action Controller
|
10
|
+
#
|
11
|
+
# Action Controller is a module of Action Pack.
|
12
|
+
#
|
13
|
+
# Action Controller provides a base controller class that can be subclassed to
|
14
|
+
# implement filters and actions to handle requests. The result of an action is
|
15
|
+
# typically content generated from views.
|
8
16
|
module ActionController
|
9
17
|
extend ActiveSupport::Autoload
|
10
18
|
|
@@ -60,7 +68,6 @@ end
|
|
60
68
|
|
61
69
|
# Common Active Support usage in Action Controller
|
62
70
|
require "active_support/core_ext/module/attribute_accessors"
|
63
|
-
require "active_support/core_ext/load_error"
|
64
71
|
require "active_support/core_ext/module/attr_internal"
|
65
72
|
require "active_support/core_ext/name_error"
|
66
73
|
require "active_support/inflector"
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rack/version"
|
4
|
+
|
5
|
+
module ActionDispatch
|
6
|
+
module Constants
|
7
|
+
# Response Header keys for Rack 2.x and 3.x
|
8
|
+
if Gem::Version.new(Rack::RELEASE) < Gem::Version.new("3")
|
9
|
+
VARY = "Vary"
|
10
|
+
CONTENT_ENCODING = "Content-Encoding"
|
11
|
+
CONTENT_SECURITY_POLICY = "Content-Security-Policy"
|
12
|
+
CONTENT_SECURITY_POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only"
|
13
|
+
LOCATION = "Location"
|
14
|
+
FEATURE_POLICY = "Feature-Policy"
|
15
|
+
X_REQUEST_ID = "X-Request-Id"
|
16
|
+
X_CASCADE = "X-Cascade"
|
17
|
+
SERVER_TIMING = "Server-Timing"
|
18
|
+
STRICT_TRANSPORT_SECURITY = "Strict-Transport-Security"
|
19
|
+
else
|
20
|
+
VARY = "vary"
|
21
|
+
CONTENT_ENCODING = "content-encoding"
|
22
|
+
CONTENT_SECURITY_POLICY = "content-security-policy"
|
23
|
+
CONTENT_SECURITY_POLICY_REPORT_ONLY = "content-security-policy-report-only"
|
24
|
+
LOCATION = "location"
|
25
|
+
FEATURE_POLICY = "feature-policy"
|
26
|
+
X_REQUEST_ID = "x-request-id"
|
27
|
+
X_CASCADE = "x-cascade"
|
28
|
+
SERVER_TIMING = "server-timing"
|
29
|
+
STRICT_TRANSPORT_SECURITY = "strict-transport-security"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -138,15 +138,13 @@ module ActionDispatch
|
|
138
138
|
def cache_control_segments
|
139
139
|
if cache_control = _cache_control
|
140
140
|
cache_control.delete(" ").split(",")
|
141
|
-
else
|
142
|
-
[]
|
143
141
|
end
|
144
142
|
end
|
145
143
|
|
146
144
|
def cache_control_headers
|
147
145
|
cache_control = {}
|
148
146
|
|
149
|
-
cache_control_segments
|
147
|
+
cache_control_segments&.each do |segment|
|
150
148
|
directive, argument = segment.split("=", 2)
|
151
149
|
|
152
150
|
if SPECIAL_KEYS.include? directive
|
@@ -4,6 +4,8 @@ require "active_support/core_ext/object/deep_dup"
|
|
4
4
|
require "active_support/core_ext/array/wrap"
|
5
5
|
|
6
6
|
module ActionDispatch # :nodoc:
|
7
|
+
# = Action Dispatch Content Security Policy
|
8
|
+
#
|
7
9
|
# Configures the HTTP
|
8
10
|
# {Content-Security-Policy}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy]
|
9
11
|
# response header to help protect against XSS and injection attacks.
|
@@ -23,16 +25,11 @@ module ActionDispatch # :nodoc:
|
|
23
25
|
# end
|
24
26
|
class ContentSecurityPolicy
|
25
27
|
class Middleware
|
26
|
-
CONTENT_TYPE = "Content-Type"
|
27
|
-
POLICY = "Content-Security-Policy"
|
28
|
-
POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only"
|
29
|
-
|
30
28
|
def initialize(app)
|
31
29
|
@app = app
|
32
30
|
end
|
33
31
|
|
34
32
|
def call(env)
|
35
|
-
request = ActionDispatch::Request.new env
|
36
33
|
status, headers, _ = response = @app.call(env)
|
37
34
|
|
38
35
|
# Returning CSP headers with a 304 Not Modified is harmful, since nonces in the new
|
@@ -41,6 +38,8 @@ module ActionDispatch # :nodoc:
|
|
41
38
|
|
42
39
|
return response if policy_present?(headers)
|
43
40
|
|
41
|
+
request = ActionDispatch::Request.new env
|
42
|
+
|
44
43
|
if policy = request.content_security_policy
|
45
44
|
nonce = request.content_security_policy_nonce
|
46
45
|
nonce_directives = request.content_security_policy_nonce_directives
|
@@ -54,14 +53,15 @@ module ActionDispatch # :nodoc:
|
|
54
53
|
private
|
55
54
|
def header_name(request)
|
56
55
|
if request.content_security_policy_report_only
|
57
|
-
|
56
|
+
ActionDispatch::Constants::CONTENT_SECURITY_POLICY_REPORT_ONLY
|
58
57
|
else
|
59
|
-
|
58
|
+
ActionDispatch::Constants::CONTENT_SECURITY_POLICY
|
60
59
|
end
|
61
60
|
end
|
62
61
|
|
63
62
|
def policy_present?(headers)
|
64
|
-
headers[
|
63
|
+
headers[ActionDispatch::Constants::CONTENT_SECURITY_POLICY] ||
|
64
|
+
headers[ActionDispatch::Constants::CONTENT_SECURITY_POLICY_REPORT_ONLY]
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
@@ -123,6 +123,7 @@ module ActionDispatch # :nodoc:
|
|
123
123
|
MAPPINGS = {
|
124
124
|
self: "'self'",
|
125
125
|
unsafe_eval: "'unsafe-eval'",
|
126
|
+
unsafe_hashes: "'unsafe-hashes'",
|
126
127
|
unsafe_inline: "'unsafe-inline'",
|
127
128
|
none: "'none'",
|
128
129
|
http: "http:",
|
@@ -4,6 +4,8 @@ require "active_support/parameter_filter"
|
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
6
|
module Http
|
7
|
+
# = Action Dispatch HTTP Filter Parameters
|
8
|
+
#
|
7
9
|
# Allows you to specify sensitive query string and POST parameters to filter
|
8
10
|
# from the request log.
|
9
11
|
#
|
@@ -21,6 +23,7 @@ module ActionDispatch
|
|
21
23
|
@filtered_parameters = nil
|
22
24
|
@filtered_env = nil
|
23
25
|
@filtered_path = nil
|
26
|
+
@parameter_filter = nil
|
24
27
|
end
|
25
28
|
|
26
29
|
# Returns a hash of parameters with all sensitive data replaced.
|
@@ -40,13 +43,16 @@ module ActionDispatch
|
|
40
43
|
@filtered_path ||= query_string.empty? ? path : "#{path}?#{filtered_query_string}"
|
41
44
|
end
|
42
45
|
|
43
|
-
|
44
|
-
def parameter_filter
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
# Returns the +ActiveSupport::ParameterFilter+ object used to filter in this request.
|
47
|
+
def parameter_filter
|
48
|
+
@parameter_filter ||= if has_header?("action_dispatch.parameter_filter")
|
49
|
+
parameter_filter_for get_header("action_dispatch.parameter_filter")
|
50
|
+
else
|
51
|
+
NULL_PARAM_FILTER
|
52
|
+
end
|
48
53
|
end
|
49
54
|
|
55
|
+
private
|
50
56
|
def env_filter # :doc:
|
51
57
|
user_key = fetch_header("action_dispatch.parameter_filter") {
|
52
58
|
return NULL_ENV_FILTER
|
@@ -16,7 +16,20 @@ module ActionDispatch
|
|
16
16
|
|
17
17
|
included do
|
18
18
|
mattr_accessor :ignore_accept_header, default: false
|
19
|
-
|
19
|
+
|
20
|
+
def return_only_media_type_on_content_type=(value)
|
21
|
+
ActionDispatch.deprecator.warn(
|
22
|
+
"`config.action_dispatch.return_only_request_media_type_on_content_type` is deprecated and will" \
|
23
|
+
" be removed in Rails 7.2."
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def return_only_media_type_on_content_type
|
28
|
+
ActionDispatch.deprecator.warn(
|
29
|
+
"`config.action_dispatch.return_only_request_media_type_on_content_type` is deprecated and will" \
|
30
|
+
" be removed in Rails 7.2."
|
31
|
+
)
|
32
|
+
end
|
20
33
|
end
|
21
34
|
|
22
35
|
# The MIME type of the HTTP request, such as Mime[:xml].
|
@@ -33,19 +46,6 @@ module ActionDispatch
|
|
33
46
|
end
|
34
47
|
end
|
35
48
|
|
36
|
-
def content_type
|
37
|
-
if self.class.return_only_media_type_on_content_type
|
38
|
-
ActiveSupport::Deprecation.warn(
|
39
|
-
"Rails 7.1 will return Content-Type header without modification." \
|
40
|
-
" If you want just the MIME type, please use `#media_type` instead."
|
41
|
-
)
|
42
|
-
|
43
|
-
content_mime_type&.to_s
|
44
|
-
else
|
45
|
-
super
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
49
|
def has_content_type? # :nodoc:
|
50
50
|
get_header "CONTENT_TYPE"
|
51
51
|
end
|
@@ -72,7 +72,7 @@ module ActionDispatch
|
|
72
72
|
# GET /posts/5.xhtml | request.format => Mime[:html]
|
73
73
|
# GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first
|
74
74
|
#
|
75
|
-
def format(
|
75
|
+
def format(_view_path = nil)
|
76
76
|
formats.first || Mime::NullType.instance
|
77
77
|
end
|
78
78
|
|
@@ -81,7 +81,7 @@ module ActionDispatch
|
|
81
81
|
v = if params_readable?
|
82
82
|
Array(Mime[parameters[:format]])
|
83
83
|
elsif use_accept_header && valid_accept_header
|
84
|
-
accepts
|
84
|
+
accepts.dup
|
85
85
|
elsif extension_format = format_from_path_extension
|
86
86
|
[extension_format]
|
87
87
|
elsif xhr?
|
@@ -90,7 +90,7 @@ module ActionDispatch
|
|
90
90
|
[Mime[:html]]
|
91
91
|
end
|
92
92
|
|
93
|
-
v
|
93
|
+
v.select! do |format|
|
94
94
|
format.symbol || format.ref == "*/*"
|
95
95
|
end
|
96
96
|
|
@@ -132,7 +132,7 @@ module ActionDispatch
|
|
132
132
|
# Sets the \formats by string extensions. This differs from #format= by allowing you
|
133
133
|
# to set multiple, ordered formats, which is useful when you want to have a fallback.
|
134
134
|
#
|
135
|
-
# In this example, the +:iphone+ format will be used if it's available, otherwise it'll
|
135
|
+
# In this example, the +:iphone+ format will be used if it's available, otherwise it'll fall back
|
136
136
|
# to the +:html+ format.
|
137
137
|
#
|
138
138
|
# class ApplicationController < ActionController::Base
|
@@ -172,22 +172,22 @@ module ActionDispatch
|
|
172
172
|
# in which case we assume you're a browser and send HTML.
|
173
173
|
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
|
174
174
|
|
175
|
-
def params_readable?
|
175
|
+
def params_readable?
|
176
176
|
parameters[:format]
|
177
177
|
rescue *RESCUABLE_MIME_FORMAT_ERRORS
|
178
178
|
false
|
179
179
|
end
|
180
180
|
|
181
|
-
def valid_accept_header
|
181
|
+
def valid_accept_header
|
182
182
|
(xhr? && (accept.present? || content_mime_type)) ||
|
183
183
|
(accept.present? && !accept.match?(BROWSER_LIKE_ACCEPTS))
|
184
184
|
end
|
185
185
|
|
186
|
-
def use_accept_header
|
186
|
+
def use_accept_header
|
187
187
|
!self.class.ignore_accept_header
|
188
188
|
end
|
189
189
|
|
190
|
-
def format_from_path_extension
|
190
|
+
def format_from_path_extension
|
191
191
|
path = get_header("action_dispatch.original_path") || get_header("PATH_INFO")
|
192
192
|
if match = path && path.match(/\.(\w+)\z/)
|
193
193
|
Mime[match.captures.first]
|