actionpack 7.0.8.1 → 7.2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +94 -500
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +119 -106
  7. data/lib/abstract_controller/caching/fragments.rb +51 -52
  8. data/lib/abstract_controller/caching.rb +2 -0
  9. data/lib/abstract_controller/callbacks.rb +94 -67
  10. data/lib/abstract_controller/collector.rb +6 -6
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +2 -0
  13. data/lib/abstract_controller/helpers.rb +121 -91
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +3 -16
  16. data/lib/abstract_controller/rendering.rb +14 -13
  17. data/lib/abstract_controller/translation.rb +12 -30
  18. data/lib/abstract_controller/url_for.rb +9 -5
  19. data/lib/abstract_controller.rb +8 -0
  20. data/lib/action_controller/api/api_rendering.rb +2 -0
  21. data/lib/action_controller/api.rb +78 -73
  22. data/lib/action_controller/base.rb +199 -141
  23. data/lib/action_controller/caching.rb +16 -11
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +21 -16
  26. data/lib/action_controller/log_subscriber.rb +19 -5
  27. data/lib/action_controller/metal/allow_browser.rb +123 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  29. data/lib/action_controller/metal/conditional_get.rb +187 -174
  30. data/lib/action_controller/metal/content_security_policy.rb +26 -25
  31. data/lib/action_controller/metal/cookies.rb +4 -2
  32. data/lib/action_controller/metal/data_streaming.rb +65 -54
  33. data/lib/action_controller/metal/default_headers.rb +6 -2
  34. data/lib/action_controller/metal/etag_with_flash.rb +4 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +18 -14
  36. data/lib/action_controller/metal/exceptions.rb +19 -9
  37. data/lib/action_controller/metal/flash.rb +12 -10
  38. data/lib/action_controller/metal/head.rb +20 -16
  39. data/lib/action_controller/metal/helpers.rb +64 -67
  40. data/lib/action_controller/metal/http_authentication.rb +214 -200
  41. data/lib/action_controller/metal/implicit_render.rb +21 -17
  42. data/lib/action_controller/metal/instrumentation.rb +22 -12
  43. data/lib/action_controller/metal/live.rb +125 -92
  44. data/lib/action_controller/metal/logging.rb +6 -4
  45. data/lib/action_controller/metal/mime_responds.rb +151 -142
  46. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  47. data/lib/action_controller/metal/params_wrapper.rb +58 -58
  48. data/lib/action_controller/metal/permissions_policy.rb +14 -13
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +110 -84
  51. data/lib/action_controller/metal/renderers.rb +50 -49
  52. data/lib/action_controller/metal/rendering.rb +103 -82
  53. data/lib/action_controller/metal/request_forgery_protection.rb +279 -161
  54. data/lib/action_controller/metal/rescue.rb +12 -8
  55. data/lib/action_controller/metal/streaming.rb +174 -132
  56. data/lib/action_controller/metal/strong_parameters.rb +598 -473
  57. data/lib/action_controller/metal/testing.rb +2 -0
  58. data/lib/action_controller/metal/url_for.rb +23 -14
  59. data/lib/action_controller/metal.rb +145 -61
  60. data/lib/action_controller/railtie.rb +25 -9
  61. data/lib/action_controller/railties/helpers.rb +2 -0
  62. data/lib/action_controller/renderer.rb +105 -66
  63. data/lib/action_controller/template_assertions.rb +4 -2
  64. data/lib/action_controller/test_case.rb +157 -128
  65. data/lib/action_controller.rb +17 -3
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +28 -29
  69. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +69 -49
  71. data/lib/action_dispatch/http/filter_parameters.rb +27 -12
  72. data/lib/action_dispatch/http/filter_redirect.rb +22 -1
  73. data/lib/action_dispatch/http/headers.rb +23 -21
  74. data/lib/action_dispatch/http/mime_negotiation.rb +37 -48
  75. data/lib/action_dispatch/http/mime_type.rb +60 -30
  76. data/lib/action_dispatch/http/mime_types.rb +5 -1
  77. data/lib/action_dispatch/http/parameters.rb +12 -10
  78. data/lib/action_dispatch/http/permissions_policy.rb +32 -34
  79. data/lib/action_dispatch/http/rack_cache.rb +4 -0
  80. data/lib/action_dispatch/http/request.rb +132 -79
  81. data/lib/action_dispatch/http/response.rb +136 -103
  82. data/lib/action_dispatch/http/upload.rb +19 -15
  83. data/lib/action_dispatch/http/url.rb +75 -73
  84. data/lib/action_dispatch/journey/formatter.rb +19 -6
  85. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  88. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  89. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  90. data/lib/action_dispatch/journey/parser.rb +4 -3
  91. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  92. data/lib/action_dispatch/journey/path/pattern.rb +18 -15
  93. data/lib/action_dispatch/journey/route.rb +12 -9
  94. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  95. data/lib/action_dispatch/journey/router.rb +13 -10
  96. data/lib/action_dispatch/journey/routes.rb +6 -4
  97. data/lib/action_dispatch/journey/scanner.rb +4 -2
  98. data/lib/action_dispatch/journey/visitors.rb +2 -0
  99. data/lib/action_dispatch/journey.rb +2 -0
  100. data/lib/action_dispatch/log_subscriber.rb +25 -0
  101. data/lib/action_dispatch/middleware/actionable_exceptions.rb +7 -6
  102. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  103. data/lib/action_dispatch/middleware/callbacks.rb +4 -0
  104. data/lib/action_dispatch/middleware/cookies.rb +192 -194
  105. data/lib/action_dispatch/middleware/debug_exceptions.rb +36 -27
  106. data/lib/action_dispatch/middleware/debug_locks.rb +18 -13
  107. data/lib/action_dispatch/middleware/debug_view.rb +9 -2
  108. data/lib/action_dispatch/middleware/exception_wrapper.rb +181 -27
  109. data/lib/action_dispatch/middleware/executor.rb +9 -1
  110. data/lib/action_dispatch/middleware/flash.rb +65 -46
  111. data/lib/action_dispatch/middleware/host_authorization.rb +22 -17
  112. data/lib/action_dispatch/middleware/public_exceptions.rb +12 -8
  113. data/lib/action_dispatch/middleware/reloader.rb +9 -5
  114. data/lib/action_dispatch/middleware/remote_ip.rb +88 -83
  115. data/lib/action_dispatch/middleware/request_id.rb +15 -8
  116. data/lib/action_dispatch/middleware/server_timing.rb +8 -6
  117. data/lib/action_dispatch/middleware/session/abstract_store.rb +7 -0
  118. data/lib/action_dispatch/middleware/session/cache_store.rb +14 -7
  119. data/lib/action_dispatch/middleware/session/cookie_store.rb +32 -25
  120. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +9 -3
  121. data/lib/action_dispatch/middleware/show_exceptions.rb +42 -28
  122. data/lib/action_dispatch/middleware/ssl.rb +60 -45
  123. data/lib/action_dispatch/middleware/stack.rb +15 -9
  124. data/lib/action_dispatch/middleware/static.rb +40 -34
  125. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  126. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
  127. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  129. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  130. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  132. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  134. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  135. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  136. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  137. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  138. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +47 -38
  139. data/lib/action_dispatch/railtie.rb +12 -4
  140. data/lib/action_dispatch/request/session.rb +39 -27
  141. data/lib/action_dispatch/request/utils.rb +10 -3
  142. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  143. data/lib/action_dispatch/routing/inspector.rb +59 -9
  144. data/lib/action_dispatch/routing/mapper.rb +686 -639
  145. data/lib/action_dispatch/routing/polymorphic_routes.rb +70 -61
  146. data/lib/action_dispatch/routing/redirection.rb +52 -38
  147. data/lib/action_dispatch/routing/route_set.rb +106 -62
  148. data/lib/action_dispatch/routing/routes_proxy.rb +16 -19
  149. data/lib/action_dispatch/routing/url_for.rb +131 -122
  150. data/lib/action_dispatch/routing.rb +152 -150
  151. data/lib/action_dispatch/system_test_case.rb +91 -81
  152. data/lib/action_dispatch/system_testing/browser.rb +27 -19
  153. data/lib/action_dispatch/system_testing/driver.rb +16 -22
  154. data/lib/action_dispatch/system_testing/server.rb +2 -0
  155. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +53 -31
  156. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  157. data/lib/action_dispatch/testing/assertion_response.rb +9 -7
  158. data/lib/action_dispatch/testing/assertions/response.rb +36 -26
  159. data/lib/action_dispatch/testing/assertions/routing.rb +203 -95
  160. data/lib/action_dispatch/testing/assertions.rb +5 -1
  161. data/lib/action_dispatch/testing/integration.rb +240 -229
  162. data/lib/action_dispatch/testing/request_encoder.rb +6 -1
  163. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  164. data/lib/action_dispatch/testing/test_process.rb +14 -9
  165. data/lib/action_dispatch/testing/test_request.rb +4 -2
  166. data/lib/action_dispatch/testing/test_response.rb +34 -19
  167. data/lib/action_dispatch.rb +52 -21
  168. data/lib/action_pack/gem_version.rb +5 -3
  169. data/lib/action_pack/version.rb +3 -1
  170. data/lib/action_pack.rb +18 -17
  171. metadata +91 -32
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "singleton"
4
6
 
5
7
  module Mime
@@ -11,6 +13,7 @@ module Mime
11
13
  def initialize
12
14
  @mimes = []
13
15
  @symbols = []
16
+ @symbols_set = Set.new
14
17
  end
15
18
 
16
19
  def each(&block)
@@ -19,17 +22,25 @@ module Mime
19
22
 
20
23
  def <<(type)
21
24
  @mimes << type
22
- @symbols << type.to_sym
25
+ sym_type = type.to_sym
26
+ @symbols << sym_type
27
+ @symbols_set << sym_type
23
28
  end
24
29
 
25
30
  def delete_if
26
31
  @mimes.delete_if do |x|
27
32
  if yield x
28
- @symbols.delete(x.to_sym)
33
+ sym_type = x.to_sym
34
+ @symbols.delete(sym_type)
35
+ @symbols_set.delete(sym_type)
29
36
  true
30
37
  end
31
38
  end
32
39
  end
40
+
41
+ def valid_symbols?(symbols) # :nodoc
42
+ symbols.all? { |s| @symbols_set.include?(s) }
43
+ end
33
44
  end
34
45
 
35
46
  SET = Mimes.new
@@ -42,25 +53,34 @@ module Mime
42
53
  Type.lookup_by_extension(type)
43
54
  end
44
55
 
56
+ def symbols
57
+ SET.symbols
58
+ end
59
+
60
+ def valid_symbols?(symbols) # :nodoc:
61
+ SET.valid_symbols?(symbols)
62
+ end
63
+
45
64
  def fetch(type, &block)
46
65
  return type if type.is_a?(Type)
47
66
  EXTENSION_LOOKUP.fetch(type.to_s, &block)
48
67
  end
49
68
  end
50
69
 
51
- # Encapsulates the notion of a MIME type. Can be used at render time, for example, with:
70
+ # Encapsulates the notion of a MIME type. Can be used at render time, for
71
+ # example, with:
52
72
  #
53
- # class PostsController < ActionController::Base
54
- # def show
55
- # @post = Post.find(params[:id])
73
+ # class PostsController < ActionController::Base
74
+ # def show
75
+ # @post = Post.find(params[:id])
56
76
  #
57
- # respond_to do |format|
58
- # format.html
59
- # format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") }
60
- # format.xml { render xml: @post }
77
+ # respond_to do |format|
78
+ # format.html
79
+ # format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") }
80
+ # format.xml { render xml: @post }
81
+ # end
61
82
  # end
62
83
  # end
63
- # end
64
84
  class Type
65
85
  attr_reader :symbol
66
86
 
@@ -135,13 +155,20 @@ module Mime
135
155
 
136
156
  class << self
137
157
  TRAILING_STAR_REGEXP = /^(text|application)\/\*/
138
- PARAMETER_SEPARATOR_REGEXP = /;\s*\w+="?\w+"?/
158
+ # all media-type parameters need to be before the q-parameter
159
+ # https://www.rfc-editor.org/rfc/rfc7231#section-5.3.2
160
+ PARAMETER_SEPARATOR_REGEXP = /;\s*q="?/
161
+ ACCEPT_HEADER_REGEXP = /[^,\s"](?:[^,"]|"[^"]*")*/
139
162
 
140
163
  def register_callback(&block)
141
164
  @register_callbacks << block
142
165
  end
143
166
 
144
167
  def lookup(string)
168
+ return LOOKUP[string] if LOOKUP.key?(string)
169
+
170
+ # fallback to the media-type without parameters if it was not found
171
+ string = string.split(";", 2)[0]&.rstrip
145
172
  LOOKUP[string] || Type.new(string)
146
173
  end
147
174
 
@@ -149,8 +176,9 @@ module Mime
149
176
  EXTENSION_LOOKUP[extension.to_s]
150
177
  end
151
178
 
152
- # Registers an alias that's not used on MIME type lookup, but can be referenced directly. Especially useful for
153
- # rendering different HTML versions depending on the user agent, like an iPhone.
179
+ # Registers an alias that's not used on MIME type lookup, but can be referenced
180
+ # directly. Especially useful for rendering different HTML versions depending on
181
+ # the user agent, like an iPhone.
154
182
  def register_alias(string, symbol, extension_synonyms = [])
155
183
  register(string, symbol, [], extension_synonyms, true)
156
184
  end
@@ -171,12 +199,14 @@ module Mime
171
199
 
172
200
  def parse(accept_header)
173
201
  if !accept_header.include?(",")
174
- accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
175
- return [] unless accept_header
176
- parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
202
+ if (index = accept_header.index(PARAMETER_SEPARATOR_REGEXP))
203
+ accept_header = accept_header[0, index].strip
204
+ end
205
+ return [] if accept_header.blank?
206
+ parse_trailing_star(accept_header) || Array(Mime::Type.lookup(accept_header))
177
207
  else
178
208
  list, index = [], 0
179
- accept_header.split(",").each do |header|
209
+ accept_header.scan(ACCEPT_HEADER_REGEXP).each do |header|
180
210
  params, q = header.split(PARAMETER_SEPARATOR_REGEXP)
181
211
 
182
212
  next unless params
@@ -198,11 +228,11 @@ module Mime
198
228
  parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
199
229
  end
200
230
 
201
- # For an input of <tt>'text'</tt>, returns <tt>[Mime[:json], Mime[:xml], Mime[:ics],
202
- # Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]</tt>.
231
+ # For an input of `'text'`, returns `[Mime[:json], Mime[:xml], Mime[:ics],
232
+ # Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]]`.
203
233
  #
204
- # For an input of <tt>'application'</tt>, returns <tt>[Mime[:html], Mime[:js],
205
- # Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]</tt>.
234
+ # For an input of `'application'`, returns `[Mime[:html], Mime[:js], Mime[:xml],
235
+ # Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]]`.
206
236
  def parse_data_with_trailing_star(type)
207
237
  Mime::SET.select { |m| m.match?(type) }
208
238
  end
@@ -211,7 +241,7 @@ module Mime
211
241
  #
212
242
  # To unregister a MIME type:
213
243
  #
214
- # Mime::Type.unregister(:mobile)
244
+ # Mime::Type.unregister(:mobile)
215
245
  def unregister(symbol)
216
246
  symbol = symbol.downcase
217
247
  if mime = Mime[symbol]
@@ -225,7 +255,7 @@ module Mime
225
255
  attr_reader :hash
226
256
 
227
257
  MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
228
- MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?#{MIME_NAME}#{Regexp.escape('"')}?"
258
+ MIME_PARAMETER_VALUE = "(?:#{MIME_NAME}|\"[^\"\r\\\\]*\")"
229
259
  MIME_PARAMETER = "\s*;\s*#{MIME_NAME}(?:=#{MIME_PARAMETER_VALUE})?"
230
260
  MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>#{MIME_PARAMETER})*\s*)\z/
231
261
 
@@ -291,7 +321,7 @@ module Mime
291
321
  end
292
322
 
293
323
  def html?
294
- (symbol == :html) || /html/.match?(@string)
324
+ (symbol == :html) || @string.include?("html")
295
325
  end
296
326
 
297
327
  def all?; false; end
@@ -303,7 +333,7 @@ module Mime
303
333
  def to_ary; end
304
334
  def to_a; end
305
335
 
306
- def method_missing(method, *args)
336
+ def method_missing(method, ...)
307
337
  if method.end_with?("?")
308
338
  method[0..-2].downcase.to_sym == to_sym
309
339
  else
@@ -327,9 +357,9 @@ module Mime
327
357
  def html?; true; end
328
358
  end
329
359
 
330
- # ALL isn't a real MIME type, so we don't register it for lookup with the
331
- # other concrete types. It's a wildcard match that we use for +respond_to+
332
- # negotiation internals.
360
+ # ALL isn't a real MIME type, so we don't register it for lookup with the other
361
+ # concrete types. It's a wildcard match that we use for `respond_to` negotiation
362
+ # internals.
333
363
  ALL = AllType.instance
334
364
 
335
365
  class NullType
@@ -350,7 +380,7 @@ module Mime
350
380
  method.end_with?("?")
351
381
  end
352
382
 
353
- def method_missing(method, *args)
383
+ def method_missing(method, ...)
354
384
  false if method.end_with?("?")
355
385
  end
356
386
  end
@@ -3,6 +3,8 @@
3
3
  # Build list of Mime types for HTTP responses
4
4
  # https://www.iana.org/assignments/media-types/
5
5
 
6
+ # :markup: markdown
7
+
6
8
  Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
7
9
  Mime::Type.register "text/plain", :text, [], %w(txt)
8
10
  Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript )
@@ -18,6 +20,7 @@ Mime::Type.register "image/gif", :gif, [], %w(gif)
18
20
  Mime::Type.register "image/bmp", :bmp, [], %w(bmp)
19
21
  Mime::Type.register "image/tiff", :tiff, [], %w(tif tiff)
20
22
  Mime::Type.register "image/svg+xml", :svg
23
+ Mime::Type.register "image/webp", :webp, [], %w(webp)
21
24
 
22
25
  Mime::Type.register "video/mpeg", :mpeg, [], %w(mpg mpeg mpe)
23
26
 
@@ -43,7 +46,8 @@ Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
43
46
 
44
47
  # https://www.ietf.org/rfc/rfc4627.txt
45
48
  # http://www.json.org/JSONRequest.html
46
- Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
49
+ # https://www.ietf.org/rfc/rfc7807.txt
50
+ Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest application/problem+json )
47
51
 
48
52
  Mime::Type.register "application/pdf", :pdf, [], %w(pdf)
49
53
  Mime::Type.register "application/zip", :zip, [], %w(zip)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionDispatch
4
6
  module Http
5
7
  module Parameters
@@ -14,8 +16,8 @@ module ActionDispatch
14
16
  }
15
17
  }
16
18
 
17
- # Raised when raw data from the request cannot be parsed by the parser
18
- # defined for request's content MIME type.
19
+ # Raised when raw data from the request cannot be parsed by the parser defined
20
+ # for request's content MIME type.
19
21
  class ParseError < StandardError
20
22
  def initialize(message = $!.message)
21
23
  super(message)
@@ -34,8 +36,8 @@ module ActionDispatch
34
36
  module ClassMethods
35
37
  # Configure the parameter parser for a given MIME type.
36
38
  #
37
- # It accepts a hash where the key is the symbol of the MIME type
38
- # and the value is a proc.
39
+ # It accepts a hash where the key is the symbol of the MIME type and the value
40
+ # is a proc.
39
41
  #
40
42
  # original_parsers = ActionDispatch::Request.parameter_parsers
41
43
  # xml_parser = -> (raw_post) { Hash.from_xml(raw_post) || {} }
@@ -46,7 +48,7 @@ module ActionDispatch
46
48
  end
47
49
  end
48
50
 
49
- # Returns both GET and POST \parameters in a single hash.
51
+ # Returns both GET and POST parameters in a single hash.
50
52
  def parameters
51
53
  params = get_header("action_dispatch.request.parameters")
52
54
  return params if params
@@ -66,8 +68,8 @@ module ActionDispatch
66
68
  delete_header("action_dispatch.request.parameters")
67
69
 
68
70
  parameters = Request::Utils.set_binary_encoding(self, parameters, parameters[:controller], parameters[:action])
69
- # If any of the path parameters has an invalid encoding then
70
- # raise since it's likely to trigger errors further on.
71
+ # If any of the path parameters has an invalid encoding then raise since it's
72
+ # likely to trigger errors further on.
71
73
  Request::Utils.check_param_encoding(parameters)
72
74
 
73
75
  set_header PARAMETERS_KEY, parameters
@@ -75,10 +77,10 @@ module ActionDispatch
75
77
  raise ActionController::BadRequest.new("Invalid path parameters: #{e.message}")
76
78
  end
77
79
 
78
- # Returns a hash with the \parameters used to form the \path of the request.
79
- # Returned hash keys are strings:
80
+ # Returns a hash with the parameters used to form the path of the request.
81
+ # Returned hash keys are symbols:
80
82
  #
81
- # { action: "my_action", controller: "my_controller" }
83
+ # { action: "my_action", controller: "my_controller" }
82
84
  def path_parameters
83
85
  get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
84
86
  end
@@ -1,65 +1,60 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/object/deep_dup"
4
6
 
5
7
  module ActionDispatch # :nodoc:
8
+ # # Action Dispatch PermissionsPolicy
9
+ #
6
10
  # Configures the HTTP
7
- # {Feature-Policy}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy]
8
- # response header to specify which browser features the current document and
9
- # its iframes can use.
11
+ # [Feature-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy)
12
+ # response header to specify which browser features the current
13
+ # document and its iframes can use.
10
14
  #
11
15
  # Example global policy:
12
16
  #
13
- # Rails.application.config.permissions_policy do |policy|
14
- # policy.camera :none
15
- # policy.gyroscope :none
16
- # policy.microphone :none
17
- # policy.usb :none
18
- # policy.fullscreen :self
19
- # policy.payment :self, "https://secure.example.com"
20
- # end
17
+ # Rails.application.config.permissions_policy do |policy|
18
+ # policy.camera :none
19
+ # policy.gyroscope :none
20
+ # policy.microphone :none
21
+ # policy.usb :none
22
+ # policy.fullscreen :self
23
+ # policy.payment :self, "https://secure.example.com"
24
+ # end
21
25
  #
26
+ # The Feature-Policy header has been renamed to Permissions-Policy. The
27
+ # Permissions-Policy requires a different implementation and isn't yet supported
28
+ # by all browsers. To avoid having to rename this middleware in the future we
29
+ # use the new name for the middleware but keep the old header name and
30
+ # implementation for now.
22
31
  class PermissionsPolicy
23
32
  class Middleware
24
- CONTENT_TYPE = "Content-Type"
25
- # The Feature-Policy header has been renamed to Permissions-Policy.
26
- # The Permissions-Policy requires a different implementation and isn't
27
- # yet supported by all browsers. To avoid having to rename this
28
- # middleware in the future we use the new name for the middleware but
29
- # keep the old header name and implementation for now.
30
- POLICY = "Feature-Policy"
31
-
32
33
  def initialize(app)
33
34
  @app = app
34
35
  end
35
36
 
36
37
  def call(env)
37
- request = ActionDispatch::Request.new(env)
38
38
  _, headers, _ = response = @app.call(env)
39
39
 
40
- return response unless html_response?(headers)
41
40
  return response if policy_present?(headers)
42
41
 
42
+ request = ActionDispatch::Request.new(env)
43
+
43
44
  if policy = request.permissions_policy
44
- headers[POLICY] = policy.build(request.controller_instance)
45
+ headers[ActionDispatch::Constants::FEATURE_POLICY] = policy.build(request.controller_instance)
45
46
  end
46
47
 
47
48
  if policy_empty?(policy)
48
- headers.delete(POLICY)
49
+ headers.delete(ActionDispatch::Constants::FEATURE_POLICY)
49
50
  end
50
51
 
51
52
  response
52
53
  end
53
54
 
54
55
  private
55
- def html_response?(headers)
56
- if content_type = headers[CONTENT_TYPE]
57
- /html/.match?(content_type)
58
- end
59
- end
60
-
61
56
  def policy_present?(headers)
62
- headers[POLICY]
57
+ headers[ActionDispatch::Constants::FEATURE_POLICY]
63
58
  end
64
59
 
65
60
  def policy_empty?(policy)
@@ -85,7 +80,7 @@ module ActionDispatch # :nodoc:
85
80
  }.freeze
86
81
 
87
82
  # List of available permissions can be found at
88
- # https://github.com/w3c/webappsec-permissions-policy/blob/master/features.md#policy-controlled-features
83
+ # https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md#policy-controlled-features
89
84
  DIRECTIVES = {
90
85
  accelerometer: "accelerometer",
91
86
  ambient_light_sensor: "ambient-light-sensor",
@@ -95,15 +90,18 @@ module ActionDispatch # :nodoc:
95
90
  fullscreen: "fullscreen",
96
91
  geolocation: "geolocation",
97
92
  gyroscope: "gyroscope",
93
+ hid: "hid",
94
+ idle_detection: "idle-detection",
98
95
  magnetometer: "magnetometer",
99
96
  microphone: "microphone",
100
97
  midi: "midi",
101
98
  payment: "payment",
102
99
  picture_in_picture: "picture-in-picture",
103
- speaker: "speaker",
100
+ screen_wake_lock: "screen-wake-lock",
101
+ serial: "serial",
102
+ sync_xhr: "sync-xhr",
104
103
  usb: "usb",
105
- vibrate: "vibrate",
106
- vr: "vr",
104
+ web_share: "web-share",
107
105
  }.freeze
108
106
 
109
107
  private_constant :MAPPINGS, :DIRECTIVES
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :enddoc:
4
+
5
+ # :markup: markdown
6
+
3
7
  require "rack/cache"
4
8
  require "rack/cache/context"
5
9
  require "active_support/cache"