actionpack 7.0.8.1 → 7.2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +94 -500
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +119 -106
  7. data/lib/abstract_controller/caching/fragments.rb +51 -52
  8. data/lib/abstract_controller/caching.rb +2 -0
  9. data/lib/abstract_controller/callbacks.rb +94 -67
  10. data/lib/abstract_controller/collector.rb +6 -6
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +2 -0
  13. data/lib/abstract_controller/helpers.rb +121 -91
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +3 -16
  16. data/lib/abstract_controller/rendering.rb +14 -13
  17. data/lib/abstract_controller/translation.rb +12 -30
  18. data/lib/abstract_controller/url_for.rb +9 -5
  19. data/lib/abstract_controller.rb +8 -0
  20. data/lib/action_controller/api/api_rendering.rb +2 -0
  21. data/lib/action_controller/api.rb +78 -73
  22. data/lib/action_controller/base.rb +199 -141
  23. data/lib/action_controller/caching.rb +16 -11
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +21 -16
  26. data/lib/action_controller/log_subscriber.rb +19 -5
  27. data/lib/action_controller/metal/allow_browser.rb +123 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  29. data/lib/action_controller/metal/conditional_get.rb +187 -174
  30. data/lib/action_controller/metal/content_security_policy.rb +26 -25
  31. data/lib/action_controller/metal/cookies.rb +4 -2
  32. data/lib/action_controller/metal/data_streaming.rb +65 -54
  33. data/lib/action_controller/metal/default_headers.rb +6 -2
  34. data/lib/action_controller/metal/etag_with_flash.rb +4 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +18 -14
  36. data/lib/action_controller/metal/exceptions.rb +19 -9
  37. data/lib/action_controller/metal/flash.rb +12 -10
  38. data/lib/action_controller/metal/head.rb +20 -16
  39. data/lib/action_controller/metal/helpers.rb +64 -67
  40. data/lib/action_controller/metal/http_authentication.rb +214 -200
  41. data/lib/action_controller/metal/implicit_render.rb +21 -17
  42. data/lib/action_controller/metal/instrumentation.rb +22 -12
  43. data/lib/action_controller/metal/live.rb +125 -92
  44. data/lib/action_controller/metal/logging.rb +6 -4
  45. data/lib/action_controller/metal/mime_responds.rb +151 -142
  46. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  47. data/lib/action_controller/metal/params_wrapper.rb +58 -58
  48. data/lib/action_controller/metal/permissions_policy.rb +14 -13
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +110 -84
  51. data/lib/action_controller/metal/renderers.rb +50 -49
  52. data/lib/action_controller/metal/rendering.rb +103 -82
  53. data/lib/action_controller/metal/request_forgery_protection.rb +279 -161
  54. data/lib/action_controller/metal/rescue.rb +12 -8
  55. data/lib/action_controller/metal/streaming.rb +174 -132
  56. data/lib/action_controller/metal/strong_parameters.rb +598 -473
  57. data/lib/action_controller/metal/testing.rb +2 -0
  58. data/lib/action_controller/metal/url_for.rb +23 -14
  59. data/lib/action_controller/metal.rb +145 -61
  60. data/lib/action_controller/railtie.rb +25 -9
  61. data/lib/action_controller/railties/helpers.rb +2 -0
  62. data/lib/action_controller/renderer.rb +105 -66
  63. data/lib/action_controller/template_assertions.rb +4 -2
  64. data/lib/action_controller/test_case.rb +157 -128
  65. data/lib/action_controller.rb +17 -3
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +28 -29
  69. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +69 -49
  71. data/lib/action_dispatch/http/filter_parameters.rb +27 -12
  72. data/lib/action_dispatch/http/filter_redirect.rb +22 -1
  73. data/lib/action_dispatch/http/headers.rb +23 -21
  74. data/lib/action_dispatch/http/mime_negotiation.rb +37 -48
  75. data/lib/action_dispatch/http/mime_type.rb +60 -30
  76. data/lib/action_dispatch/http/mime_types.rb +5 -1
  77. data/lib/action_dispatch/http/parameters.rb +12 -10
  78. data/lib/action_dispatch/http/permissions_policy.rb +32 -34
  79. data/lib/action_dispatch/http/rack_cache.rb +4 -0
  80. data/lib/action_dispatch/http/request.rb +132 -79
  81. data/lib/action_dispatch/http/response.rb +136 -103
  82. data/lib/action_dispatch/http/upload.rb +19 -15
  83. data/lib/action_dispatch/http/url.rb +75 -73
  84. data/lib/action_dispatch/journey/formatter.rb +19 -6
  85. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  88. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  89. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  90. data/lib/action_dispatch/journey/parser.rb +4 -3
  91. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  92. data/lib/action_dispatch/journey/path/pattern.rb +18 -15
  93. data/lib/action_dispatch/journey/route.rb +12 -9
  94. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  95. data/lib/action_dispatch/journey/router.rb +13 -10
  96. data/lib/action_dispatch/journey/routes.rb +6 -4
  97. data/lib/action_dispatch/journey/scanner.rb +4 -2
  98. data/lib/action_dispatch/journey/visitors.rb +2 -0
  99. data/lib/action_dispatch/journey.rb +2 -0
  100. data/lib/action_dispatch/log_subscriber.rb +25 -0
  101. data/lib/action_dispatch/middleware/actionable_exceptions.rb +7 -6
  102. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  103. data/lib/action_dispatch/middleware/callbacks.rb +4 -0
  104. data/lib/action_dispatch/middleware/cookies.rb +192 -194
  105. data/lib/action_dispatch/middleware/debug_exceptions.rb +36 -27
  106. data/lib/action_dispatch/middleware/debug_locks.rb +18 -13
  107. data/lib/action_dispatch/middleware/debug_view.rb +9 -2
  108. data/lib/action_dispatch/middleware/exception_wrapper.rb +181 -27
  109. data/lib/action_dispatch/middleware/executor.rb +9 -1
  110. data/lib/action_dispatch/middleware/flash.rb +65 -46
  111. data/lib/action_dispatch/middleware/host_authorization.rb +22 -17
  112. data/lib/action_dispatch/middleware/public_exceptions.rb +12 -8
  113. data/lib/action_dispatch/middleware/reloader.rb +9 -5
  114. data/lib/action_dispatch/middleware/remote_ip.rb +88 -83
  115. data/lib/action_dispatch/middleware/request_id.rb +15 -8
  116. data/lib/action_dispatch/middleware/server_timing.rb +8 -6
  117. data/lib/action_dispatch/middleware/session/abstract_store.rb +7 -0
  118. data/lib/action_dispatch/middleware/session/cache_store.rb +14 -7
  119. data/lib/action_dispatch/middleware/session/cookie_store.rb +32 -25
  120. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +9 -3
  121. data/lib/action_dispatch/middleware/show_exceptions.rb +42 -28
  122. data/lib/action_dispatch/middleware/ssl.rb +60 -45
  123. data/lib/action_dispatch/middleware/stack.rb +15 -9
  124. data/lib/action_dispatch/middleware/static.rb +40 -34
  125. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  126. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
  127. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  129. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  130. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  132. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  134. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  136. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  137. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  138. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +47 -38
  139. data/lib/action_dispatch/railtie.rb +12 -4
  140. data/lib/action_dispatch/request/session.rb +39 -27
  141. data/lib/action_dispatch/request/utils.rb +10 -3
  142. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  143. data/lib/action_dispatch/routing/inspector.rb +59 -9
  144. data/lib/action_dispatch/routing/mapper.rb +686 -639
  145. data/lib/action_dispatch/routing/polymorphic_routes.rb +70 -61
  146. data/lib/action_dispatch/routing/redirection.rb +52 -38
  147. data/lib/action_dispatch/routing/route_set.rb +106 -62
  148. data/lib/action_dispatch/routing/routes_proxy.rb +16 -19
  149. data/lib/action_dispatch/routing/url_for.rb +131 -122
  150. data/lib/action_dispatch/routing.rb +152 -150
  151. data/lib/action_dispatch/system_test_case.rb +91 -81
  152. data/lib/action_dispatch/system_testing/browser.rb +27 -19
  153. data/lib/action_dispatch/system_testing/driver.rb +16 -22
  154. data/lib/action_dispatch/system_testing/server.rb +2 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +53 -31
  156. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  157. data/lib/action_dispatch/testing/assertion_response.rb +9 -7
  158. data/lib/action_dispatch/testing/assertions/response.rb +36 -26
  159. data/lib/action_dispatch/testing/assertions/routing.rb +203 -95
  160. data/lib/action_dispatch/testing/assertions.rb +5 -1
  161. data/lib/action_dispatch/testing/integration.rb +240 -229
  162. data/lib/action_dispatch/testing/request_encoder.rb +6 -1
  163. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  164. data/lib/action_dispatch/testing/test_process.rb +14 -9
  165. data/lib/action_dispatch/testing/test_request.rb +4 -2
  166. data/lib/action_dispatch/testing/test_response.rb +34 -19
  167. data/lib/action_dispatch.rb +52 -21
  168. data/lib/action_pack/gem_version.rb +5 -3
  169. data/lib/action_pack/version.rb +3 -1
  170. data/lib/action_pack.rb +18 -17
  171. metadata +91 -32
@@ -1,74 +1,78 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/module/attribute_accessors"
4
6
  require "action_dispatch/http/filter_redirect"
5
7
  require "action_dispatch/http/cache"
6
8
  require "monitor"
7
9
 
8
10
  module ActionDispatch # :nodoc:
11
+ # # Action Dispatch Response
12
+ #
9
13
  # Represents an HTTP response generated by a controller action. Use it to
10
14
  # retrieve the current state of the response, or customize the response. It can
11
- # either represent a real HTTP response (i.e. one that is meant to be sent
12
- # back to the web browser) or a TestResponse (i.e. one that is generated
13
- # from integration tests).
15
+ # either represent a real HTTP response (i.e. one that is meant to be sent back
16
+ # to the web browser) or a TestResponse (i.e. one that is generated from
17
+ # integration tests).
14
18
  #
15
- # \Response is mostly a Ruby on \Rails framework implementation detail, and
16
- # should never be used directly in controllers. Controllers should use the
17
- # methods defined in ActionController::Base instead. For example, if you want
18
- # to set the HTTP response's content MIME type, then use
19
- # ActionControllerBase#headers instead of Response#headers.
19
+ # The Response object for the current request is exposed on controllers as
20
+ # ActionController::Metal#response. ActionController::Metal also provides a few
21
+ # additional methods that delegate to attributes of the Response such as
22
+ # ActionController::Metal#headers.
20
23
  #
21
- # Nevertheless, integration tests may want to inspect controller responses in
22
- # more detail, and that's when \Response can be useful for application
23
- # developers. Integration test methods such as
24
- # Integration::RequestHelpers#get and Integration::RequestHelpers#post return
25
- # objects of type TestResponse (which are of course also of type \Response).
24
+ # Integration tests will likely also want to inspect responses in more detail.
25
+ # Methods such as Integration::RequestHelpers#get and
26
+ # Integration::RequestHelpers#post return instances of TestResponse (which
27
+ # inherits from Response) for this purpose.
26
28
  #
27
29
  # For example, the following demo integration test prints the body of the
28
30
  # controller response to the console:
29
31
  #
30
- # class DemoControllerTest < ActionDispatch::IntegrationTest
31
- # def test_print_root_path_to_console
32
- # get('/')
33
- # puts response.body
34
- # end
35
- # end
32
+ # class DemoControllerTest < ActionDispatch::IntegrationTest
33
+ # def test_print_root_path_to_console
34
+ # get('/')
35
+ # puts response.body
36
+ # end
37
+ # end
36
38
  class Response
37
- class Header < DelegateClass(Hash) # :nodoc:
38
- def initialize(response, header)
39
- @response = response
40
- super(header)
41
- end
42
-
43
- def []=(k, v)
44
- if @response.sending? || @response.sent?
45
- raise ActionDispatch::IllegalStateError, "header already sent"
46
- end
47
-
48
- super
49
- end
50
-
51
- def merge(other)
52
- self.class.new @response, __getobj__.merge(other)
53
- end
54
-
55
- def to_hash
56
- __getobj__.dup
57
- end
39
+ begin
40
+ # For `Rack::Headers` (Rack 3+):
41
+ require "rack/headers"
42
+ Headers = ::Rack::Headers
43
+ rescue LoadError
44
+ # For `Rack::Utils::HeaderHash`:
45
+ require "rack/utils"
46
+ Headers = ::Rack::Utils::HeaderHash
58
47
  end
59
48
 
49
+ # To be deprecated:
50
+ Header = Headers
51
+
60
52
  # The request that the response is responding to.
61
53
  attr_accessor :request
62
54
 
63
55
  # The HTTP status code.
64
56
  attr_reader :status
65
57
 
66
- # Get headers for this response.
67
- attr_reader :header
58
+ # The headers for the response.
59
+ #
60
+ # header["Content-Type"] # => "text/plain"
61
+ # header["Content-Type"] = "application/json"
62
+ # header["Content-Type"] # => "application/json"
63
+ #
64
+ # Also aliased as `headers`.
65
+ #
66
+ # headers["Content-Type"] # => "text/plain"
67
+ # headers["Content-Type"] = "application/json"
68
+ # headers["Content-Type"] # => "application/json"
69
+ #
70
+ # Also aliased as `header` for compatibility.
71
+ attr_reader :headers
68
72
 
69
- alias_method :headers, :header
73
+ alias_method :header, :headers
70
74
 
71
- delegate :[], :[]=, to: :@header
75
+ delegate :[], :[]=, to: :@headers
72
76
 
73
77
  def each(&block)
74
78
  sending!
@@ -79,7 +83,6 @@ module ActionDispatch # :nodoc:
79
83
 
80
84
  CONTENT_TYPE = "Content-Type"
81
85
  SET_COOKIE = "Set-Cookie"
82
- LOCATION = "Location"
83
86
  NO_CONTENT_CODES = [100, 101, 102, 103, 204, 205, 304]
84
87
 
85
88
  cattr_accessor :default_charset, default: "utf-8"
@@ -102,6 +105,12 @@ module ActionDispatch # :nodoc:
102
105
  @str_body = nil
103
106
  end
104
107
 
108
+ def to_ary
109
+ @buf.respond_to?(:to_ary) ?
110
+ @buf.to_ary :
111
+ @buf.each
112
+ end
113
+
105
114
  def body
106
115
  @str_body ||= begin
107
116
  buf = +""
@@ -117,6 +126,7 @@ module ActionDispatch # :nodoc:
117
126
  @response.commit!
118
127
  @buf.push string
119
128
  end
129
+ alias_method :<<, :write
120
130
 
121
131
  def each(&block)
122
132
  if @str_body
@@ -146,9 +156,9 @@ module ActionDispatch # :nodoc:
146
156
  end
147
157
  end
148
158
 
149
- def self.create(status = 200, header = {}, body = [], default_headers: self.default_headers)
150
- header = merge_default_headers(header, default_headers)
151
- new status, header, body
159
+ def self.create(status = 200, headers = {}, body = [], default_headers: self.default_headers)
160
+ headers = merge_default_headers(headers, default_headers)
161
+ new status, headers, body
152
162
  end
153
163
 
154
164
  def self.merge_default_headers(original, default)
@@ -158,10 +168,14 @@ module ActionDispatch # :nodoc:
158
168
  # The underlying body, as a streamable object.
159
169
  attr_reader :stream
160
170
 
161
- def initialize(status = 200, header = {}, body = [])
171
+ def initialize(status = 200, headers = nil, body = [])
162
172
  super()
163
173
 
164
- @header = Header.new(self, header)
174
+ @headers = Headers.new
175
+
176
+ headers&.each do |key, value|
177
+ @headers[key] = value
178
+ end
165
179
 
166
180
  self.body, self.status = body, status
167
181
 
@@ -175,10 +189,10 @@ module ActionDispatch # :nodoc:
175
189
  yield self if block_given?
176
190
  end
177
191
 
178
- def has_header?(key); headers.key? key; end
179
- def get_header(key); headers[key]; end
180
- def set_header(key, v); headers[key] = v; end
181
- def delete_header(key); headers.delete key; end
192
+ def has_header?(key); @headers.key? key; end
193
+ def get_header(key); @headers[key]; end
194
+ def set_header(key, v); @headers[key] = v; end
195
+ def delete_header(key); @headers.delete key; end
182
196
 
183
197
  def await_commit
184
198
  synchronize do
@@ -217,18 +231,30 @@ module ActionDispatch # :nodoc:
217
231
  def committed?; synchronize { @committed }; end
218
232
  def sent?; synchronize { @sent }; end
219
233
 
234
+ ##
235
+ # :method: location
236
+ #
237
+ # Location of the response.
238
+
239
+ ##
240
+ # :method: location=
241
+ #
242
+ # :call-seq: location=(location)
243
+ #
244
+ # Sets the location of the response
245
+
220
246
  # Sets the HTTP status code.
221
247
  def status=(status)
222
248
  @status = Rack::Utils.status_code(status)
223
249
  end
224
250
 
225
- # Sets the HTTP response's content MIME type. For example, in the controller
226
- # you could write this:
251
+ # Sets the HTTP response's content MIME type. For example, in the controller you
252
+ # could write this:
227
253
  #
228
- # response.content_type = "text/plain"
254
+ # response.content_type = "text/plain"
229
255
  #
230
- # If a character set has been defined for this response (see charset=) then
231
- # the character set information will also be included in the content type
256
+ # If a character set has been defined for this response (see #charset=) then the
257
+ # character set information will also be included in the content type
232
258
  # information.
233
259
  def content_type=(content_type)
234
260
  return unless content_type
@@ -255,11 +281,11 @@ module ActionDispatch # :nodoc:
255
281
  end
256
282
  end
257
283
 
258
- # Sets the HTTP character set. In case of +nil+ parameter
259
- # it sets the charset to +default_charset+.
284
+ # Sets the HTTP character set. In case of `nil` parameter it sets the charset to
285
+ # `default_charset`.
260
286
  #
261
- # response.charset = 'utf-16' # => 'utf-16'
262
- # response.charset = nil # => 'utf-8'
287
+ # response.charset = 'utf-16' # => 'utf-16'
288
+ # response.charset = nil # => 'utf-8'
263
289
  def charset=(charset)
264
290
  content_type = parsed_content_type_header.mime_type
265
291
  if false == charset
@@ -269,8 +295,8 @@ module ActionDispatch # :nodoc:
269
295
  end
270
296
  end
271
297
 
272
- # The charset of the response. HTML wants to know the encoding of the
273
- # content you're giving them, so we need to send that along.
298
+ # The charset of the response. HTML wants to know the encoding of the content
299
+ # you're giving them, so we need to send that along.
274
300
  def charset
275
301
  header_info = parsed_content_type_header
276
302
  header_info.charset || self.class.default_charset
@@ -281,26 +307,26 @@ module ActionDispatch # :nodoc:
281
307
  @status
282
308
  end
283
309
 
284
- # Returns a string to ensure compatibility with <tt>Net::HTTPResponse</tt>.
310
+ # Returns a string to ensure compatibility with `Net::HTTPResponse`.
285
311
  def code
286
312
  @status.to_s
287
313
  end
288
314
 
289
315
  # Returns the corresponding message for the current HTTP status code:
290
316
  #
291
- # response.status = 200
292
- # response.message # => "OK"
317
+ # response.status = 200
318
+ # response.message # => "OK"
293
319
  #
294
- # response.status = 404
295
- # response.message # => "Not Found"
320
+ # response.status = 404
321
+ # response.message # => "Not Found"
296
322
  #
297
323
  def message
298
324
  Rack::Utils::HTTP_STATUS_CODES[@status]
299
325
  end
300
326
  alias_method :status_message, :message
301
327
 
302
- # Returns the content of the response as a string. This contains the contents
303
- # of any calls to <tt>render</tt>.
328
+ # Returns the content of the response as a string. This contains the contents of
329
+ # any calls to `render`.
304
330
  def body
305
331
  @stream.body
306
332
  end
@@ -320,9 +346,9 @@ module ActionDispatch # :nodoc:
320
346
  end
321
347
  end
322
348
 
323
- # Avoid having to pass an open file handle as the response body.
324
- # Rack::Sendfile will usually intercept the response and uses
325
- # the path directly, so there is no reason to open the file.
349
+ # Avoid having to pass an open file handle as the response body. Rack::Sendfile
350
+ # will usually intercept the response and uses the path directly, so there is no
351
+ # reason to open the file.
326
352
  class FileBody # :nodoc:
327
353
  attr_reader :to_path
328
354
 
@@ -344,7 +370,7 @@ module ActionDispatch # :nodoc:
344
370
  end
345
371
  end
346
372
 
347
- # Send the file stored at +path+ as the response body.
373
+ # Send the file stored at `path` as the response body.
348
374
  def send_file(path)
349
375
  commit!
350
376
  @stream = FileBody.new(path)
@@ -371,26 +397,25 @@ module ActionDispatch # :nodoc:
371
397
  if stream.respond_to?(:abort)
372
398
  stream.abort
373
399
  elsif stream.respond_to?(:close)
374
- # `stream.close` should really be reserved for a close from the
375
- # other direction, but we must fall back to it for
376
- # compatibility.
400
+ # `stream.close` should really be reserved for a close from the other direction,
401
+ # but we must fall back to it for compatibility.
377
402
  stream.close
378
403
  end
379
404
  end
380
405
 
381
- # Turns the Response into a Rack-compatible array of the status, headers,
382
- # and body. Allows explicit splatting:
406
+ # Turns the Response into a Rack-compatible array of the status, headers, and
407
+ # body. Allows explicit splatting:
383
408
  #
384
- # status, headers, body = *response
409
+ # status, headers, body = *response
385
410
  def to_a
386
411
  commit!
387
- rack_response @status, @header.to_hash
412
+ rack_response @status, @headers.to_hash
388
413
  end
389
414
  alias prepare! to_a
390
415
 
391
416
  # Returns the response cookies, converted to a Hash of (name => value) pairs
392
417
  #
393
- # assert_equal 'AuthorOfNewPage', r.cookies['author']
418
+ # assert_equal 'AuthorOfNewPage', r.cookies['author']
394
419
  def cookies
395
420
  cookies = {}
396
421
  if header = get_header(SET_COOKIE)
@@ -444,15 +469,13 @@ module ActionDispatch # :nodoc:
444
469
  end
445
470
 
446
471
  def before_sending
447
- # Normally we've already committed by now, but it's possible
448
- # (e.g., if the controller action tries to read back its own
449
- # response) to get here before that. In that case, we must force
450
- # an "early" commit: we're about to freeze the headers, so this is
451
- # our last chance.
472
+ # Normally we've already committed by now, but it's possible (e.g., if the
473
+ # controller action tries to read back its own response) to get here before
474
+ # that. In that case, we must force an "early" commit: we're about to freeze the
475
+ # headers, so this is our last chance.
452
476
  commit! unless committed?
453
477
 
454
- headers.freeze
455
- request.commit_cookie_jar! unless committed?
478
+ @request.commit_cookie_jar! unless committed?
456
479
  end
457
480
 
458
481
  def build_buffer(response, body)
@@ -476,13 +499,9 @@ module ActionDispatch # :nodoc:
476
499
  @response = response
477
500
  end
478
501
 
479
- def each(*args, &block)
480
- @response.each(*args, &block)
481
- end
482
-
483
502
  def close
484
- # Rack "close" maps to Response#abort, and *not* Response#close
485
- # (which is used when the controller's finished writing)
503
+ # Rack "close" maps to Response#abort, and **not** Response#close (which is used
504
+ # when the controller's finished writing)
486
505
  @response.abort
487
506
  end
488
507
 
@@ -490,14 +509,28 @@ module ActionDispatch # :nodoc:
490
509
  @response.body
491
510
  end
492
511
 
512
+ BODY_METHODS = { to_ary: true, each: true, call: true, to_path: true }
513
+
493
514
  def respond_to?(method, include_private = false)
494
- if method.to_sym == :to_path
515
+ if BODY_METHODS.key?(method)
495
516
  @response.stream.respond_to?(method)
496
517
  else
497
518
  super
498
519
  end
499
520
  end
500
521
 
522
+ def to_ary
523
+ @response.stream.to_ary
524
+ end
525
+
526
+ def each(*args, &block)
527
+ @response.each(*args, &block)
528
+ end
529
+
530
+ def call(*arguments, &block)
531
+ @response.stream.call(*arguments, &block)
532
+ end
533
+
501
534
  def to_path
502
535
  @response.stream.to_path
503
536
  end
@@ -505,16 +538,16 @@ module ActionDispatch # :nodoc:
505
538
 
506
539
  def handle_no_content!
507
540
  if NO_CONTENT_CODES.include?(@status)
508
- @header.delete CONTENT_TYPE
509
- @header.delete "Content-Length"
541
+ @headers.delete CONTENT_TYPE
542
+ @headers.delete "Content-Length"
510
543
  end
511
544
  end
512
545
 
513
- def rack_response(status, header)
546
+ def rack_response(status, headers)
514
547
  if NO_CONTENT_CODES.include?(status)
515
- [status, header, []]
548
+ [status, headers, []]
516
549
  else
517
- [status, header, RackBody.new(self)]
550
+ [status, headers, RackBody.new(self)]
518
551
  end
519
552
  end
520
553
  end
@@ -1,15 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Http
7
+ # # Action Dispatch HTTP UploadedFile
8
+ #
5
9
  # Models uploaded files.
6
10
  #
7
- # The actual file is accessible via the +tempfile+ accessor, though some
8
- # of its interface is available directly for convenience.
11
+ # The actual file is accessible via the `tempfile` accessor, though some of its
12
+ # interface is available directly for convenience.
9
13
  #
10
- # Uploaded files are temporary files whose lifespan is one request. When
11
- # the object is finalized Ruby unlinks the file, so there is no need to
12
- # clean them with a separate maintenance task.
14
+ # Uploaded files are temporary files whose lifespan is one request. When the
15
+ # object is finalized Ruby unlinks the file, so there is no need to clean them
16
+ # with a separate maintenance task.
13
17
  class UploadedFile
14
18
  # The basename of the file in the client.
15
19
  attr_accessor :original_filename
@@ -17,8 +21,8 @@ module ActionDispatch
17
21
  # A string with the MIME type of the file.
18
22
  attr_accessor :content_type
19
23
 
20
- # A +Tempfile+ object with the actual uploaded file. Note that some of
21
- # its interface is available directly.
24
+ # A `Tempfile` object with the actual uploaded file. Note that some of its
25
+ # interface is available directly.
22
26
  attr_accessor :tempfile
23
27
 
24
28
  # A string with the headers of the multipart request.
@@ -55,42 +59,42 @@ module ActionDispatch
55
59
  end
56
60
  end
57
61
 
58
- # Shortcut for +tempfile.read+.
62
+ # Shortcut for `tempfile.read`.
59
63
  def read(length = nil, buffer = nil)
60
64
  @tempfile.read(length, buffer)
61
65
  end
62
66
 
63
- # Shortcut for +tempfile.open+.
67
+ # Shortcut for `tempfile.open`.
64
68
  def open
65
69
  @tempfile.open
66
70
  end
67
71
 
68
- # Shortcut for +tempfile.close+.
72
+ # Shortcut for `tempfile.close`.
69
73
  def close(unlink_now = false)
70
74
  @tempfile.close(unlink_now)
71
75
  end
72
76
 
73
- # Shortcut for +tempfile.path+.
77
+ # Shortcut for `tempfile.path`.
74
78
  def path
75
79
  @tempfile.path
76
80
  end
77
81
 
78
- # Shortcut for +tempfile.to_path+.
82
+ # Shortcut for `tempfile.to_path`.
79
83
  def to_path
80
84
  @tempfile.to_path
81
85
  end
82
86
 
83
- # Shortcut for +tempfile.rewind+.
87
+ # Shortcut for `tempfile.rewind`.
84
88
  def rewind
85
89
  @tempfile.rewind
86
90
  end
87
91
 
88
- # Shortcut for +tempfile.size+.
92
+ # Shortcut for `tempfile.size`.
89
93
  def size
90
94
  @tempfile.size
91
95
  end
92
96
 
93
- # Shortcut for +tempfile.eof?+.
97
+ # Shortcut for `tempfile.eof?`.
94
98
  def eof?
95
99
  @tempfile.eof?
96
100
  end