actionpack 4.2.10 → 7.2.0.rc1

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 (202) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +86 -600
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -14
  5. data/lib/abstract_controller/asset_paths.rb +5 -1
  6. data/lib/abstract_controller/base.rb +166 -136
  7. data/lib/abstract_controller/caching/fragments.rb +149 -0
  8. data/lib/abstract_controller/caching.rb +68 -0
  9. data/lib/abstract_controller/callbacks.rb +126 -57
  10. data/lib/abstract_controller/collector.rb +13 -15
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +8 -0
  13. data/lib/abstract_controller/helpers.rb +181 -132
  14. data/lib/abstract_controller/logger.rb +5 -1
  15. data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
  16. data/lib/abstract_controller/rendering.rb +56 -56
  17. data/lib/abstract_controller/translation.rb +29 -15
  18. data/lib/abstract_controller/url_for.rb +15 -11
  19. data/lib/abstract_controller.rb +21 -5
  20. data/lib/action_controller/api/api_rendering.rb +18 -0
  21. data/lib/action_controller/api.rb +154 -0
  22. data/lib/action_controller/base.rb +219 -155
  23. data/lib/action_controller/caching.rb +28 -68
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +55 -0
  26. data/lib/action_controller/log_subscriber.rb +35 -22
  27. data/lib/action_controller/metal/allow_browser.rb +119 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
  29. data/lib/action_controller/metal/conditional_get.rb +259 -122
  30. data/lib/action_controller/metal/content_security_policy.rb +86 -0
  31. data/lib/action_controller/metal/cookies.rb +9 -5
  32. data/lib/action_controller/metal/data_streaming.rb +87 -104
  33. data/lib/action_controller/metal/default_headers.rb +21 -0
  34. data/lib/action_controller/metal/etag_with_flash.rb +22 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
  36. data/lib/action_controller/metal/exceptions.rb +71 -24
  37. data/lib/action_controller/metal/flash.rb +26 -19
  38. data/lib/action_controller/metal/head.rb +45 -36
  39. data/lib/action_controller/metal/helpers.rb +80 -64
  40. data/lib/action_controller/metal/http_authentication.rb +297 -244
  41. data/lib/action_controller/metal/implicit_render.rb +57 -9
  42. data/lib/action_controller/metal/instrumentation.rb +76 -64
  43. data/lib/action_controller/metal/live.rb +238 -176
  44. data/lib/action_controller/metal/logging.rb +22 -0
  45. data/lib/action_controller/metal/mime_responds.rb +177 -166
  46. data/lib/action_controller/metal/parameter_encoding.rb +84 -0
  47. data/lib/action_controller/metal/params_wrapper.rb +145 -118
  48. data/lib/action_controller/metal/permissions_policy.rb +38 -0
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +203 -64
  51. data/lib/action_controller/metal/renderers.rb +108 -65
  52. data/lib/action_controller/metal/rendering.rb +216 -56
  53. data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
  54. data/lib/action_controller/metal/rescue.rb +19 -21
  55. data/lib/action_controller/metal/streaming.rb +179 -138
  56. data/lib/action_controller/metal/strong_parameters.rb +1058 -382
  57. data/lib/action_controller/metal/testing.rb +11 -17
  58. data/lib/action_controller/metal/url_for.rb +37 -21
  59. data/lib/action_controller/metal.rb +236 -138
  60. data/lib/action_controller/railtie.rb +89 -11
  61. data/lib/action_controller/railties/helpers.rb +5 -1
  62. data/lib/action_controller/renderer.rb +161 -0
  63. data/lib/action_controller/template_assertions.rb +13 -0
  64. data/lib/action_controller/test_case.rb +425 -497
  65. data/lib/action_controller.rb +44 -22
  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 +119 -63
  69. data/lib/action_dispatch/http/content_disposition.rb +47 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +364 -0
  71. data/lib/action_dispatch/http/filter_parameters.rb +36 -34
  72. data/lib/action_dispatch/http/filter_redirect.rb +24 -12
  73. data/lib/action_dispatch/http/headers.rb +66 -31
  74. data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
  75. data/lib/action_dispatch/http/mime_type.rb +196 -136
  76. data/lib/action_dispatch/http/mime_types.rb +25 -7
  77. data/lib/action_dispatch/http/parameters.rb +97 -45
  78. data/lib/action_dispatch/http/permissions_policy.rb +187 -0
  79. data/lib/action_dispatch/http/rack_cache.rb +6 -0
  80. data/lib/action_dispatch/http/request.rb +299 -170
  81. data/lib/action_dispatch/http/response.rb +311 -160
  82. data/lib/action_dispatch/http/upload.rb +52 -23
  83. data/lib/action_dispatch/http/url.rb +201 -125
  84. data/lib/action_dispatch/journey/formatter.rb +110 -50
  85. data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
  88. data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
  89. data/lib/action_dispatch/journey/nodes/node.rb +100 -20
  90. data/lib/action_dispatch/journey/parser.rb +19 -17
  91. data/lib/action_dispatch/journey/parser.y +4 -3
  92. data/lib/action_dispatch/journey/parser_extras.rb +14 -4
  93. data/lib/action_dispatch/journey/path/pattern.rb +79 -63
  94. data/lib/action_dispatch/journey/route.rb +108 -44
  95. data/lib/action_dispatch/journey/router/utils.rb +41 -29
  96. data/lib/action_dispatch/journey/router.rb +64 -57
  97. data/lib/action_dispatch/journey/routes.rb +23 -21
  98. data/lib/action_dispatch/journey/scanner.rb +28 -17
  99. data/lib/action_dispatch/journey/visitors.rb +100 -54
  100. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  101. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  102. data/lib/action_dispatch/journey.rb +7 -5
  103. data/lib/action_dispatch/log_subscriber.rb +25 -0
  104. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  105. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  106. data/lib/action_dispatch/middleware/callbacks.rb +7 -6
  107. data/lib/action_dispatch/middleware/cookies.rb +471 -328
  108. data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
  109. data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
  110. data/lib/action_dispatch/middleware/debug_view.rb +73 -0
  111. data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
  112. data/lib/action_dispatch/middleware/executor.rb +32 -0
  113. data/lib/action_dispatch/middleware/flash.rb +143 -101
  114. data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
  115. data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
  116. data/lib/action_dispatch/middleware/reloader.rb +10 -92
  117. data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
  118. data/lib/action_dispatch/middleware/request_id.rb +29 -15
  119. data/lib/action_dispatch/middleware/server_timing.rb +78 -0
  120. data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
  121. data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
  122. data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
  123. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
  124. data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
  125. data/lib/action_dispatch/middleware/ssl.rb +134 -36
  126. data/lib/action_dispatch/middleware/stack.rb +109 -44
  127. data/lib/action_dispatch/middleware/static.rb +159 -90
  128. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
  132. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
  136. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
  139. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
  140. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  141. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
  142. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
  144. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  145. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
  146. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
  147. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
  148. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  149. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
  150. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  151. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
  152. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
  153. data/lib/action_dispatch/railtie.rb +44 -16
  154. data/lib/action_dispatch/request/session.rb +159 -69
  155. data/lib/action_dispatch/request/utils.rb +97 -23
  156. data/lib/action_dispatch/routing/endpoint.rb +11 -2
  157. data/lib/action_dispatch/routing/inspector.rb +195 -106
  158. data/lib/action_dispatch/routing/mapper.rb +1338 -955
  159. data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
  160. data/lib/action_dispatch/routing/redirection.rb +78 -51
  161. data/lib/action_dispatch/routing/route_set.rb +460 -374
  162. data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
  163. data/lib/action_dispatch/routing/url_for.rb +172 -124
  164. data/lib/action_dispatch/routing.rb +159 -158
  165. data/lib/action_dispatch/system_test_case.rb +206 -0
  166. data/lib/action_dispatch/system_testing/browser.rb +84 -0
  167. data/lib/action_dispatch/system_testing/driver.rb +85 -0
  168. data/lib/action_dispatch/system_testing/server.rb +33 -0
  169. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
  170. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
  171. data/lib/action_dispatch/testing/assertion_response.rb +48 -0
  172. data/lib/action_dispatch/testing/assertions/response.rb +71 -39
  173. data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
  174. data/lib/action_dispatch/testing/assertions.rb +9 -6
  175. data/lib/action_dispatch/testing/integration.rb +486 -306
  176. data/lib/action_dispatch/testing/request_encoder.rb +60 -0
  177. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  178. data/lib/action_dispatch/testing/test_process.rb +35 -22
  179. data/lib/action_dispatch/testing/test_request.rb +29 -34
  180. data/lib/action_dispatch/testing/test_response.rb +48 -15
  181. data/lib/action_dispatch.rb +82 -40
  182. data/lib/action_pack/gem_version.rb +8 -4
  183. data/lib/action_pack/version.rb +6 -2
  184. data/lib/action_pack.rb +21 -18
  185. metadata +146 -56
  186. data/lib/action_controller/caching/fragments.rb +0 -103
  187. data/lib/action_controller/metal/force_ssl.rb +0 -97
  188. data/lib/action_controller/metal/hide_actions.rb +0 -40
  189. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  190. data/lib/action_controller/middleware.rb +0 -39
  191. data/lib/action_controller/model_naming.rb +0 -12
  192. data/lib/action_dispatch/http/parameter_filter.rb +0 -72
  193. data/lib/action_dispatch/journey/backwards.rb +0 -5
  194. data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
  195. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  196. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
  197. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  199. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
  200. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  201. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  202. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,6 +1,13 @@
1
- require 'action_controller/metal/exceptions'
1
+ # frozen_string_literal: true
2
2
 
3
- module ActionController #:nodoc:
3
+ # :markup: markdown
4
+
5
+ require "action_controller/metal/exceptions"
6
+ require "action_dispatch/http/content_disposition"
7
+
8
+ module ActionController # :nodoc:
9
+ # # Action Controller Data Streaming
10
+ #
4
11
  # Methods for sending arbitrary data and for streaming files to the browser,
5
12
  # instead of rendering.
6
13
  module DataStreaming
@@ -8,132 +15,120 @@ module ActionController #:nodoc:
8
15
 
9
16
  include ActionController::Rendering
10
17
 
11
- DEFAULT_SEND_FILE_TYPE = 'application/octet-stream'.freeze #:nodoc:
12
- DEFAULT_SEND_FILE_DISPOSITION = 'attachment'.freeze #:nodoc:
18
+ DEFAULT_SEND_FILE_TYPE = "application/octet-stream" # :nodoc:
19
+ DEFAULT_SEND_FILE_DISPOSITION = "attachment" # :nodoc:
13
20
 
14
- protected
15
- # Sends the file. This uses a server-appropriate method (such as X-Sendfile)
16
- # via the Rack::Sendfile middleware. The header to use is set via
17
- # +config.action_dispatch.x_sendfile_header+.
18
- # Your server can also configure this for you by setting the X-Sendfile-Type header.
21
+ private
22
+ # Sends the file. This uses a server-appropriate method (such as `X-Sendfile`)
23
+ # via the `Rack::Sendfile` middleware. The header to use is set via
24
+ # `config.action_dispatch.x_sendfile_header`. Your server can also configure
25
+ # this for you by setting the `X-Sendfile-Type` header.
19
26
  #
20
- # Be careful to sanitize the path parameter if it is coming from a web
21
- # page. <tt>send_file(params[:path])</tt> allows a malicious user to
22
- # download any file on your server.
27
+ # Be careful to sanitize the path parameter if it is coming from a web page.
28
+ # `send_file(params[:path])` allows a malicious user to download any file on
29
+ # your server.
23
30
  #
24
31
  # Options:
25
- # * <tt>:filename</tt> - suggests a filename for the browser to use.
26
- # Defaults to <tt>File.basename(path)</tt>.
27
- # * <tt>:type</tt> - specifies an HTTP content type.
28
- # You can specify either a string or a symbol for a registered type register with
29
- # <tt>Mime::Type.register</tt>, for example :json
30
- # If omitted, type will be guessed from the file extension specified in <tt>:filename</tt>.
31
- # If no content type is registered for the extension, default type 'application/octet-stream' will be used.
32
- # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
33
- # Valid values are 'inline' and 'attachment' (default).
34
- # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to 200.
35
- # * <tt>:url_based_filename</tt> - set to +true+ if you want the browser guess the filename from
36
- # the URL, which is necessary for i18n filenames on certain browsers
37
- # (setting <tt>:filename</tt> overrides this option).
38
- #
39
- # The default Content-Type and Content-Disposition headers are
40
- # set to download arbitrary binary files in as many browsers as
41
- # possible. IE versions 4, 5, 5.5, and 6 are all known to have
42
- # a variety of quirks (especially when downloading over SSL).
32
+ # * `:filename` - suggests a filename for the browser to use. Defaults to
33
+ # `File.basename(path)`.
34
+ # * `:type` - specifies an HTTP content type. You can specify either a string
35
+ # or a symbol for a registered type with `Mime::Type.register`, for example
36
+ # `:json`. If omitted, the type will be inferred from the file extension
37
+ # specified in `:filename`. If no content type is registered for the
38
+ # extension, the default type `application/octet-stream` will be used.
39
+ # * `:disposition` - specifies whether the file will be shown inline or
40
+ # downloaded. Valid values are `"inline"` and `"attachment"` (default).
41
+ # * `:status` - specifies the status code to send with the response. Defaults
42
+ # to 200.
43
+ # * `:url_based_filename` - set to `true` if you want the browser to guess the
44
+ # filename from the URL, which is necessary for i18n filenames on certain
45
+ # browsers (setting `:filename` overrides this option).
46
+ #
47
+ #
48
+ # The default `Content-Type` and `Content-Disposition` headers are set to
49
+ # download arbitrary binary files in as many browsers as possible. IE versions
50
+ # 4, 5, 5.5, and 6 are all known to have a variety of quirks (especially when
51
+ # downloading over SSL).
43
52
  #
44
53
  # Simple download:
45
54
  #
46
- # send_file '/path/to.zip'
55
+ # send_file '/path/to.zip'
47
56
  #
48
57
  # Show a JPEG in the browser:
49
58
  #
50
- # send_file '/path/to.jpeg', type: 'image/jpeg', disposition: 'inline'
59
+ # send_file '/path/to.jpeg', type: 'image/jpeg', disposition: 'inline'
51
60
  #
52
61
  # Show a 404 page in the browser:
53
62
  #
54
- # send_file '/path/to/404.html', type: 'text/html; charset=utf-8', status: 404
55
- #
56
- # Read about the other Content-* HTTP headers if you'd like to
57
- # provide the user with more information (such as Content-Description) in
58
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
59
- #
60
- # Also be aware that the document may be cached by proxies and browsers.
61
- # The Pragma and Cache-Control headers declare how the file may be cached
62
- # by intermediaries. They default to require clients to validate with
63
- # the server before releasing cached responses. See
64
- # http://www.mnot.net/cache_docs/ for an overview of web caching and
65
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
66
- # for the Cache-Control header spec.
67
- def send_file(path, options = {}) #:doc:
68
- raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
63
+ # send_file '/path/to/404.html', type: 'text/html; charset=utf-8', disposition: 'inline', status: 404
64
+ #
65
+ # You can use other `Content-*` HTTP headers to provide additional information
66
+ # to the client. See MDN for a [list of HTTP
67
+ # headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers).
68
+ #
69
+ # Also be aware that the document may be cached by proxies and browsers. The
70
+ # `Pragma` and `Cache-Control` headers declare how the file may be cached by
71
+ # intermediaries. They default to require clients to validate with the server
72
+ # before releasing cached responses. See https://www.mnot.net/cache_docs/ for an
73
+ # overview of web caching and [RFC
74
+ # 9111](https://www.rfc-editor.org/rfc/rfc9111.html#name-cache-control) for the
75
+ # `Cache-Control` header spec.
76
+ def send_file(path, options = {}) # :doc:
77
+ raise MissingFile, "Cannot read file #{path}" unless File.file?(path) && File.readable?(path)
69
78
 
70
79
  options[:filename] ||= File.basename(path) unless options[:url_based_filename]
71
80
  send_file_headers! options
72
81
 
73
82
  self.status = options[:status] || 200
74
83
  self.content_type = options[:content_type] if options.key?(:content_type)
75
- self.response_body = FileBody.new(path)
84
+ response.send_file path
76
85
  end
77
86
 
78
- # Avoid having to pass an open file handle as the response body.
79
- # Rack::Sendfile will usually intercept the response and uses
80
- # the path directly, so there is no reason to open the file.
81
- class FileBody #:nodoc:
82
- attr_reader :to_path
83
-
84
- def initialize(path)
85
- @to_path = path
86
- end
87
-
88
- # Stream the file's contents if Rack::Sendfile isn't present.
89
- def each
90
- File.open(to_path, 'rb') do |file|
91
- while chunk = file.read(16384)
92
- yield chunk
93
- end
94
- end
95
- end
96
- end
97
-
98
- # Sends the given binary data to the browser. This method is similar to
99
- # <tt>render plain: data</tt>, but also allows you to specify whether
100
- # the browser should display the response as a file attachment (i.e. in a
101
- # download dialog) or as inline data. You may also set the content type,
102
- # the apparent file name, and other things.
87
+ # Sends the given binary data to the browser. This method is similar to `render
88
+ # plain: data`, but also allows you to specify whether the browser should
89
+ # display the response as a file attachment (i.e. in a download dialog) or as
90
+ # inline data. You may also set the content type, the file name, and other
91
+ # things.
103
92
  #
104
93
  # Options:
105
- # * <tt>:filename</tt> - suggests a filename for the browser to use.
106
- # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify
107
- # either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json
108
- # If omitted, type will be guessed from the file extension specified in <tt>:filename</tt>.
109
- # If no content type is registered for the extension, default type 'application/octet-stream' will be used.
110
- # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
111
- # Valid values are 'inline' and 'attachment' (default).
112
- # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to 200.
94
+ # * `:filename` - suggests a filename for the browser to use.
95
+ # * `:type` - specifies an HTTP content type. Defaults to
96
+ # `application/octet-stream`. You can specify either a string or a symbol
97
+ # for a registered type with `Mime::Type.register`, for example `:json`. If
98
+ # omitted, type will be inferred from the file extension specified in
99
+ # `:filename`. If no content type is registered for the extension, the
100
+ # default type `application/octet-stream` will be used.
101
+ # * `:disposition` - specifies whether the file will be shown inline or
102
+ # downloaded. Valid values are `"inline"` and `"attachment"` (default).
103
+ # * `:status` - specifies the status code to send with the response. Defaults
104
+ # to 200.
105
+ #
113
106
  #
114
107
  # Generic data download:
115
108
  #
116
- # send_data buffer
109
+ # send_data buffer
117
110
  #
118
111
  # Download a dynamically-generated tarball:
119
112
  #
120
- # send_data generate_tgz('dir'), filename: 'dir.tgz'
113
+ # send_data generate_tgz('dir'), filename: 'dir.tgz'
121
114
  #
122
115
  # Display an image Active Record in the browser:
123
116
  #
124
- # send_data image.data, type: image.content_type, disposition: 'inline'
117
+ # send_data image.data, type: image.content_type, disposition: 'inline'
125
118
  #
126
- # See +send_file+ for more information on HTTP Content-* headers and caching.
127
- def send_data(data, options = {}) #:doc:
119
+ # See `send_file` for more information on HTTP `Content-*` headers and caching.
120
+ def send_data(data, options = {}) # :doc:
128
121
  send_file_headers! options
129
- render options.slice(:status, :content_type).merge(:text => data)
122
+ render options.slice(:status, :content_type).merge(body: data)
130
123
  end
131
124
 
132
- private
133
125
  def send_file_headers!(options)
134
126
  type_provided = options.has_key?(:type)
135
127
 
136
128
  content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
129
+ self.content_type = content_type
130
+ response.sending_file = true
131
+
137
132
  raise ArgumentError, ":type option required" if content_type.nil?
138
133
 
139
134
  if content_type.is_a?(Symbol)
@@ -143,29 +138,17 @@ module ActionController #:nodoc:
143
138
  else
144
139
  if !type_provided && options[:filename]
145
140
  # If type wasn't provided, try guessing from file extension.
146
- content_type = Mime::Type.lookup_by_extension(File.extname(options[:filename]).downcase.delete('.')) || content_type
141
+ content_type = Mime::Type.lookup_by_extension(File.extname(options[:filename]).downcase.delete(".")) || content_type
147
142
  end
148
143
  self.content_type = content_type
149
144
  end
150
145
 
151
146
  disposition = options.fetch(:disposition, DEFAULT_SEND_FILE_DISPOSITION)
152
- unless disposition.nil?
153
- disposition = disposition.to_s
154
- disposition += %(; filename="#{options[:filename]}") if options[:filename]
155
- headers['Content-Disposition'] = disposition
147
+ if disposition
148
+ headers["Content-Disposition"] = ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: options[:filename])
156
149
  end
157
150
 
158
- headers['Content-Transfer-Encoding'] = 'binary'
159
-
160
- response.sending_file = true
161
-
162
- # Fix a problem with IE 6.0 on opening downloaded files:
163
- # If Cache-Control: no-cache is set (which Rails does by default),
164
- # IE removes the file it just downloaded from its cache immediately
165
- # after it displays the "open/save" dialog, which means that if you
166
- # hit "open" the file isn't there anymore when the application that
167
- # is called for handling the download is run, so let's workaround that
168
- response.cache_control[:public] ||= false
151
+ headers["Content-Transfer-Encoding"] = "binary"
169
152
  end
170
153
  end
171
154
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module ActionController
6
+ # # Action Controller Default Headers
7
+ #
8
+ # Allows configuring default headers that will be automatically merged into each
9
+ # response.
10
+ module DefaultHeaders
11
+ extend ActiveSupport::Concern
12
+
13
+ module ClassMethods
14
+ def make_response!(request)
15
+ ActionDispatch::Response.create.tap do |res|
16
+ res.request = request
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module ActionController
6
+ # # Action Controller Etag With Flash
7
+ #
8
+ # When you're using the flash, it's generally used as a conditional on the view.
9
+ # This means the content of the view depends on the flash. Which in turn means
10
+ # that the ETag for a response should be computed with the content of the flash
11
+ # in mind. This does that by including the content of the flash as a component
12
+ # in the ETag that's generated for a response.
13
+ module EtagWithFlash
14
+ extend ActiveSupport::Concern
15
+
16
+ include ActionController::ConditionalGet
17
+
18
+ included do
19
+ etag { flash if request.respond_to?(:flash) && !flash.empty? }
20
+ end
21
+ end
22
+ end
@@ -1,20 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
1
5
  module ActionController
2
- # When our views change, they should bubble up into HTTP cache freshness
3
- # and bust browser caches. So the template digest for the current action
4
- # is automatically included in the ETag.
6
+ # # Action Controller Etag With Template Digest
7
+ #
8
+ # When our views change, they should bubble up into HTTP cache freshness and
9
+ # bust browser caches. So the template digest for the current action is
10
+ # automatically included in the ETag.
5
11
  #
6
12
  # Enabled by default for apps that use Action View. Disable by setting
7
13
  #
8
- # config.action_controller.etag_with_template_digest = false
14
+ # config.action_controller.etag_with_template_digest = false
9
15
  #
10
- # Override the template to digest by passing +:template+ to +fresh_when+
11
- # and +stale?+ calls. For example:
16
+ # Override the template to digest by passing `:template` to `fresh_when` and
17
+ # `stale?` calls. For example:
12
18
  #
13
- # # We're going to render widgets/show, not posts/show
14
- # fresh_when @post, template: 'widgets/show'
19
+ # # We're going to render widgets/show, not posts/show
20
+ # fresh_when @post, template: 'widgets/show'
15
21
  #
16
- # # We're not going to render a template, so omit it from the ETag.
17
- # fresh_when @post, template: false
22
+ # # We're not going to render a template, so omit it from the ETag.
23
+ # fresh_when @post, template: false
18
24
  #
19
25
  module EtagWithTemplateDigest
20
26
  extend ActiveSupport::Concern
@@ -22,29 +28,32 @@ module ActionController
22
28
  include ActionController::ConditionalGet
23
29
 
24
30
  included do
25
- class_attribute :etag_with_template_digest
26
- self.etag_with_template_digest = true
31
+ class_attribute :etag_with_template_digest, default: true
27
32
 
28
- ActiveSupport.on_load :action_view, yield: true do |action_view_base|
29
- etag do |options|
30
- determine_template_etag(options) if etag_with_template_digest
31
- end
33
+ etag do |options|
34
+ determine_template_etag(options) if etag_with_template_digest
32
35
  end
33
36
  end
34
37
 
35
38
  private
36
- def determine_template_etag(options)
37
- if template = pick_template_for_etag(options)
38
- lookup_and_digest_template(template)
39
+ def determine_template_etag(options)
40
+ if template = pick_template_for_etag(options)
41
+ lookup_and_digest_template(template)
42
+ end
39
43
  end
40
- end
41
44
 
42
- def pick_template_for_etag(options)
43
- options.fetch(:template) { "#{controller_name}/#{action_name}" }
44
- end
45
+ # Pick the template digest to include in the ETag. If the `:template` option is
46
+ # present, use the named template. If `:template` is `nil` or absent, use the
47
+ # default controller/action template. If `:template` is false, omit the template
48
+ # digest from the ETag.
49
+ def pick_template_for_etag(options)
50
+ unless options[:template] == false
51
+ options[:template] || lookup_context.find_all(action_name, _prefixes).first&.virtual_path
52
+ end
53
+ end
45
54
 
46
- def lookup_and_digest_template(template)
47
- ActionView::Digestor.digest name: template, finder: lookup_context
48
- end
55
+ def lookup_and_digest_template(template)
56
+ ActionView::Digestor.digest name: template, format: nil, finder: lookup_context
57
+ end
49
58
  end
50
59
  end
@@ -1,59 +1,106 @@
1
- module ActionController
2
- class ActionControllerError < StandardError #:nodoc:
3
- end
1
+ # frozen_string_literal: true
4
2
 
5
- class BadRequest < ActionControllerError #:nodoc:
6
- attr_reader :original_exception
3
+ # :markup: markdown
7
4
 
8
- def initialize(type = nil, e = nil)
9
- return super() unless type && e
5
+ module ActionController
6
+ class ActionControllerError < StandardError # :nodoc:
7
+ end
10
8
 
11
- super("Invalid #{type} parameters: #{e.message}")
12
- @original_exception = e
13
- set_backtrace e.backtrace
9
+ class BadRequest < ActionControllerError # :nodoc:
10
+ def initialize(msg = nil)
11
+ super(msg)
12
+ set_backtrace $!.backtrace if $!
14
13
  end
15
14
  end
16
15
 
17
- class RenderError < ActionControllerError #:nodoc:
16
+ class RenderError < ActionControllerError # :nodoc:
18
17
  end
19
18
 
20
- class RoutingError < ActionControllerError #:nodoc:
19
+ class RoutingError < ActionControllerError # :nodoc:
21
20
  attr_reader :failures
22
- def initialize(message, failures=[])
21
+ def initialize(message, failures = [])
23
22
  super(message)
24
23
  @failures = failures
25
24
  end
26
25
  end
27
26
 
28
- class ActionController::UrlGenerationError < ActionControllerError #:nodoc:
27
+ class UrlGenerationError < ActionControllerError # :nodoc:
28
+ attr_reader :routes, :route_name, :method_name
29
+
30
+ def initialize(message, routes = nil, route_name = nil, method_name = nil)
31
+ @routes = routes
32
+ @route_name = route_name
33
+ @method_name = method_name
34
+
35
+ super(message)
36
+ end
37
+
38
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
39
+ include DidYouMean::Correctable
40
+
41
+ def corrections
42
+ @corrections ||= begin
43
+ maybe_these = routes&.named_routes&.helper_names&.grep(/#{route_name}/) || []
44
+ maybe_these -= [method_name.to_s] # remove exact match
45
+
46
+ DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(route_name)
47
+ end
48
+ end
49
+ end
29
50
  end
30
51
 
31
- class MethodNotAllowed < ActionControllerError #:nodoc:
52
+ class MethodNotAllowed < ActionControllerError # :nodoc:
32
53
  def initialize(*allowed_methods)
33
- super("Only #{allowed_methods.to_sentence(:locale => :en)} requests are allowed.")
54
+ super("Only #{allowed_methods.to_sentence} requests are allowed.")
34
55
  end
35
56
  end
36
57
 
37
- class NotImplemented < MethodNotAllowed #:nodoc:
58
+ class NotImplemented < MethodNotAllowed # :nodoc:
38
59
  end
39
60
 
40
- class UnknownController < ActionControllerError #:nodoc:
61
+ class MissingFile < ActionControllerError # :nodoc:
41
62
  end
42
63
 
43
- class MissingFile < ActionControllerError #:nodoc:
64
+ class SessionOverflowError < ActionControllerError # :nodoc:
65
+ DEFAULT_MESSAGE = "Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data."
66
+
67
+ def initialize(message = nil)
68
+ super(message || DEFAULT_MESSAGE)
69
+ end
70
+ end
71
+
72
+ class UnknownHttpMethod < ActionControllerError # :nodoc:
44
73
  end
45
74
 
46
- class SessionOverflowError < ActionControllerError #:nodoc:
47
- DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.'
75
+ class UnknownFormat < ActionControllerError # :nodoc:
76
+ end
77
+
78
+ # Raised when a nested respond_to is triggered and the content types of each are
79
+ # incompatible. For example:
80
+ #
81
+ # respond_to do |outer_type|
82
+ # outer_type.js do
83
+ # respond_to do |inner_type|
84
+ # inner_type.html { render body: "HTML" }
85
+ # end
86
+ # end
87
+ # end
88
+ class RespondToMismatchError < ActionControllerError
89
+ DEFAULT_MESSAGE = "respond_to was called multiple times and matched with conflicting formats in this action. Please note that you may only call respond_to and match on a single format per action."
48
90
 
49
91
  def initialize(message = nil)
50
92
  super(message || DEFAULT_MESSAGE)
51
93
  end
52
94
  end
53
95
 
54
- class UnknownHttpMethod < ActionControllerError #:nodoc:
55
- end
96
+ class MissingExactTemplate < UnknownFormat # :nodoc:
97
+ attr_reader :controller, :action_name
56
98
 
57
- class UnknownFormat < ActionControllerError #:nodoc:
99
+ def initialize(message, controller, action_name)
100
+ @controller = controller
101
+ @action_name = action_name
102
+
103
+ super(message)
104
+ end
58
105
  end
59
106
  end
@@ -1,10 +1,13 @@
1
- module ActionController #:nodoc:
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module ActionController # :nodoc:
2
6
  module Flash
3
7
  extend ActiveSupport::Concern
4
8
 
5
9
  included do
6
- class_attribute :_flash_types, instance_accessor: false
7
- self._flash_types = []
10
+ class_attribute :_flash_types, instance_accessor: false, default: []
8
11
 
9
12
  delegate :flash, to: :request
10
13
  add_flash_types(:alert, :notice)
@@ -12,19 +15,19 @@ module ActionController #:nodoc:
12
15
 
13
16
  module ClassMethods
14
17
  # Creates new flash types. You can pass as many types as you want to create
15
- # flash types other than the default <tt>alert</tt> and <tt>notice</tt> in
16
- # your controllers and views. For instance:
18
+ # flash types other than the default `alert` and `notice` in your controllers
19
+ # and views. For instance:
17
20
  #
18
- # # in application_controller.rb
19
- # class ApplicationController < ActionController::Base
20
- # add_flash_types :warning
21
- # end
21
+ # # in application_controller.rb
22
+ # class ApplicationController < ActionController::Base
23
+ # add_flash_types :warning
24
+ # end
22
25
  #
23
- # # in your controller
24
- # redirect_to user_path(@user), warning: "Incomplete profile"
26
+ # # in your controller
27
+ # redirect_to user_path(@user), warning: "Incomplete profile"
25
28
  #
26
- # # in your view
27
- # <%= warning %>
29
+ # # in your view
30
+ # <%= warning %>
28
31
  #
29
32
  # This method will automatically define a new method for each of the given
30
33
  # names, and it will be available in your views.
@@ -35,26 +38,30 @@ module ActionController #:nodoc:
35
38
  define_method(type) do
36
39
  request.flash[type]
37
40
  end
38
- helper_method type
41
+ helper_method(type) if respond_to?(:helper_method)
39
42
 
40
43
  self._flash_types += [type]
41
44
  end
42
45
  end
46
+
47
+ def action_methods # :nodoc:
48
+ @action_methods ||= super - _flash_types.map(&:to_s).to_set
49
+ end
43
50
  end
44
51
 
45
- protected
46
- def redirect_to(options = {}, response_status_and_flash = {}) #:doc:
52
+ private
53
+ def redirect_to(options = {}, response_options_and_flash = {}) # :doc:
47
54
  self.class._flash_types.each do |flash_type|
48
- if type = response_status_and_flash.delete(flash_type)
55
+ if type = response_options_and_flash.delete(flash_type)
49
56
  flash[flash_type] = type
50
57
  end
51
58
  end
52
59
 
53
- if other_flashes = response_status_and_flash.delete(:flash)
60
+ if other_flashes = response_options_and_flash.delete(:flash)
54
61
  flash.update(other_flashes)
55
62
  end
56
63
 
57
- super(options, response_status_and_flash)
64
+ super(options, response_options_and_flash)
58
65
  end
59
66
  end
60
67
  end