actionpack 7.0.8 → 7.1.0.beta1

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.

Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +320 -387
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/abstract_controller/base.rb +19 -10
  6. data/lib/abstract_controller/caching/fragments.rb +2 -0
  7. data/lib/abstract_controller/callbacks.rb +31 -6
  8. data/lib/abstract_controller/deprecator.rb +7 -0
  9. data/lib/abstract_controller/helpers.rb +61 -18
  10. data/lib/abstract_controller/railties/routes_helpers.rb +1 -16
  11. data/lib/abstract_controller/rendering.rb +3 -3
  12. data/lib/abstract_controller/translation.rb +1 -5
  13. data/lib/abstract_controller/url_for.rb +2 -0
  14. data/lib/abstract_controller.rb +6 -0
  15. data/lib/action_controller/api.rb +5 -3
  16. data/lib/action_controller/base.rb +3 -17
  17. data/lib/action_controller/caching.rb +2 -0
  18. data/lib/action_controller/deprecator.rb +7 -0
  19. data/lib/action_controller/form_builder.rb +2 -0
  20. data/lib/action_controller/log_subscriber.rb +16 -4
  21. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  22. data/lib/action_controller/metal/data_streaming.rb +2 -0
  23. data/lib/action_controller/metal/default_headers.rb +2 -0
  24. data/lib/action_controller/metal/etag_with_flash.rb +2 -0
  25. data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
  26. data/lib/action_controller/metal/exceptions.rb +8 -0
  27. data/lib/action_controller/metal/head.rb +8 -6
  28. data/lib/action_controller/metal/helpers.rb +3 -14
  29. data/lib/action_controller/metal/http_authentication.rb +11 -4
  30. data/lib/action_controller/metal/implicit_render.rb +5 -3
  31. data/lib/action_controller/metal/instrumentation.rb +8 -1
  32. data/lib/action_controller/metal/live.rb +24 -0
  33. data/lib/action_controller/metal/mime_responds.rb +2 -2
  34. data/lib/action_controller/metal/params_wrapper.rb +3 -1
  35. data/lib/action_controller/metal/permissions_policy.rb +1 -1
  36. data/lib/action_controller/metal/redirecting.rb +6 -6
  37. data/lib/action_controller/metal/renderers.rb +2 -2
  38. data/lib/action_controller/metal/rendering.rb +0 -7
  39. data/lib/action_controller/metal/request_forgery_protection.rb +138 -50
  40. data/lib/action_controller/metal/rescue.rb +2 -0
  41. data/lib/action_controller/metal/streaming.rb +70 -30
  42. data/lib/action_controller/metal/strong_parameters.rb +89 -50
  43. data/lib/action_controller/metal/url_for.rb +7 -0
  44. data/lib/action_controller/metal.rb +79 -21
  45. data/lib/action_controller/railtie.rb +22 -9
  46. data/lib/action_controller/renderer.rb +98 -65
  47. data/lib/action_controller/test_case.rb +15 -5
  48. data/lib/action_controller.rb +8 -1
  49. data/lib/action_dispatch/constants.rb +32 -0
  50. data/lib/action_dispatch/deprecator.rb +7 -0
  51. data/lib/action_dispatch/http/cache.rb +1 -3
  52. data/lib/action_dispatch/http/content_security_policy.rb +9 -8
  53. data/lib/action_dispatch/http/filter_parameters.rb +11 -5
  54. data/lib/action_dispatch/http/headers.rb +2 -0
  55. data/lib/action_dispatch/http/mime_negotiation.rb +21 -21
  56. data/lib/action_dispatch/http/mime_type.rb +35 -12
  57. data/lib/action_dispatch/http/mime_types.rb +3 -1
  58. data/lib/action_dispatch/http/parameters.rb +1 -1
  59. data/lib/action_dispatch/http/permissions_policy.rb +39 -17
  60. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  61. data/lib/action_dispatch/http/request.rb +48 -14
  62. data/lib/action_dispatch/http/response.rb +78 -59
  63. data/lib/action_dispatch/http/upload.rb +2 -0
  64. data/lib/action_dispatch/journey/formatter.rb +8 -2
  65. data/lib/action_dispatch/journey/path/pattern.rb +14 -14
  66. data/lib/action_dispatch/journey/route.rb +3 -2
  67. data/lib/action_dispatch/journey/router.rb +5 -4
  68. data/lib/action_dispatch/journey/routes.rb +2 -2
  69. data/lib/action_dispatch/log_subscriber.rb +23 -0
  70. data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -6
  71. data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
  72. data/lib/action_dispatch/middleware/callbacks.rb +2 -0
  73. data/lib/action_dispatch/middleware/cookies.rb +81 -98
  74. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -25
  75. data/lib/action_dispatch/middleware/debug_locks.rb +4 -1
  76. data/lib/action_dispatch/middleware/debug_view.rb +7 -2
  77. data/lib/action_dispatch/middleware/exception_wrapper.rb +181 -27
  78. data/lib/action_dispatch/middleware/executor.rb +1 -1
  79. data/lib/action_dispatch/middleware/flash.rb +7 -0
  80. data/lib/action_dispatch/middleware/host_authorization.rb +6 -3
  81. data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
  82. data/lib/action_dispatch/middleware/reloader.rb +7 -5
  83. data/lib/action_dispatch/middleware/remote_ip.rb +17 -16
  84. data/lib/action_dispatch/middleware/request_id.rb +2 -0
  85. data/lib/action_dispatch/middleware/server_timing.rb +4 -4
  86. data/lib/action_dispatch/middleware/session/abstract_store.rb +5 -0
  87. data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
  88. data/lib/action_dispatch/middleware/session/cookie_store.rb +11 -5
  89. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
  90. data/lib/action_dispatch/middleware/show_exceptions.rb +19 -15
  91. data/lib/action_dispatch/middleware/ssl.rb +18 -6
  92. data/lib/action_dispatch/middleware/stack.rb +7 -2
  93. data/lib/action_dispatch/middleware/static.rb +12 -8
  94. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  95. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
  96. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  97. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  98. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  99. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  100. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  101. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  102. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  103. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  104. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  105. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  106. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  107. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
  108. data/lib/action_dispatch/railtie.rb +14 -4
  109. data/lib/action_dispatch/request/session.rb +16 -6
  110. data/lib/action_dispatch/request/utils.rb +8 -3
  111. data/lib/action_dispatch/routing/inspector.rb +54 -6
  112. data/lib/action_dispatch/routing/mapper.rb +26 -14
  113. data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
  114. data/lib/action_dispatch/routing/redirection.rb +15 -6
  115. data/lib/action_dispatch/routing/route_set.rb +52 -22
  116. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  117. data/lib/action_dispatch/routing/url_for.rb +5 -1
  118. data/lib/action_dispatch/routing.rb +4 -4
  119. data/lib/action_dispatch/system_test_case.rb +3 -3
  120. data/lib/action_dispatch/system_testing/browser.rb +5 -6
  121. data/lib/action_dispatch/system_testing/driver.rb +13 -21
  122. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
  123. data/lib/action_dispatch/testing/assertions/response.rb +13 -6
  124. data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
  125. data/lib/action_dispatch/testing/assertions.rb +3 -1
  126. data/lib/action_dispatch/testing/integration.rb +27 -17
  127. data/lib/action_dispatch/testing/request_encoder.rb +4 -1
  128. data/lib/action_dispatch/testing/test_process.rb +4 -3
  129. data/lib/action_dispatch/testing/test_request.rb +1 -1
  130. data/lib/action_dispatch/testing/test_response.rb +23 -9
  131. data/lib/action_dispatch.rb +37 -4
  132. data/lib/action_pack/gem_version.rb +4 -4
  133. data/lib/action_pack/version.rb +1 -1
  134. data/lib/action_pack.rb +1 -1
  135. metadata +51 -29
@@ -4,6 +4,8 @@ require "active_support/core_ext/array/extract_options"
4
4
  require "action_dispatch/middleware/stack"
5
5
 
6
6
  module ActionController
7
+ # = Action Controller \MiddlewareStack
8
+ #
7
9
  # Extend ActionDispatch middleware stack to make it aware of options
8
10
  # allowing the following syntax in controllers:
9
11
  #
@@ -58,7 +60,9 @@ module ActionController
58
60
  end
59
61
  end
60
62
 
61
- # <tt>ActionController::Metal</tt> is the simplest possible controller, providing a
63
+ # = Action Controller \Metal
64
+ #
65
+ # +ActionController::Metal+ is the simplest possible controller, providing a
62
66
  # valid Rack interface without the additional niceties provided by
63
67
  # ActionController::Base.
64
68
  #
@@ -78,9 +82,9 @@ module ActionController
78
82
  # The +action+ method returns a valid Rack application for the \Rails
79
83
  # router to dispatch to.
80
84
  #
81
- # == Rendering Helpers
85
+ # == \Rendering \Helpers
82
86
  #
83
- # <tt>ActionController::Metal</tt> by default provides no utilities for rendering
87
+ # +ActionController::Metal+ by default provides no utilities for rendering
84
88
  # views, partials, or other responses aside from explicitly calling of
85
89
  # <tt>response_body=</tt>, <tt>content_type=</tt>, and <tt>status=</tt>. To
86
90
  # add the render helpers you're used to having in a normal controller, you
@@ -96,7 +100,7 @@ module ActionController
96
100
  # end
97
101
  # end
98
102
  #
99
- # == Redirection Helpers
103
+ # == Redirection \Helpers
100
104
  #
101
105
  # To add redirection helpers to your metal controller, do the following:
102
106
  #
@@ -109,7 +113,7 @@ module ActionController
109
113
  # end
110
114
  # end
111
115
  #
112
- # == Other Helpers
116
+ # == Other \Helpers
113
117
  #
114
118
  # You can refer to the modules included in ActionController::Base to see
115
119
  # other features you can bring into your metal controller.
@@ -118,8 +122,8 @@ module ActionController
118
122
  abstract!
119
123
 
120
124
  # Returns the last part of the controller's name, underscored, without the ending
121
- # <tt>Controller</tt>. For instance, PostsController returns <tt>posts</tt>.
122
- # Namespaces are left out, so Admin::PostsController returns <tt>posts</tt> as well.
125
+ # <tt>Controller</tt>. For instance, +PostsController+ returns <tt>posts</tt>.
126
+ # Namespaces are left out, so +Admin::PostsController+ returns <tt>posts</tt> as well.
123
127
  #
124
128
  # ==== Returns
125
129
  # * <tt>string</tt>
@@ -137,20 +141,53 @@ module ActionController
137
141
  false
138
142
  end
139
143
 
144
+ class << self
145
+ private
146
+ def inherited(subclass)
147
+ super
148
+ subclass.middleware_stack = middleware_stack.dup
149
+ subclass.class_eval do
150
+ @controller_name = nil
151
+ end
152
+ end
153
+ end
154
+
140
155
  # Delegates to the class's ::controller_name.
141
156
  def controller_name
142
157
  self.class.controller_name
143
158
  end
144
159
 
145
- attr_internal :response, :request
160
+ ##
161
+ # :attr_reader: request
162
+ #
163
+ # The ActionDispatch::Request instance for the current request.
164
+ attr_internal :request
165
+
166
+ ##
167
+ # :attr_reader: response
168
+ #
169
+ # The ActionDispatch::Response instance for the current response.
170
+ attr_internal_reader :response
171
+
172
+ ##
173
+ # The ActionDispatch::Request::Session instance for the current request.
174
+ # See further details in the
175
+ # {Active Controller Session guide}[https://guides.rubyonrails.org/action_controller_overview.html#session].
146
176
  delegate :session, to: "@_request"
147
- delegate :headers, :status=, :location=, :content_type=,
177
+
178
+ ##
179
+ # Delegates to ActionDispatch::Response#headers.
180
+ delegate :headers, to: "@_response"
181
+
182
+ delegate :status=, :location=, :content_type=,
148
183
  :status, :location, :content_type, :media_type, to: "@_response"
149
184
 
150
185
  def initialize
151
186
  @_request = nil
152
187
  @_response = nil
188
+ @_response_body = nil
153
189
  @_routes = nil
190
+ @_params = nil
154
191
  super
155
192
  end
156
193
 
@@ -164,17 +201,19 @@ module ActionController
164
201
 
165
202
  alias :response_code :status # :nodoc:
166
203
 
167
- # Basic url_for that can be overridden for more robust functionality.
204
+ # Basic \url_for that can be overridden for more robust functionality.
168
205
  def url_for(string)
169
206
  string
170
207
  end
171
208
 
172
209
  def response_body=(body)
173
- body = [body] unless body.nil? || body.respond_to?(:each)
174
- response.reset_body!
175
- return unless body
176
- response.body = body
177
- super
210
+ if body
211
+ body = [body] if body.is_a?(String)
212
+ response.body = body
213
+ super
214
+ else
215
+ response.reset_body!
216
+ end
178
217
  end
179
218
 
180
219
  # Tests if render or redirect has already happened.
@@ -191,9 +230,22 @@ module ActionController
191
230
  end
192
231
 
193
232
  def set_response!(response) # :nodoc:
233
+ if @_response
234
+ _, _, body = @_response
235
+ body.close if body.respond_to?(:close)
236
+ end
237
+
194
238
  @_response = response
195
239
  end
196
240
 
241
+ # Assign the response and mark it as committed. No further processing will occur.
242
+ def response=(response)
243
+ set_response!(response)
244
+
245
+ # Force `performed?` to return true:
246
+ @_response_body = true
247
+ end
248
+
197
249
  def set_request!(request) # :nodoc:
198
250
  @_request = request
199
251
  @_request.controller_instance = self
@@ -209,11 +261,6 @@ module ActionController
209
261
 
210
262
  class_attribute :middleware_stack, default: ActionController::MiddlewareStack.new
211
263
 
212
- def self.inherited(base) # :nodoc:
213
- base.middleware_stack = middleware_stack.dup
214
- super
215
- end
216
-
217
264
  class << self
218
265
  # Pushes the given Rack middleware and its arguments to the bottom of the
219
266
  # middleware stack.
@@ -222,7 +269,18 @@ module ActionController
222
269
  end
223
270
  end
224
271
 
225
- # Alias for +middleware_stack+.
272
+ # The middleware stack used by this controller.
273
+ #
274
+ # By default uses a variation of ActionDispatch::MiddlewareStack which
275
+ # allows for the following syntax:
276
+ #
277
+ # class PostsController < ApplicationController
278
+ # use AuthenticationMiddleware, except: [:index, :show]
279
+ # end
280
+ #
281
+ # Read more about {Rails middleware
282
+ # stack}[https://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack]
283
+ # in the guides.
226
284
  def self.middleware
227
285
  middleware_stack
228
286
  end
@@ -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 = (Rails.env.test? || Rails.env.development?) ? :log : false
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) { context[:controller].class.name if context[:controller] }
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
- # ActionController::Renderer allows you to render arbitrary templates
5
- # without requirement of being in controller actions.
4
+ # = Action Controller \Renderer
6
5
  #
7
- # You get a concrete renderer class by invoking ActionController::Base#renderer.
8
- # For example:
6
+ # ActionController::Renderer allows you to render arbitrary templates without
7
+ # being inside a controller action.
9
8
  #
10
- # ApplicationController.renderer
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
- # #render allows you to use the same options that you can use when rendering in a controller.
21
- # For example:
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
- # * by changing renderer defaults, like
14
+ # and render a template by calling the #render method:
29
15
  #
30
- # ApplicationController.renderer.defaults # => hash with default Rack environment
16
+ # ApplicationController.renderer.render template: "posts/show", assigns: { post: Post.first }
17
+ # PostsController.renderer.render :show, assigns: { post: Post.first }
31
18
  #
32
- # * by initializing an instance of renderer by passing it a custom environment.
19
+ # As a shortcut, you can also call +render+ directly on the controller class itself:
33
20
  #
34
- # ApplicationController.renderer.new(method: 'post', https: true)
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 :defaults, :controller
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
- # Create a new renderer instance for a specific controller class.
48
- def self.for(controller, env = {}, defaults = DEFAULTS.dup)
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
- # Create a new renderer for the same controller but with a new env.
53
- def new(env = {})
54
- self.class.new controller, env, defaults
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
- # Create a new renderer for the same controller but with new defaults.
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, self.defaults.merge(defaults)
76
+ self.class.new controller, @env, @defaults.merge(defaults)
60
77
  end
61
78
 
62
- # Accepts a custom Rack environment to render templates in.
63
- # It will be merged with the default Rack environment defined by
64
- # +ActionController::Renderer::DEFAULTS+.
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
- @env = normalize_keys defaults, env
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
- raise "missing controller" unless controller
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
- def rack_key_for(key)
108
- RACK_KEY_TRANSLATION[key] || key.to_s
109
- end
143
+ DEFAULT_ENV = normalize_env(DEFAULTS).freeze # :nodoc:
110
144
 
111
- def rack_value_for(key, value)
112
- case key
113
- when :https
114
- value ? "on" : "off"
115
- when :method
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
- value
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 = Rack::Session::SessionId.new(SecureRandom.hex(16))
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.
@@ -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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionDispatch
4
+ def self.deprecator # :nodoc:
5
+ @deprecator ||= ActiveSupport::Deprecation.new
6
+ end
7
+ 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.each do |segment|
147
+ cache_control_segments&.each do |segment|
150
148
  directive, argument = segment.split("=", 2)
151
149
 
152
150
  if SPECIAL_KEYS.include? directive