actionpack 4.2.11.1 → 6.0.3

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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +212 -526
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +9 -9
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +47 -50
  7. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +64 -17
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/callbacks.rb +59 -31
  10. data/lib/abstract_controller/collector.rb +9 -13
  11. data/lib/abstract_controller/error.rb +6 -0
  12. data/lib/abstract_controller/helpers.rb +31 -30
  13. data/lib/abstract_controller/logger.rb +2 -0
  14. data/lib/abstract_controller/railties/routes_helpers.rb +5 -3
  15. data/lib/abstract_controller/rendering.rb +42 -41
  16. data/lib/abstract_controller/translation.rb +12 -9
  17. data/lib/abstract_controller/url_for.rb +2 -0
  18. data/lib/abstract_controller.rb +12 -5
  19. data/lib/action_controller/api/api_rendering.rb +16 -0
  20. data/lib/action_controller/api.rb +150 -0
  21. data/lib/action_controller/base.rb +25 -22
  22. data/lib/action_controller/caching.rb +13 -57
  23. data/lib/action_controller/form_builder.rb +50 -0
  24. data/lib/action_controller/log_subscriber.rb +15 -17
  25. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  26. data/lib/action_controller/metal/conditional_get.rb +124 -44
  27. data/lib/action_controller/metal/content_security_policy.rb +51 -0
  28. data/lib/action_controller/metal/cookies.rb +3 -3
  29. data/lib/action_controller/metal/data_streaming.rb +29 -49
  30. data/lib/action_controller/metal/default_headers.rb +17 -0
  31. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  32. data/lib/action_controller/metal/etag_with_template_digest.rb +20 -13
  33. data/lib/action_controller/metal/exceptions.rb +30 -15
  34. data/lib/action_controller/metal/flash.rb +9 -8
  35. data/lib/action_controller/metal/force_ssl.rb +23 -62
  36. data/lib/action_controller/metal/head.rb +22 -20
  37. data/lib/action_controller/metal/helpers.rb +26 -17
  38. data/lib/action_controller/metal/http_authentication.rb +76 -70
  39. data/lib/action_controller/metal/implicit_render.rb +53 -9
  40. data/lib/action_controller/metal/instrumentation.rb +22 -27
  41. data/lib/action_controller/metal/live.rb +101 -119
  42. data/lib/action_controller/metal/mime_responds.rb +44 -46
  43. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  44. data/lib/action_controller/metal/params_wrapper.rb +74 -63
  45. data/lib/action_controller/metal/redirecting.rb +53 -32
  46. data/lib/action_controller/metal/renderers.rb +87 -44
  47. data/lib/action_controller/metal/rendering.rb +72 -51
  48. data/lib/action_controller/metal/request_forgery_protection.rb +217 -97
  49. data/lib/action_controller/metal/rescue.rb +9 -16
  50. data/lib/action_controller/metal/streaming.rb +12 -11
  51. data/lib/action_controller/metal/strong_parameters.rb +619 -183
  52. data/lib/action_controller/metal/testing.rb +2 -17
  53. data/lib/action_controller/metal/url_for.rb +19 -10
  54. data/lib/action_controller/metal.rb +104 -87
  55. data/lib/action_controller/railtie.rb +28 -10
  56. data/lib/action_controller/railties/helpers.rb +3 -1
  57. data/lib/action_controller/renderer.rb +130 -0
  58. data/lib/action_controller/template_assertions.rb +11 -0
  59. data/lib/action_controller/test_case.rb +286 -418
  60. data/lib/action_controller.rb +33 -21
  61. data/lib/action_dispatch/http/cache.rb +100 -51
  62. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  63. data/lib/action_dispatch/http/content_security_policy.rb +282 -0
  64. data/lib/action_dispatch/http/filter_parameters.rb +31 -24
  65. data/lib/action_dispatch/http/filter_redirect.rb +10 -12
  66. data/lib/action_dispatch/http/headers.rb +54 -22
  67. data/lib/action_dispatch/http/mime_negotiation.rb +61 -45
  68. data/lib/action_dispatch/http/mime_type.rb +141 -122
  69. data/lib/action_dispatch/http/mime_types.rb +20 -6
  70. data/lib/action_dispatch/http/parameter_filter.rb +8 -68
  71. data/lib/action_dispatch/http/parameters.rb +107 -39
  72. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  73. data/lib/action_dispatch/http/request.rb +204 -117
  74. data/lib/action_dispatch/http/response.rb +248 -114
  75. data/lib/action_dispatch/http/upload.rb +21 -7
  76. data/lib/action_dispatch/http/url.rb +181 -100
  77. data/lib/action_dispatch/journey/formatter.rb +56 -34
  78. data/lib/action_dispatch/journey/gtg/builder.rb +7 -6
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +3 -9
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +17 -17
  81. data/lib/action_dispatch/journey/nfa/builder.rb +5 -3
  82. data/lib/action_dispatch/journey/nfa/dot.rb +13 -13
  83. data/lib/action_dispatch/journey/nfa/simulator.rb +3 -3
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -49
  85. data/lib/action_dispatch/journey/nodes/node.rb +25 -12
  86. data/lib/action_dispatch/journey/parser.rb +23 -22
  87. data/lib/action_dispatch/journey/parser.y +3 -2
  88. data/lib/action_dispatch/journey/parser_extras.rb +12 -4
  89. data/lib/action_dispatch/journey/path/pattern.rb +55 -46
  90. data/lib/action_dispatch/journey/route.rb +107 -28
  91. data/lib/action_dispatch/journey/router/utils.rb +25 -16
  92. data/lib/action_dispatch/journey/router.rb +35 -27
  93. data/lib/action_dispatch/journey/routes.rb +17 -17
  94. data/lib/action_dispatch/journey/scanner.rb +26 -17
  95. data/lib/action_dispatch/journey/visitors.rb +98 -54
  96. data/lib/action_dispatch/journey.rb +7 -5
  97. data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
  98. data/lib/action_dispatch/middleware/callbacks.rb +3 -6
  99. data/lib/action_dispatch/middleware/cookies.rb +292 -203
  100. data/lib/action_dispatch/middleware/debug_exceptions.rb +142 -63
  101. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  102. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  103. data/lib/action_dispatch/middleware/exception_wrapper.rb +102 -70
  104. data/lib/action_dispatch/middleware/executor.rb +21 -0
  105. data/lib/action_dispatch/middleware/flash.rb +78 -54
  106. data/lib/action_dispatch/middleware/host_authorization.rb +101 -0
  107. data/lib/action_dispatch/middleware/public_exceptions.rb +32 -27
  108. data/lib/action_dispatch/middleware/reloader.rb +5 -91
  109. data/lib/action_dispatch/middleware/remote_ip.rb +48 -41
  110. data/lib/action_dispatch/middleware/request_id.rb +17 -9
  111. data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -26
  112. data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
  113. data/lib/action_dispatch/middleware/session/cookie_store.rb +72 -73
  114. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
  115. data/lib/action_dispatch/middleware/show_exceptions.rb +26 -23
  116. data/lib/action_dispatch/middleware/ssl.rb +113 -35
  117. data/lib/action_dispatch/middleware/stack.rb +64 -41
  118. data/lib/action_dispatch/middleware/static.rb +57 -51
  119. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -14
  122. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  123. data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +4 -2
  124. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  126. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -4
  129. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  130. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +15 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +5 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  136. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  137. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  138. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  139. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  140. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +67 -64
  141. data/lib/action_dispatch/railtie.rb +26 -13
  142. data/lib/action_dispatch/request/session.rb +114 -60
  143. data/lib/action_dispatch/request/utils.rb +67 -24
  144. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  145. data/lib/action_dispatch/routing/inspector.rb +140 -102
  146. data/lib/action_dispatch/routing/mapper.rb +762 -455
  147. data/lib/action_dispatch/routing/polymorphic_routes.rb +161 -142
  148. data/lib/action_dispatch/routing/redirection.rb +36 -26
  149. data/lib/action_dispatch/routing/route_set.rb +322 -298
  150. data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
  151. data/lib/action_dispatch/routing/url_for.rb +65 -26
  152. data/lib/action_dispatch/routing.rb +36 -36
  153. data/lib/action_dispatch/system_test_case.rb +185 -0
  154. data/lib/action_dispatch/system_testing/browser.rb +80 -0
  155. data/lib/action_dispatch/system_testing/driver.rb +68 -0
  156. data/lib/action_dispatch/system_testing/server.rb +31 -0
  157. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +97 -0
  158. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +32 -0
  159. data/lib/action_dispatch/testing/assertion_response.rb +46 -0
  160. data/lib/action_dispatch/testing/assertions/response.rb +44 -20
  161. data/lib/action_dispatch/testing/assertions/routing.rb +44 -28
  162. data/lib/action_dispatch/testing/assertions.rb +6 -4
  163. data/lib/action_dispatch/testing/integration.rb +375 -215
  164. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  165. data/lib/action_dispatch/testing/test_process.rb +28 -22
  166. data/lib/action_dispatch/testing/test_request.rb +27 -34
  167. data/lib/action_dispatch/testing/test_response.rb +11 -11
  168. data/lib/action_dispatch.rb +33 -20
  169. data/lib/action_pack/gem_version.rb +6 -4
  170. data/lib/action_pack/version.rb +3 -1
  171. data/lib/action_pack.rb +4 -2
  172. metadata +71 -40
  173. data/lib/action_controller/metal/hide_actions.rb +0 -40
  174. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  175. data/lib/action_controller/middleware.rb +0 -39
  176. data/lib/action_controller/model_naming.rb +0 -12
  177. data/lib/action_dispatch/journey/backwards.rb +0 -5
  178. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  179. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  180. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  181. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  182. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,95 +1,113 @@
1
- require 'rack/session/abstract/id'
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/session/abstract/id"
2
4
 
3
5
  module ActionDispatch
4
- class Request < Rack::Request
6
+ class Request
5
7
  # Session is responsible for lazily loading the session from store.
6
8
  class Session # :nodoc:
7
- ENV_SESSION_KEY = Rack::Session::Abstract::ENV_SESSION_KEY # :nodoc:
8
- ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY # :nodoc:
9
+ ENV_SESSION_KEY = Rack::RACK_SESSION # :nodoc:
10
+ ENV_SESSION_OPTIONS_KEY = Rack::RACK_SESSION_OPTIONS # :nodoc:
9
11
 
10
- # Singleton object used to determine if an optional param wasn't specified
12
+ # Singleton object used to determine if an optional param wasn't specified.
11
13
  Unspecified = Object.new
12
14
 
13
- def self.create(store, env, default_options)
14
- session_was = find env
15
- session = Request::Session.new(store, env)
15
+ # Creates a session hash, merging the properties of the previous session if any.
16
+ def self.create(store, req, default_options)
17
+ session_was = find req
18
+ session = Request::Session.new(store, req)
16
19
  session.merge! session_was if session_was
17
20
 
18
- set(env, session)
19
- Options.set(env, Request::Session::Options.new(store, env, default_options))
21
+ set(req, session)
22
+ Options.set(req, Request::Session::Options.new(store, default_options))
20
23
  session
21
24
  end
22
25
 
23
- def self.find(env)
24
- env[ENV_SESSION_KEY]
26
+ def self.find(req)
27
+ req.get_header ENV_SESSION_KEY
25
28
  end
26
29
 
27
- def self.set(env, session)
28
- env[ENV_SESSION_KEY] = session
30
+ def self.set(req, session)
31
+ req.set_header ENV_SESSION_KEY, session
29
32
  end
30
33
 
31
34
  class Options #:nodoc:
32
- def self.set(env, options)
33
- env[ENV_SESSION_OPTIONS_KEY] = options
35
+ def self.set(req, options)
36
+ req.set_header ENV_SESSION_OPTIONS_KEY, options
34
37
  end
35
38
 
36
- def self.find(env)
37
- env[ENV_SESSION_OPTIONS_KEY]
39
+ def self.find(req)
40
+ req.get_header ENV_SESSION_OPTIONS_KEY
38
41
  end
39
42
 
40
- def initialize(by, env, default_options)
43
+ def initialize(by, default_options)
41
44
  @by = by
42
- @env = env
43
45
  @delegate = default_options.dup
44
46
  end
45
47
 
46
48
  def [](key)
47
- if key == :id
48
- @delegate.fetch(key) {
49
- @delegate[:id] = @by.send(:extract_session_id, @env)
50
- }
51
- else
52
- @delegate[key]
53
- end
49
+ @delegate[key]
50
+ end
51
+
52
+ def id(req)
53
+ @delegate.fetch(:id) {
54
+ @by.send(:extract_session_id, req)
55
+ }
54
56
  end
55
57
 
56
- def []=(k,v); @delegate[k] = v; end
58
+ def []=(k, v); @delegate[k] = v; end
57
59
  def to_hash; @delegate.dup; end
58
60
  def values_at(*args); @delegate.values_at(*args); end
59
61
  end
60
62
 
61
- def initialize(by, env)
63
+ def initialize(by, req)
62
64
  @by = by
63
- @env = env
65
+ @req = req
64
66
  @delegate = {}
65
67
  @loaded = false
66
- @exists = nil # we haven't checked yet
68
+ @exists = nil # We haven't checked yet.
67
69
  end
68
70
 
69
71
  def id
70
- options[:id]
72
+ options.id(@req)
71
73
  end
72
74
 
73
75
  def options
74
- Options.find @env
76
+ Options.find @req
75
77
  end
76
78
 
77
79
  def destroy
78
80
  clear
79
81
  options = self.options || {}
80
- new_sid = @by.send(:destroy_session, @env, options[:id], options)
81
- options[:id] = new_sid # Reset session id with a new value or nil
82
+ @by.send(:delete_session, @req, options.id(@req), options)
82
83
 
83
- # Load the new sid to be written with the response
84
+ # Load the new sid to be written with the response.
84
85
  @loaded = false
85
86
  load_for_write!
86
87
  end
87
88
 
89
+ # Returns value of the key stored in the session or
90
+ # +nil+ if the given key is not found in the session.
88
91
  def [](key)
89
92
  load_for_read!
90
- @delegate[key.to_s]
93
+ key = key.to_s
94
+
95
+ if key == "session_id"
96
+ id&.public_id
97
+ else
98
+ @delegate[key]
99
+ end
100
+ end
101
+
102
+ # Returns the nested value specified by the sequence of keys, returning
103
+ # +nil+ if any intermediate step is +nil+.
104
+ def dig(*keys)
105
+ load_for_read!
106
+ keys = keys.map.with_index { |key, i| i.zero? ? key.to_s : key }
107
+ @delegate.dig(*keys)
91
108
  end
92
109
 
110
+ # Returns true if the session has the given key or false.
93
111
  def has_key?(key)
94
112
  load_for_read!
95
113
  @delegate.key?(key.to_s)
@@ -97,40 +115,73 @@ module ActionDispatch
97
115
  alias :key? :has_key?
98
116
  alias :include? :has_key?
99
117
 
118
+ # Returns keys of the session as Array.
100
119
  def keys
120
+ load_for_read!
101
121
  @delegate.keys
102
122
  end
103
123
 
124
+ # Returns values of the session as Array.
104
125
  def values
126
+ load_for_read!
105
127
  @delegate.values
106
128
  end
107
129
 
130
+ # Writes given value to given key of the session.
108
131
  def []=(key, value)
109
132
  load_for_write!
110
133
  @delegate[key.to_s] = value
111
134
  end
112
135
 
136
+ # Clears the session.
113
137
  def clear
114
138
  load_for_write!
115
139
  @delegate.clear
116
140
  end
117
141
 
142
+ # Returns the session as Hash.
118
143
  def to_hash
119
144
  load_for_read!
120
- @delegate.dup.delete_if { |_,v| v.nil? }
121
- end
122
-
145
+ @delegate.dup.delete_if { |_, v| v.nil? }
146
+ end
147
+ alias :to_h :to_hash
148
+
149
+ # Updates the session with given Hash.
150
+ #
151
+ # session.to_hash
152
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2"}
153
+ #
154
+ # session.update({ "foo" => "bar" })
155
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
156
+ #
157
+ # session.to_hash
158
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
123
159
  def update(hash)
124
160
  load_for_write!
125
161
  @delegate.update stringify_keys(hash)
126
162
  end
127
163
 
164
+ # Deletes given key from the session.
128
165
  def delete(key)
129
166
  load_for_write!
130
167
  @delegate.delete key.to_s
131
168
  end
132
169
 
133
- def fetch(key, default=Unspecified, &block)
170
+ # Returns value of the given key from the session, or raises +KeyError+
171
+ # if can't find the given key and no default value is set.
172
+ # Returns default value if specified.
173
+ #
174
+ # session.fetch(:foo)
175
+ # # => KeyError: key not found: "foo"
176
+ #
177
+ # session.fetch(:foo, :bar)
178
+ # # => :bar
179
+ #
180
+ # session.fetch(:foo) do
181
+ # :bar
182
+ # end
183
+ # # => :bar
184
+ def fetch(key, default = Unspecified, &block)
134
185
  load_for_read!
135
186
  if default == Unspecified
136
187
  @delegate.fetch(key.to_s, &block)
@@ -149,7 +200,7 @@ module ActionDispatch
149
200
 
150
201
  def exists?
151
202
  return @exists unless @exists.nil?
152
- @exists = @by.send(:session_exists?, @env)
203
+ @exists = @by.send(:session_exists?, @req)
153
204
  end
154
205
 
155
206
  def loaded?
@@ -166,28 +217,31 @@ module ActionDispatch
166
217
  @delegate.merge!(other)
167
218
  end
168
219
 
169
- private
170
-
171
- def load_for_read!
172
- load! if !loaded? && exists?
220
+ def each(&block)
221
+ to_hash.each(&block)
173
222
  end
174
223
 
175
- def load_for_write!
176
- load! unless loaded?
177
- end
224
+ private
225
+ def load_for_read!
226
+ load! if !loaded? && exists?
227
+ end
178
228
 
179
- def load!
180
- id, session = @by.load_session @env
181
- options[:id] = id
182
- @delegate.replace(stringify_keys(session))
183
- @loaded = true
184
- end
229
+ def load_for_write!
230
+ load! unless loaded?
231
+ end
185
232
 
186
- def stringify_keys(other)
187
- other.each_with_object({}) { |(key, value), hash|
188
- hash[key.to_s] = value
189
- }
190
- end
233
+ def load!
234
+ id, session = @by.load_session @req
235
+ options[:id] = id
236
+ @delegate.replace(stringify_keys(session))
237
+ @loaded = true
238
+ end
239
+
240
+ def stringify_keys(other)
241
+ other.each_with_object({}) { |(key, value), hash|
242
+ hash[key.to_s] = value
243
+ }
244
+ end
191
245
  end
192
246
  end
193
247
  end
@@ -1,35 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/indifferent_access"
4
+
1
5
  module ActionDispatch
2
- class Request < Rack::Request
6
+ class Request
3
7
  class Utils # :nodoc:
8
+ mattr_accessor :perform_deep_munge, default: true
9
+
10
+ def self.each_param_value(params, &block)
11
+ case params
12
+ when Array
13
+ params.each { |element| each_param_value(element, &block) }
14
+ when Hash
15
+ params.each_value { |value| each_param_value(value, &block) }
16
+ when String
17
+ block.call params
18
+ end
19
+ end
4
20
 
5
- mattr_accessor :perform_deep_munge
6
- self.perform_deep_munge = true
7
-
8
- class << self
9
- # Remove nils from the params hash
10
- def deep_munge(hash, keys = [])
11
- return hash unless perform_deep_munge
12
-
13
- hash.each do |k, v|
14
- keys << k
15
- case v
16
- when Array
17
- v.grep(Hash) { |x| deep_munge(x, keys) }
18
- v.compact!
19
- if v.empty?
20
- hash[k] = nil
21
- ActiveSupport::Notifications.instrument("deep_munge.action_controller", keys: keys)
22
- end
23
- when Hash
24
- deep_munge(v, keys)
21
+ def self.normalize_encode_params(params)
22
+ if perform_deep_munge
23
+ NoNilParamEncoder.normalize_encode_params params
24
+ else
25
+ ParamEncoder.normalize_encode_params params
26
+ end
27
+ end
28
+
29
+ def self.check_param_encoding(params)
30
+ case params
31
+ when Array
32
+ params.each { |element| check_param_encoding(element) }
33
+ when Hash
34
+ params.each_value { |value| check_param_encoding(value) }
35
+ when String
36
+ unless params.valid_encoding?
37
+ # Raise Rack::Utils::InvalidParameterError for consistency with Rack.
38
+ # ActionDispatch::Request#GET will re-raise as a BadRequest error.
39
+ raise Rack::Utils::InvalidParameterError, "Invalid encoding for parameter: #{params.scrub}"
40
+ end
41
+ end
42
+ end
43
+
44
+ class ParamEncoder # :nodoc:
45
+ # Convert nested Hash to HashWithIndifferentAccess.
46
+ def self.normalize_encode_params(params)
47
+ case params
48
+ when Array
49
+ handle_array params
50
+ when Hash
51
+ if params.has_key?(:tempfile)
52
+ ActionDispatch::Http::UploadedFile.new(params)
53
+ else
54
+ params.each_with_object({}) do |(key, val), new_hash|
55
+ new_hash[key] = normalize_encode_params(val)
56
+ end.with_indifferent_access
25
57
  end
26
- keys.pop
58
+ else
59
+ params
27
60
  end
61
+ end
28
62
 
29
- hash
63
+ def self.handle_array(params)
64
+ params.map! { |el| normalize_encode_params(el) }
65
+ end
66
+ end
67
+
68
+ # Remove nils from the params hash.
69
+ class NoNilParamEncoder < ParamEncoder # :nodoc:
70
+ def self.handle_array(params)
71
+ list = super
72
+ list.compact!
73
+ list
30
74
  end
31
75
  end
32
76
  end
33
77
  end
34
78
  end
35
-
@@ -1,10 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionDispatch
2
4
  module Routing
3
5
  class Endpoint # :nodoc:
4
6
  def dispatcher?; false; end
5
7
  def redirect?; false; end
6
- def matches?(req); true; end
7
- def app; self; end
8
+ def matches?(req); true; end
9
+ def app; self; end
10
+ def rack_app; app; end
11
+
12
+ def engine?
13
+ rack_app.is_a?(Class) && rack_app < Rails::Engine
14
+ end
8
15
  end
9
16
  end
10
17
  end