actionpack 7.0.8.7 → 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 +90 -537
  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 +212 -199
  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 +48 -45
  71. data/lib/action_dispatch/http/filter_parameters.rb +18 -8
  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 -27
  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 +6 -4
  169. data/lib/action_pack/version.rb +3 -1
  170. data/lib/action_pack.rb +18 -17
  171. metadata +86 -27
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "stringio"
4
6
 
5
7
  require "active_support/inflector"
@@ -72,7 +74,7 @@ module ActionDispatch
72
74
 
73
75
  PASS_NOT_FOUND = Class.new { # :nodoc:
74
76
  def self.action(_); self; end
75
- def self.call(_); [404, { "X-Cascade" => "pass" }, []]; end
77
+ def self.call(_); [404, { Constants::X_CASCADE => "pass" }, []]; end
76
78
  def self.action_encoding_template(action); false; end
77
79
  }
78
80
 
@@ -102,26 +104,26 @@ module ActionDispatch
102
104
 
103
105
  # Returns true if the request has a header matching the given key parameter.
104
106
  #
105
- # request.key? :ip_spoofing_check # => true
107
+ # request.key? :ip_spoofing_check # => true
106
108
  def key?(key)
107
109
  has_header? key
108
110
  end
109
111
 
110
- # HTTP methods from {RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1}[https://www.ietf.org/rfc/rfc2616.txt]
112
+ # HTTP methods from [RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1](https://www.ietf.org/rfc/rfc2616.txt)
111
113
  RFC2616 = %w(OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT)
112
- # HTTP methods from {RFC 2518: HTTP Extensions for Distributed Authoring -- WEBDAV}[https://www.ietf.org/rfc/rfc2518.txt]
114
+ # HTTP methods from [RFC 2518: HTTP Extensions for Distributed Authoring -- WEBDAV](https://www.ietf.org/rfc/rfc2518.txt)
113
115
  RFC2518 = %w(PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
114
- # HTTP methods from {RFC 3253: Versioning Extensions to WebDAV}[https://www.ietf.org/rfc/rfc3253.txt]
116
+ # HTTP methods from [RFC 3253: Versioning Extensions to WebDAV](https://www.ietf.org/rfc/rfc3253.txt)
115
117
  RFC3253 = %w(VERSION-CONTROL REPORT CHECKOUT CHECKIN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE BASELINE-CONTROL MKACTIVITY)
116
- # HTTP methods from {RFC 3648: WebDAV Ordered Collections Protocol}[https://www.ietf.org/rfc/rfc3648.txt]
118
+ # HTTP methods from [RFC 3648: WebDAV Ordered Collections Protocol](https://www.ietf.org/rfc/rfc3648.txt)
117
119
  RFC3648 = %w(ORDERPATCH)
118
- # HTTP methods from {RFC 3744: WebDAV Access Control Protocol}[https://www.ietf.org/rfc/rfc3744.txt]
120
+ # HTTP methods from [RFC 3744: WebDAV Access Control Protocol](https://www.ietf.org/rfc/rfc3744.txt)
119
121
  RFC3744 = %w(ACL)
120
- # HTTP methods from {RFC 5323: WebDAV SEARCH}[https://www.ietf.org/rfc/rfc5323.txt]
122
+ # HTTP methods from [RFC 5323: WebDAV SEARCH](https://www.ietf.org/rfc/rfc5323.txt)
121
123
  RFC5323 = %w(SEARCH)
122
- # HTTP methods from {RFC 4791: Calendaring Extensions to WebDAV}[https://www.ietf.org/rfc/rfc4791.txt]
124
+ # HTTP methods from [RFC 4791: Calendaring Extensions to WebDAV](https://www.ietf.org/rfc/rfc4791.txt)
123
125
  RFC4791 = %w(MKCALENDAR)
124
- # HTTP methods from {RFC 5789: PATCH Method for HTTP}[https://www.ietf.org/rfc/rfc5789.txt]
126
+ # HTTP methods from [RFC 5789: PATCH Method for HTTP](https://www.ietf.org/rfc/rfc5789.txt)
125
127
  RFC5789 = %w(PATCH)
126
128
 
127
129
  HTTP_METHODS = RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC4791 + RFC5789
@@ -135,16 +137,27 @@ module ActionDispatch
135
137
 
136
138
  alias raw_request_method request_method # :nodoc:
137
139
 
138
- # Returns the HTTP \method that the application should see.
139
- # In the case where the \method was overridden by a middleware
140
- # (for instance, if a HEAD request was converted to a GET,
141
- # or if a _method parameter was used to determine the \method
142
- # the application should use), this \method returns the overridden
143
- # value, not the original.
140
+ # Returns the HTTP method that the application should see. In the case where the
141
+ # method was overridden by a middleware (for instance, if a HEAD request was
142
+ # converted to a GET, or if a _method parameter was used to determine the method
143
+ # the application should use), this method returns the overridden value, not the
144
+ # original.
144
145
  def request_method
145
146
  @request_method ||= check_method(super)
146
147
  end
147
148
 
149
+ # Returns the URI pattern of the matched route for the request, using the same
150
+ # format as `bin/rails routes`:
151
+ #
152
+ # request.route_uri_pattern # => "/:controller(/:action(/:id))(.:format)"
153
+ def route_uri_pattern
154
+ get_header("action_dispatch.route_uri_pattern")
155
+ end
156
+
157
+ def route_uri_pattern=(pattern) # :nodoc:
158
+ set_header("action_dispatch.route_uri_pattern", pattern)
159
+ end
160
+
148
161
  def routes # :nodoc:
149
162
  get_header("action_dispatch.routes")
150
163
  end
@@ -179,24 +192,27 @@ module ActionDispatch
179
192
  get_header "action_dispatch.http_auth_salt"
180
193
  end
181
194
 
182
- def show_exceptions? # :nodoc:
183
- # We're treating `nil` as "unset", and we want the default setting to be
184
- # `true`. This logic should be extracted to `env_config` and calculated
185
- # once.
186
- !(get_header("action_dispatch.show_exceptions") == false)
187
- end
188
-
189
195
  # Returns a symbol form of the #request_method.
190
196
  def request_method_symbol
191
197
  HTTP_METHOD_LOOKUP[request_method]
192
198
  end
193
199
 
194
- # Returns the original value of the environment's REQUEST_METHOD,
195
- # even if it was overridden by middleware. See #request_method for
196
- # more information.
197
- def method
198
- @method ||= check_method(get_header("rack.methodoverride.original_method") || get_header("REQUEST_METHOD"))
200
+ # Returns the original value of the environment's REQUEST_METHOD, even if it was
201
+ # overridden by middleware. See #request_method for more information.
202
+ #
203
+ # For debugging purposes, when called with arguments this method will fall back
204
+ # to Object#method
205
+ def method(*args)
206
+ if args.empty?
207
+ @method ||= check_method(
208
+ get_header("rack.methodoverride.original_method") ||
209
+ get_header("REQUEST_METHOD")
210
+ )
211
+ else
212
+ super
213
+ end
199
214
  end
215
+ ruby2_keywords(:method)
200
216
 
201
217
  # Returns a symbol form of the #method.
202
218
  def method_symbol
@@ -205,72 +221,72 @@ module ActionDispatch
205
221
 
206
222
  # Provides access to the request's HTTP headers, for example:
207
223
  #
208
- # request.headers["Content-Type"] # => "text/plain"
224
+ # request.headers["Content-Type"] # => "text/plain"
209
225
  def headers
210
226
  @headers ||= Http::Headers.new(self)
211
227
  end
212
228
 
213
- # Early Hints is an HTTP/2 status code that indicates hints to help a client start
214
- # making preparations for processing the final response.
229
+ # Early Hints is an HTTP/2 status code that indicates hints to help a client
230
+ # start making preparations for processing the final response.
215
231
  #
216
- # If the env contains +rack.early_hints+ then the server accepts HTTP2 push for Link headers.
232
+ # If the env contains `rack.early_hints` then the server accepts HTTP2 push for
233
+ # link headers.
217
234
  #
218
- # The +send_early_hints+ method accepts a hash of links as follows:
235
+ # The `send_early_hints` method accepts a hash of links as follows:
219
236
  #
220
- # send_early_hints("Link" => "</style.css>; rel=preload; as=style\n</script.js>; rel=preload")
237
+ # send_early_hints("link" => "</style.css>; rel=preload; as=style,</script.js>; rel=preload")
221
238
  #
222
- # If you are using +javascript_include_tag+ or +stylesheet_link_tag+ the
223
- # Early Hints headers are included by default if supported.
239
+ # If you are using `javascript_include_tag` or `stylesheet_link_tag` the Early
240
+ # Hints headers are included by default if supported.
224
241
  def send_early_hints(links)
225
- return unless env["rack.early_hints"]
226
-
227
- env["rack.early_hints"].call(links)
242
+ env["rack.early_hints"]&.call(links)
228
243
  end
229
244
 
230
- # Returns a +String+ with the last requested path including their params.
245
+ # Returns a `String` with the last requested path including their params.
231
246
  #
232
- # # get '/foo'
233
- # request.original_fullpath # => '/foo'
247
+ # # get '/foo'
248
+ # request.original_fullpath # => '/foo'
234
249
  #
235
- # # get '/foo?bar'
236
- # request.original_fullpath # => '/foo?bar'
250
+ # # get '/foo?bar'
251
+ # request.original_fullpath # => '/foo?bar'
237
252
  def original_fullpath
238
253
  @original_fullpath ||= (get_header("ORIGINAL_FULLPATH") || fullpath)
239
254
  end
240
255
 
241
- # Returns the +String+ full path including params of the last URL requested.
256
+ # Returns the `String` full path including params of the last URL requested.
242
257
  #
243
- # # get "/articles"
244
- # request.fullpath # => "/articles"
258
+ # # get "/articles"
259
+ # request.fullpath # => "/articles"
245
260
  #
246
- # # get "/articles?page=2"
247
- # request.fullpath # => "/articles?page=2"
261
+ # # get "/articles?page=2"
262
+ # request.fullpath # => "/articles?page=2"
248
263
  def fullpath
249
264
  @fullpath ||= super
250
265
  end
251
266
 
252
- # Returns the original request URL as a +String+.
267
+ # Returns the original request URL as a `String`.
253
268
  #
254
- # # get "/articles?page=2"
255
- # request.original_url # => "http://www.example.com/articles?page=2"
269
+ # # get "/articles?page=2"
270
+ # request.original_url # => "http://www.example.com/articles?page=2"
256
271
  def original_url
257
272
  base_url + original_fullpath
258
273
  end
259
274
 
260
- # The +String+ MIME type of the request.
275
+ # The `String` MIME type of the request.
261
276
  #
262
- # # get "/articles"
263
- # request.media_type # => "application/x-www-form-urlencoded"
277
+ # # get "/articles"
278
+ # request.media_type # => "application/x-www-form-urlencoded"
264
279
  def media_type
265
280
  content_mime_type&.to_s
266
281
  end
267
282
 
268
283
  # Returns the content length of the request as an integer.
269
284
  def content_length
285
+ return raw_post.bytesize if headers.key?("Transfer-Encoding")
270
286
  super.to_i
271
287
  end
272
288
 
273
- # Returns true if the +X-Requested-With+ header contains "XMLHttpRequest"
289
+ # Returns true if the `X-Requested-With` header contains "XMLHttpRequest"
274
290
  # (case-insensitive), which may need to be manually added depending on the
275
291
  # choice of JavaScript libraries and frameworks.
276
292
  def xml_http_request?
@@ -278,13 +294,13 @@ module ActionDispatch
278
294
  end
279
295
  alias :xhr? :xml_http_request?
280
296
 
281
- # Returns the IP address of client as a +String+.
297
+ # Returns the IP address of client as a `String`.
282
298
  def ip
283
299
  @ip ||= super
284
300
  end
285
301
 
286
- # Returns the IP address of client as a +String+,
287
- # usually set by the RemoteIp middleware.
302
+ # Returns the IP address of client as a `String`, usually set by the RemoteIp
303
+ # middleware.
288
304
  def remote_ip
289
305
  @remote_ip ||= (get_header("action_dispatch.remote_ip") || ip).to_s
290
306
  end
@@ -296,12 +312,14 @@ module ActionDispatch
296
312
 
297
313
  ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
298
314
 
299
- # Returns the unique request id, which is based on either the +X-Request-Id+ header that can
300
- # be generated by a firewall, load balancer, or web server, or by the RequestId middleware
301
- # (which sets the +action_dispatch.request_id+ environment variable).
315
+ # Returns the unique request id, which is based on either the `X-Request-Id`
316
+ # header that can be generated by a firewall, load balancer, or web server, or
317
+ # by the RequestId middleware (which sets the `action_dispatch.request_id`
318
+ # environment variable).
302
319
  #
303
- # This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
304
- # This relies on the Rack variable set by the ActionDispatch::RequestId middleware.
320
+ # This unique ID is useful for tracing a request from end-to-end as part of
321
+ # logging or debugging. This relies on the Rack variable set by the
322
+ # ActionDispatch::RequestId middleware.
305
323
  def request_id
306
324
  get_header ACTION_DISPATCH_REQUEST_ID
307
325
  end
@@ -317,13 +335,11 @@ module ActionDispatch
317
335
  (get_header("SERVER_SOFTWARE") && /^([a-zA-Z]+)/ =~ get_header("SERVER_SOFTWARE")) ? $1.downcase : nil
318
336
  end
319
337
 
320
- # Read the request \body. This is useful for web services that need to
321
- # work with raw requests directly.
338
+ # Read the request body. This is useful for web services that need to work with
339
+ # raw requests directly.
322
340
  def raw_post
323
341
  unless has_header? "RAW_POST_DATA"
324
- raw_post_body = body
325
- set_header("RAW_POST_DATA", raw_post_body.read(content_length))
326
- raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
342
+ set_header("RAW_POST_DATA", read_body_stream)
327
343
  end
328
344
  get_header "RAW_POST_DATA"
329
345
  end
@@ -339,14 +355,13 @@ module ActionDispatch
339
355
  end
340
356
  end
341
357
 
342
- # Determine whether the request body contains form-data by checking
343
- # the request +Content-Type+ for one of the media-types:
344
- # +application/x-www-form-urlencoded+ or +multipart/form-data+. The
345
- # list of form-data media types can be modified through the
346
- # +FORM_DATA_MEDIA_TYPES+ array.
358
+ # Determine whether the request body contains form-data by checking the request
359
+ # `Content-Type` for one of the media-types: `application/x-www-form-urlencoded`
360
+ # or `multipart/form-data`. The list of form-data media types can be modified
361
+ # through the `FORM_DATA_MEDIA_TYPES` array.
347
362
  #
348
- # A request body is not assumed to contain form-data when no
349
- # +Content-Type+ header is provided and the request_method is POST.
363
+ # A request body is not assumed to contain form-data when no `Content-Type`
364
+ # header is provided and the request_method is POST.
350
365
  def form_data?
351
366
  FORM_DATA_MEDIA_TYPES.include?(media_type)
352
367
  end
@@ -357,6 +372,7 @@ module ActionDispatch
357
372
 
358
373
  def reset_session
359
374
  session.destroy
375
+ reset_csrf_token
360
376
  end
361
377
 
362
378
  def session=(session) # :nodoc:
@@ -398,8 +414,8 @@ module ActionDispatch
398
414
  end
399
415
  alias :request_parameters :POST
400
416
 
401
- # Returns the authorization header regardless of whether it was specified directly or through one of the
402
- # proxy alternatives.
417
+ # Returns the authorization header regardless of whether it was specified
418
+ # directly or through one of the proxy alternatives.
403
419
  def authorization
404
420
  get_header("HTTP_AUTHORIZATION") ||
405
421
  get_header("X-HTTP_AUTHORIZATION") ||
@@ -428,15 +444,52 @@ module ActionDispatch
428
444
  "#<#{self.class.name} #{method} #{original_url.dump} for #{remote_ip}>"
429
445
  end
430
446
 
447
+ def reset_csrf_token
448
+ controller_instance.reset_csrf_token(self) if controller_instance.respond_to?(:reset_csrf_token)
449
+ end
450
+
451
+ def commit_csrf_token
452
+ controller_instance.commit_csrf_token(self) if controller_instance.respond_to?(:commit_csrf_token)
453
+ end
454
+
431
455
  private
432
456
  def check_method(name)
433
- HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS[0...-1].join(', ')}, and #{HTTP_METHODS[-1]}")
457
+ if name
458
+ HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(locale: false)}")
459
+ end
460
+
434
461
  name
435
462
  end
436
463
 
437
464
  def default_session
438
465
  Session.disabled(self)
439
466
  end
467
+
468
+ def read_body_stream
469
+ if body_stream
470
+ reset_stream(body_stream) do
471
+ if headers.key?("Transfer-Encoding")
472
+ body_stream.read # Read body stream until EOF if "Transfer-Encoding" is present
473
+ else
474
+ body_stream.read(content_length)
475
+ end
476
+ end
477
+ end
478
+ end
479
+
480
+ def reset_stream(body_stream)
481
+ if body_stream.respond_to?(:rewind)
482
+ body_stream.rewind
483
+
484
+ content = yield
485
+
486
+ body_stream.rewind
487
+
488
+ content
489
+ else
490
+ yield
491
+ end
492
+ end
440
493
  end
441
494
  end
442
495