actionpack 6.1.5 → 7.0.0.alpha1

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 (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -521
  3. data/MIT-LICENSE +2 -1
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +7 -21
  7. data/lib/abstract_controller/caching/fragments.rb +2 -2
  8. data/lib/abstract_controller/caching.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +9 -8
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/error.rb +1 -1
  12. data/lib/abstract_controller/helpers.rb +3 -2
  13. data/lib/abstract_controller/logger.rb +1 -1
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/translation.rb +0 -2
  16. data/lib/abstract_controller/url_for.rb +4 -6
  17. data/lib/action_controller/api.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +3 -1
  19. data/lib/action_controller/metal/conditional_get.rb +38 -1
  20. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  21. data/lib/action_controller/metal/cookies.rb +1 -1
  22. data/lib/action_controller/metal/data_streaming.rb +5 -13
  23. data/lib/action_controller/metal/exceptions.rb +19 -30
  24. data/lib/action_controller/metal/flash.rb +6 -2
  25. data/lib/action_controller/metal/http_authentication.rb +15 -16
  26. data/lib/action_controller/metal/instrumentation.rb +55 -52
  27. data/lib/action_controller/metal/live.rb +42 -2
  28. data/lib/action_controller/metal/mime_responds.rb +3 -3
  29. data/lib/action_controller/metal/params_wrapper.rb +7 -7
  30. data/lib/action_controller/metal/permissions_policy.rb +1 -1
  31. data/lib/action_controller/metal/query_tags.rb +16 -0
  32. data/lib/action_controller/metal/redirecting.rb +50 -16
  33. data/lib/action_controller/metal/rendering.rb +7 -7
  34. data/lib/action_controller/metal/request_forgery_protection.rb +64 -20
  35. data/lib/action_controller/metal/rescue.rb +1 -1
  36. data/lib/action_controller/metal/streaming.rb +1 -3
  37. data/lib/action_controller/metal/strong_parameters.rb +25 -29
  38. data/lib/action_controller/metal/testing.rb +0 -2
  39. data/lib/action_controller/metal.rb +7 -10
  40. data/lib/action_controller/railtie.rb +42 -5
  41. data/lib/action_controller/test_case.rb +6 -2
  42. data/lib/action_controller.rb +2 -5
  43. data/lib/action_dispatch/http/cache.rb +13 -6
  44. data/lib/action_dispatch/http/content_security_policy.rb +40 -37
  45. data/lib/action_dispatch/http/filter_parameters.rb +5 -0
  46. data/lib/action_dispatch/http/mime_negotiation.rb +13 -3
  47. data/lib/action_dispatch/http/mime_type.rb +9 -11
  48. data/lib/action_dispatch/http/parameters.rb +4 -4
  49. data/lib/action_dispatch/http/permissions_policy.rb +1 -1
  50. data/lib/action_dispatch/http/request.rb +10 -19
  51. data/lib/action_dispatch/http/response.rb +3 -3
  52. data/lib/action_dispatch/http/url.rb +9 -10
  53. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  54. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  55. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  56. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  57. data/lib/action_dispatch/journey/path/pattern.rb +22 -13
  58. data/lib/action_dispatch/journey/route.rb +5 -12
  59. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  60. data/lib/action_dispatch/journey/router.rb +1 -1
  61. data/lib/action_dispatch/journey/routes.rb +3 -3
  62. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  63. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  64. data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
  65. data/lib/action_dispatch/middleware/cookies.rb +7 -3
  66. data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
  67. data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
  68. data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
  69. data/lib/action_dispatch/middleware/executor.rb +1 -1
  70. data/lib/action_dispatch/middleware/flash.rb +9 -11
  71. data/lib/action_dispatch/middleware/host_authorization.rb +25 -73
  72. data/lib/action_dispatch/middleware/remote_ip.rb +16 -4
  73. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
  74. data/lib/action_dispatch/middleware/show_exceptions.rb +6 -18
  75. data/lib/action_dispatch/middleware/stack.rb +50 -9
  76. data/lib/action_dispatch/middleware/static.rb +2 -5
  77. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
  78. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  79. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  80. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +2 -2
  81. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
  82. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  83. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
  84. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
  85. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
  86. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  87. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  88. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
  89. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +5 -14
  90. data/lib/action_dispatch/railtie.rb +8 -2
  91. data/lib/action_dispatch/request/session.rb +43 -13
  92. data/lib/action_dispatch/routing/mapper.rb +44 -72
  93. data/lib/action_dispatch/routing/redirection.rb +0 -2
  94. data/lib/action_dispatch/routing/route_set.rb +7 -4
  95. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  96. data/lib/action_dispatch/routing/url_for.rb +1 -2
  97. data/lib/action_dispatch/routing.rb +2 -2
  98. data/lib/action_dispatch/system_test_case.rb +6 -12
  99. data/lib/action_dispatch/system_testing/driver.rb +24 -4
  100. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +10 -6
  101. data/lib/action_dispatch/testing/assertions.rb +2 -5
  102. data/lib/action_dispatch/testing/integration.rb +6 -8
  103. data/lib/action_dispatch/testing/test_process.rb +2 -2
  104. data/lib/action_dispatch.rb +1 -1
  105. data/lib/action_pack/gem_version.rb +4 -4
  106. data/lib/action_pack.rb +1 -1
  107. metadata +18 -18
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2022 David Heinemeier Hansson
1
+ Copyright (c) 2004-2021 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -18,3 +18,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.rdoc CHANGED
@@ -2,9 +2,8 @@
2
2
 
3
3
  Action Pack is a framework for handling and responding to web requests. It
4
4
  provides mechanisms for *routing* (mapping request URLs to actions), defining
5
- *controllers* that implement actions, and generating responses by rendering
6
- *views*, which are templates of various formats. In short, Action Pack
7
- provides the view and controller layers in the MVC paradigm.
5
+ *controllers* that implement actions, and generating responses. In short, Action Pack
6
+ provides the controller layer in the MVC paradigm.
8
7
 
9
8
  It consists of several modules:
10
9
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbstractController
4
- module AssetPaths #:nodoc:
4
+ module AssetPaths # :nodoc:
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
@@ -9,35 +9,21 @@ require "active_support/core_ext/module/attr_internal"
9
9
  module AbstractController
10
10
  # Raised when a non-existing controller action is triggered.
11
11
  class ActionNotFound < StandardError
12
- attr_reader :controller, :action
13
- def initialize(message = nil, controller = nil, action = nil)
12
+ attr_reader :controller, :action # :nodoc:
13
+
14
+ def initialize(message = nil, controller = nil, action = nil) # :nodoc:
14
15
  @controller = controller
15
16
  @action = action
16
17
  super(message)
17
18
  end
18
19
 
19
- class Correction
20
- def initialize(error)
21
- @error = error
22
- end
23
-
24
- def corrections
25
- if @error.action
26
- maybe_these = @error.controller.class.action_methods
20
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
21
+ include DidYouMean::Correctable # :nodoc:
27
22
 
28
- maybe_these.sort_by { |n|
29
- DidYouMean::Jaro.distance(@error.action.to_s, n)
30
- }.reverse.first(4)
31
- else
32
- []
33
- end
23
+ def corrections # :nodoc:
24
+ @corrections ||= DidYouMean::SpellChecker.new(dictionary: controller.class.action_methods).correct(action)
34
25
  end
35
26
  end
36
-
37
- # We may not have DYM, and DYM might not let us register error handlers
38
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
39
- DidYouMean.correct_error(self, Correction)
40
- end
41
27
  end
42
28
 
43
29
  # AbstractController::Base is a low-level API. Nobody should be
@@ -142,8 +142,8 @@ module AbstractController
142
142
  end
143
143
  end
144
144
 
145
- def instrument_fragment_cache(name, key) # :nodoc:
146
- ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key)) { yield }
145
+ def instrument_fragment_cache(name, key, &block) # :nodoc:
146
+ ActiveSupport::Notifications.instrument("#{name}.#{instrument_name}", instrument_payload(key), &block)
147
147
  end
148
148
  end
149
149
  end
@@ -50,7 +50,7 @@ module AbstractController
50
50
  end
51
51
 
52
52
  def view_cache_dependencies
53
- self.class._view_cache_dependencies.map { |dep| instance_exec(&dep) }.compact
53
+ self.class._view_cache_dependencies.filter_map { |dep| instance_exec(&dep) }
54
54
  end
55
55
 
56
56
  private
@@ -35,14 +35,6 @@ module AbstractController
35
35
  skip_after_callbacks_if_terminated: true
36
36
  end
37
37
 
38
- # Override <tt>AbstractController::Base#process_action</tt> to run the
39
- # <tt>process_action</tt> callbacks around the normal behavior.
40
- def process_action(*)
41
- run_callbacks(:process_action) do
42
- super
43
- end
44
- end
45
-
46
38
  module ClassMethods
47
39
  # If +:only+ or +:except+ are used, convert the options into the
48
40
  # +:if+ and +:unless+ options of ActiveSupport::Callbacks.
@@ -220,5 +212,14 @@ module AbstractController
220
212
  alias_method :"append_#{callback}_action", :"#{callback}_action"
221
213
  end
222
214
  end
215
+
216
+ private
217
+ # Override <tt>AbstractController::Base#process_action</tt> to run the
218
+ # <tt>process_action</tt> callbacks around the normal behavior.
219
+ def process_action(*)
220
+ run_callbacks(:process_action) do
221
+ super
222
+ end
223
+ end
223
224
  end
224
225
  end
@@ -10,7 +10,7 @@ module AbstractController
10
10
  def #{sym}(*args, &block)
11
11
  custom(Mime[:#{sym}], *args, &block)
12
12
  end
13
- ruby2_keywords(:#{sym}) if respond_to?(:ruby2_keywords, true)
13
+ ruby2_keywords(:#{sym})
14
14
  RUBY
15
15
  end
16
16
 
@@ -39,6 +39,6 @@ module AbstractController
39
39
  super
40
40
  end
41
41
  end
42
- ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
42
+ ruby2_keywords(:method_missing)
43
43
  end
44
44
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AbstractController
4
- class Error < StandardError #:nodoc:
4
+ class Error < StandardError # :nodoc:
5
5
  end
6
6
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/dependencies"
4
+ require "active_support/core_ext/name_error"
4
5
 
5
6
  module AbstractController
6
7
  module Helpers
@@ -83,11 +84,11 @@ module AbstractController
83
84
  file, line = location.path, location.lineno
84
85
 
85
86
  methods.each do |method|
86
- _helpers_for_modification.class_eval <<-ruby_eval, file, line
87
+ _helpers_for_modification.class_eval <<~ruby_eval, file, line
87
88
  def #{method}(*args, &block) # def current_user(*args, &block)
88
89
  controller.send(:'#{method}', *args, &block) # controller.send(:'current_user', *args, &block)
89
90
  end # end
90
- ruby2_keywords(:'#{method}') if respond_to?(:ruby2_keywords, true)
91
+ ruby2_keywords(:'#{method}')
91
92
  ruby_eval
92
93
  end
93
94
  end
@@ -3,7 +3,7 @@
3
3
  require "active_support/benchmarkable"
4
4
 
5
5
  module AbstractController
6
- module Logger #:nodoc:
6
+ module Logger # :nodoc:
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/module/introspection"
4
+
3
5
  module AbstractController
4
6
  module Railties
5
7
  module RoutesHelpers
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/symbol/starts_ends_with"
4
-
5
3
  module AbstractController
6
4
  module Translation
7
5
  mattr_accessor :raise_on_missing_translations, default: false
@@ -22,12 +22,10 @@ module AbstractController
22
22
  end
23
23
 
24
24
  def action_methods
25
- @action_methods ||= begin
26
- if _routes
27
- super - _routes.named_routes.helper_names
28
- else
29
- super
30
- end
25
+ @action_methods ||= if _routes
26
+ super - _routes.named_routes.helper_names
27
+ else
28
+ super
31
29
  end
32
30
  end
33
31
  end
@@ -37,7 +37,7 @@ module ActionController
37
37
  # == Renders
38
38
  #
39
39
  # The default API Controller stack includes all renderers, which means you
40
- # can use <tt>render :json</tt> and brothers freely in your controllers. Keep
40
+ # can use <tt>render :json</tt> and siblings freely in your controllers. Keep
41
41
  # in mind that templates are not going to be rendered, so you need to ensure
42
42
  # your controller is calling either <tt>render</tt> or <tt>redirect_to</tt> in
43
43
  # all actions, otherwise it will return 204 No Content.
@@ -56,7 +56,9 @@ module ActionController
56
56
  def unpermitted_parameters(event)
57
57
  debug do
58
58
  unpermitted_keys = event.payload[:keys]
59
- color("Unpermitted parameter#{'s' if unpermitted_keys.size > 1}: #{unpermitted_keys.map { |e| ":#{e}" }.join(", ")}", RED)
59
+ display_unpermitted_keys = unpermitted_keys.map { |e| ":#{e}" }.join(", ")
60
+ context = event.payload[:context].map { |k, v| "#{k}: #{v}" }.join(", ")
61
+ color("Unpermitted parameter#{'s' if unpermitted_keys.size > 1}: #{display_unpermitted_keys}. Context: { #{context} }", RED)
60
62
  end
61
63
  end
62
64
 
@@ -57,6 +57,8 @@ module ActionController
57
57
  # 304 Not Modified response if last_modified <= If-Modified-Since.
58
58
  # * <tt>:public</tt> By default the Cache-Control header is private, set this to
59
59
  # +true+ if you want your application to be cacheable by other devices (proxy caches).
60
+ # * <tt>:cache_control</tt> When given will overwrite an existing Cache-Control header.
61
+ # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
60
62
  # * <tt>:template</tt> By default, the template digest for the current
61
63
  # controller/action is included in ETags. If the action renders a
62
64
  # different template, you can include its digest instead. If the action
@@ -98,12 +100,22 @@ module ActionController
98
100
  # fresh_when(@article, public: true)
99
101
  # end
100
102
  #
103
+ # When overwriting Cache-Control header:
104
+ #
105
+ # def show
106
+ # @article = Article.find(params[:id])
107
+ # fresh_when(@article, public: true, cache_control: { no_cache: true })
108
+ # end
109
+ #
110
+ # This will set in the response Cache-Control = public, no-cache.
111
+ #
101
112
  # When rendering a different template than the default controller/action
102
113
  # style, you can indicate which digest to include in the ETag:
103
114
  #
104
115
  # before_action { fresh_when @article, template: 'widgets/show' }
105
116
  #
106
- def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, template: nil)
117
+ def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, cache_control: {}, template: nil)
118
+ response.cache_control.delete(:no_store)
107
119
  weak_etag ||= etag || object unless strong_etag
108
120
  last_modified ||= object.try(:updated_at) || object.try(:maximum, :updated_at)
109
121
 
@@ -117,6 +129,7 @@ module ActionController
117
129
 
118
130
  response.last_modified = last_modified if last_modified
119
131
  response.cache_control[:public] = true if public
132
+ response.cache_control.merge!(cache_control)
120
133
 
121
134
  head :not_modified if request.fresh?(response)
122
135
  end
@@ -147,6 +160,8 @@ module ActionController
147
160
  # 304 Not Modified response if last_modified <= If-Modified-Since.
148
161
  # * <tt>:public</tt> By default the Cache-Control header is private, set this to
149
162
  # +true+ if you want your application to be cacheable by other devices (proxy caches).
163
+ # * <tt>:cache_control</tt> When given will overwrite an existing Cache-Control header.
164
+ # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
150
165
  # * <tt>:template</tt> By default, the template digest for the current
151
166
  # controller/action is included in ETags. If the action renders a
152
167
  # different template, you can include its digest instead. If the action
@@ -209,6 +224,21 @@ module ActionController
209
224
  # end
210
225
  # end
211
226
  #
227
+ # When overwriting Cache-Control header:
228
+ #
229
+ # def show
230
+ # @article = Article.find(params[:id])
231
+ #
232
+ # if stale?(@article, public: true, cache_control: { no_cache: true })
233
+ # @statistics = @articles.really_expensive_call
234
+ # respond_to do |format|
235
+ # # all the supported formats
236
+ # end
237
+ # end
238
+ # end
239
+ #
240
+ # This will set in the response Cache-Control = public, no-cache.
241
+ #
212
242
  # When rendering a different template than the default controller/action
213
243
  # style, you can indicate which digest to include in the ETag:
214
244
  #
@@ -244,6 +274,7 @@ module ActionController
244
274
  #
245
275
  # The method will also ensure an HTTP Date header for client compatibility.
246
276
  def expires_in(seconds, options = {})
277
+ response.cache_control.delete(:no_store)
247
278
  response.cache_control.merge!(
248
279
  max_age: seconds,
249
280
  public: options.delete(:public),
@@ -280,6 +311,12 @@ module ActionController
280
311
  public: public)
281
312
  end
282
313
 
314
+ # Sets an HTTP 1.1 Cache-Control header of <tt>no-store</tt>. This means the
315
+ # resource may not be stored in any cache.
316
+ def no_store
317
+ response.cache_control.replace(no_store: true)
318
+ end
319
+
283
320
  private
284
321
  def combine_etags(validator, options)
285
322
  [validator, *etaggers.map { |etagger| instance_exec(options, &etagger) }].compact
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActionController #:nodoc:
3
+ module ActionController # :nodoc:
4
4
  module ContentSecurityPolicy
5
5
  # TODO: Documentation
6
6
  extend ActiveSupport::Concern
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActionController #:nodoc:
3
+ module ActionController # :nodoc:
4
4
  module Cookies
5
5
  extend ActiveSupport::Concern
6
6
 
@@ -3,7 +3,7 @@
3
3
  require "action_controller/metal/exceptions"
4
4
  require "action_dispatch/http/content_disposition"
5
5
 
6
- module ActionController #:nodoc:
6
+ module ActionController # :nodoc:
7
7
  # Methods for sending arbitrary data and for streaming files to the browser,
8
8
  # instead of rendering.
9
9
  module DataStreaming
@@ -11,8 +11,8 @@ module ActionController #:nodoc:
11
11
 
12
12
  include ActionController::Rendering
13
13
 
14
- DEFAULT_SEND_FILE_TYPE = "application/octet-stream" #:nodoc:
15
- DEFAULT_SEND_FILE_DISPOSITION = "attachment" #:nodoc:
14
+ DEFAULT_SEND_FILE_TYPE = "application/octet-stream" # :nodoc:
15
+ DEFAULT_SEND_FILE_DISPOSITION = "attachment" # :nodoc:
16
16
 
17
17
  private
18
18
  # Sends the file. This uses a server-appropriate method (such as X-Sendfile)
@@ -66,7 +66,7 @@ module ActionController #:nodoc:
66
66
  # https://www.mnot.net/cache_docs/ for an overview of web caching and
67
67
  # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
68
68
  # for the Cache-Control header spec.
69
- def send_file(path, options = {}) #:doc:
69
+ def send_file(path, options = {}) # :doc:
70
70
  raise MissingFile, "Cannot read file #{path}" unless File.file?(path) && File.readable?(path)
71
71
 
72
72
  options[:filename] ||= File.basename(path) unless options[:url_based_filename]
@@ -106,7 +106,7 @@ module ActionController #:nodoc:
106
106
  # send_data image.data, type: image.content_type, disposition: 'inline'
107
107
  #
108
108
  # See +send_file+ for more information on HTTP Content-* headers and caching.
109
- def send_data(data, options = {}) #:doc:
109
+ def send_data(data, options = {}) # :doc:
110
110
  send_file_headers! options
111
111
  render options.slice(:status, :content_type).merge(body: data)
112
112
  end
@@ -138,14 +138,6 @@ module ActionController #:nodoc:
138
138
  end
139
139
 
140
140
  headers["Content-Transfer-Encoding"] = "binary"
141
-
142
- # Fix a problem with IE 6.0 on opening downloaded files:
143
- # If Cache-Control: no-cache is set (which Rails does by default),
144
- # IE removes the file it just downloaded from its cache immediately
145
- # after it displays the "open/save" dialog, which means that if you
146
- # hit "open" the file isn't there anymore when the application that
147
- # is called for handling the download is run, so let's workaround that
148
- response.cache_control[:public] ||= false
149
141
  end
150
142
  end
151
143
  end
@@ -1,20 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
- class ActionControllerError < StandardError #:nodoc:
4
+ class ActionControllerError < StandardError # :nodoc:
5
5
  end
6
6
 
7
- class BadRequest < ActionControllerError #:nodoc:
7
+ class BadRequest < ActionControllerError # :nodoc:
8
8
  def initialize(msg = nil)
9
9
  super(msg)
10
10
  set_backtrace $!.backtrace if $!
11
11
  end
12
12
  end
13
13
 
14
- class RenderError < ActionControllerError #:nodoc:
14
+ class RenderError < ActionControllerError # :nodoc:
15
15
  end
16
16
 
17
- class RoutingError < ActionControllerError #:nodoc:
17
+ class RoutingError < ActionControllerError # :nodoc:
18
18
  attr_reader :failures
19
19
  def initialize(message, failures = [])
20
20
  super(message)
@@ -22,7 +22,7 @@ module ActionController
22
22
  end
23
23
  end
24
24
 
25
- class UrlGenerationError < ActionControllerError #:nodoc:
25
+ class UrlGenerationError < ActionControllerError # :nodoc:
26
26
  attr_reader :routes, :route_name, :method_name
27
27
 
28
28
  def initialize(message, routes = nil, route_name = nil, method_name = nil)
@@ -33,44 +33,33 @@ module ActionController
33
33
  super(message)
34
34
  end
35
35
 
36
- class Correction
37
- def initialize(error)
38
- @error = error
39
- end
36
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
37
+ include DidYouMean::Correctable
40
38
 
41
39
  def corrections
42
- if @error.method_name
43
- maybe_these = @error.routes.named_routes.helper_names.grep(/#{@error.route_name}/)
44
- maybe_these -= [@error.method_name.to_s] # remove exact match
45
-
46
- maybe_these.sort_by { |n|
47
- DidYouMean::Jaro.distance(@error.route_name, n)
48
- }.reverse.first(4)
49
- else
50
- []
40
+ @corrections ||= begin
41
+ maybe_these = routes&.named_routes&.helper_names&.grep(/#{route_name}/) || []
42
+ maybe_these -= [method_name.to_s] # remove exact match
43
+
44
+ DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(route_name)
51
45
  end
52
46
  end
53
47
  end
54
-
55
- # We may not have DYM, and DYM might not let us register error handlers
56
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
57
- DidYouMean.correct_error(self, Correction)
58
- end
59
48
  end
60
49
 
61
- class MethodNotAllowed < ActionControllerError #:nodoc:
50
+ class MethodNotAllowed < ActionControllerError # :nodoc:
62
51
  def initialize(*allowed_methods)
63
52
  super("Only #{allowed_methods.to_sentence} requests are allowed.")
64
53
  end
65
54
  end
66
55
 
67
- class NotImplemented < MethodNotAllowed #:nodoc:
56
+ class NotImplemented < MethodNotAllowed # :nodoc:
68
57
  end
69
58
 
70
- class MissingFile < ActionControllerError #:nodoc:
59
+ class MissingFile < ActionControllerError # :nodoc:
71
60
  end
72
61
 
73
- class SessionOverflowError < ActionControllerError #:nodoc:
62
+ class SessionOverflowError < ActionControllerError # :nodoc:
74
63
  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
64
 
76
65
  def initialize(message = nil)
@@ -78,10 +67,10 @@ module ActionController
78
67
  end
79
68
  end
80
69
 
81
- class UnknownHttpMethod < ActionControllerError #:nodoc:
70
+ class UnknownHttpMethod < ActionControllerError # :nodoc:
82
71
  end
83
72
 
84
- class UnknownFormat < ActionControllerError #:nodoc:
73
+ class UnknownFormat < ActionControllerError # :nodoc:
85
74
  end
86
75
 
87
76
  # Raised when a nested respond_to is triggered and the content types of each
@@ -102,6 +91,6 @@ module ActionController
102
91
  end
103
92
  end
104
93
 
105
- class MissingExactTemplate < UnknownFormat #:nodoc:
94
+ class MissingExactTemplate < UnknownFormat # :nodoc:
106
95
  end
107
96
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActionController #:nodoc:
3
+ module ActionController # :nodoc:
4
4
  module Flash
5
5
  extend ActiveSupport::Concern
6
6
 
@@ -41,10 +41,14 @@ module ActionController #:nodoc:
41
41
  self._flash_types += [type]
42
42
  end
43
43
  end
44
+
45
+ def action_methods # :nodoc:
46
+ @action_methods ||= super - _flash_types.map(&:to_s).to_set
47
+ end
44
48
  end
45
49
 
46
50
  private
47
- def redirect_to(options = {}, response_options_and_flash = {}) #:doc:
51
+ def redirect_to(options = {}, response_options_and_flash = {}) # :doc:
48
52
  self.class._flash_types.each do |flash_type|
49
53
  if type = response_options_and_flash.delete(flash_type)
50
54
  flash[flash_type] = type
@@ -2,12 +2,11 @@
2
2
 
3
3
  require "base64"
4
4
  require "active_support/security_utils"
5
- require "active_support/core_ext/array/access"
6
5
 
7
6
  module ActionController
8
- # Makes it dead easy to do HTTP Basic, Digest and Token authentication.
7
+ # HTTP Basic, Digest and Token authentication.
9
8
  module HttpAuthentication
10
- # Makes it dead easy to do HTTP \Basic authentication.
9
+ # HTTP \Basic authentication.
11
10
  #
12
11
  # === Simple \Basic example
13
12
  #
@@ -25,8 +24,8 @@ module ActionController
25
24
  #
26
25
  # === Advanced \Basic example
27
26
  #
28
- # Here is a more advanced \Basic example where only Atom feeds and the XML API is protected by HTTP authentication,
29
- # the regular HTML interface is protected by a session approach:
27
+ # Here is a more advanced \Basic example where only Atom feeds and the XML API are protected by HTTP authentication.
28
+ # The regular HTML interface is protected by a session approach:
30
29
  #
31
30
  # class ApplicationController < ActionController::Base
32
31
  # before_action :set_account, :authenticate
@@ -135,15 +134,15 @@ module ActionController
135
134
  end
136
135
  end
137
136
 
138
- # Makes it dead easy to do HTTP \Digest authentication.
137
+ # HTTP \Digest authentication.
139
138
  #
140
139
  # === Simple \Digest example
141
140
  #
142
- # require "digest/md5"
141
+ # require "openssl"
143
142
  # class PostsController < ApplicationController
144
143
  # REALM = "SuperSecret"
145
144
  # USERS = {"dhh" => "secret", #plain text password
146
- # "dap" => Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":"))} #ha1 digest password
145
+ # "dap" => OpenSSL::Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":"))} #ha1 digest password
147
146
  #
148
147
  # before_action :authenticate, except: [:index]
149
148
  #
@@ -231,12 +230,12 @@ module ActionController
231
230
  # of a plain-text password.
232
231
  def expected_response(http_method, uri, credentials, password, password_is_ha1 = true)
233
232
  ha1 = password_is_ha1 ? password : ha1(credentials, password)
234
- ha2 = ::Digest::MD5.hexdigest([http_method.to_s.upcase, uri].join(":"))
235
- ::Digest::MD5.hexdigest([ha1, credentials[:nonce], credentials[:nc], credentials[:cnonce], credentials[:qop], ha2].join(":"))
233
+ ha2 = OpenSSL::Digest::MD5.hexdigest([http_method.to_s.upcase, uri].join(":"))
234
+ OpenSSL::Digest::MD5.hexdigest([ha1, credentials[:nonce], credentials[:nc], credentials[:cnonce], credentials[:qop], ha2].join(":"))
236
235
  end
237
236
 
238
237
  def ha1(credentials, password)
239
- ::Digest::MD5.hexdigest([credentials[:username], credentials[:realm], password].join(":"))
238
+ OpenSSL::Digest::MD5.hexdigest([credentials[:username], credentials[:realm], password].join(":"))
240
239
  end
241
240
 
242
241
  def encode_credentials(http_method, credentials, password, password_is_ha1)
@@ -310,7 +309,7 @@ module ActionController
310
309
  def nonce(secret_key, time = Time.now)
311
310
  t = time.to_i
312
311
  hashed = [t, secret_key]
313
- digest = ::Digest::MD5.hexdigest(hashed.join(":"))
312
+ digest = OpenSSL::Digest::MD5.hexdigest(hashed.join(":"))
314
313
  ::Base64.strict_encode64("#{t}:#{digest}")
315
314
  end
316
315
 
@@ -327,11 +326,11 @@ module ActionController
327
326
 
328
327
  # Opaque based on digest of secret key
329
328
  def opaque(secret_key)
330
- ::Digest::MD5.hexdigest(secret_key)
329
+ OpenSSL::Digest::MD5.hexdigest(secret_key)
331
330
  end
332
331
  end
333
332
 
334
- # Makes it dead easy to do HTTP Token authentication.
333
+ # HTTP Token authentication.
335
334
  #
336
335
  # Simple Token example:
337
336
  #
@@ -359,8 +358,8 @@ module ActionController
359
358
  # end
360
359
  #
361
360
  #
362
- # Here is a more advanced Token example where only Atom feeds and the XML API is protected by HTTP token authentication,
363
- # the regular HTML interface is protected by a session approach:
361
+ # Here is a more advanced Token example where only Atom feeds and the XML API are protected by HTTP token authentication.
362
+ # The regular HTML interface is protected by a session approach:
364
363
  #
365
364
  # class ApplicationController < ActionController::Base
366
365
  # before_action :set_account, :authenticate