actionpack 7.1.3.4 → 7.2.0.beta1

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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -541
  3. data/lib/abstract_controller/asset_paths.rb +2 -0
  4. data/lib/abstract_controller/base.rb +102 -98
  5. data/lib/abstract_controller/caching/fragments.rb +50 -53
  6. data/lib/abstract_controller/caching.rb +2 -0
  7. data/lib/abstract_controller/callbacks.rb +66 -64
  8. data/lib/abstract_controller/collector.rb +6 -6
  9. data/lib/abstract_controller/deprecator.rb +2 -0
  10. data/lib/abstract_controller/error.rb +2 -0
  11. data/lib/abstract_controller/helpers.rb +70 -85
  12. data/lib/abstract_controller/logger.rb +2 -0
  13. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  14. data/lib/abstract_controller/rendering.rb +13 -12
  15. data/lib/abstract_controller/translation.rb +11 -10
  16. data/lib/abstract_controller/url_for.rb +8 -6
  17. data/lib/abstract_controller.rb +2 -0
  18. data/lib/action_controller/api/api_rendering.rb +2 -0
  19. data/lib/action_controller/api.rb +74 -72
  20. data/lib/action_controller/base.rb +155 -117
  21. data/lib/action_controller/caching.rb +15 -12
  22. data/lib/action_controller/deprecator.rb +2 -0
  23. data/lib/action_controller/form_builder.rb +20 -17
  24. data/lib/action_controller/log_subscriber.rb +3 -1
  25. data/lib/action_controller/metal/allow_browser.rb +119 -0
  26. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  27. data/lib/action_controller/metal/conditional_get.rb +188 -174
  28. data/lib/action_controller/metal/content_security_policy.rb +25 -24
  29. data/lib/action_controller/metal/cookies.rb +4 -2
  30. data/lib/action_controller/metal/data_streaming.rb +64 -55
  31. data/lib/action_controller/metal/default_headers.rb +5 -3
  32. data/lib/action_controller/metal/etag_with_flash.rb +3 -1
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
  34. data/lib/action_controller/metal/exceptions.rb +11 -9
  35. data/lib/action_controller/metal/flash.rb +12 -10
  36. data/lib/action_controller/metal/head.rb +12 -10
  37. data/lib/action_controller/metal/helpers.rb +63 -55
  38. data/lib/action_controller/metal/http_authentication.rb +209 -201
  39. data/lib/action_controller/metal/implicit_render.rb +17 -15
  40. data/lib/action_controller/metal/instrumentation.rb +15 -12
  41. data/lib/action_controller/metal/live.rb +113 -107
  42. data/lib/action_controller/metal/logging.rb +6 -4
  43. data/lib/action_controller/metal/mime_responds.rb +151 -142
  44. data/lib/action_controller/metal/parameter_encoding.rb +34 -32
  45. data/lib/action_controller/metal/params_wrapper.rb +57 -59
  46. data/lib/action_controller/metal/permissions_policy.rb +13 -12
  47. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  48. data/lib/action_controller/metal/redirecting.rb +108 -82
  49. data/lib/action_controller/metal/renderers.rb +50 -49
  50. data/lib/action_controller/metal/rendering.rb +103 -75
  51. data/lib/action_controller/metal/request_forgery_protection.rb +162 -133
  52. data/lib/action_controller/metal/rescue.rb +11 -9
  53. data/lib/action_controller/metal/streaming.rb +138 -136
  54. data/lib/action_controller/metal/strong_parameters.rb +525 -480
  55. data/lib/action_controller/metal/testing.rb +2 -0
  56. data/lib/action_controller/metal/url_for.rb +17 -15
  57. data/lib/action_controller/metal.rb +58 -57
  58. data/lib/action_controller/railtie.rb +3 -0
  59. data/lib/action_controller/railties/helpers.rb +2 -0
  60. data/lib/action_controller/renderer.rb +42 -36
  61. data/lib/action_controller/template_assertions.rb +4 -2
  62. data/lib/action_controller/test_case.rb +146 -126
  63. data/lib/action_controller.rb +10 -3
  64. data/lib/action_dispatch/constants.rb +2 -0
  65. data/lib/action_dispatch/deprecator.rb +2 -0
  66. data/lib/action_dispatch/http/cache.rb +27 -26
  67. data/lib/action_dispatch/http/content_disposition.rb +2 -0
  68. data/lib/action_dispatch/http/content_security_policy.rb +44 -38
  69. data/lib/action_dispatch/http/filter_parameters.rb +9 -5
  70. data/lib/action_dispatch/http/filter_redirect.rb +15 -1
  71. data/lib/action_dispatch/http/headers.rb +22 -22
  72. data/lib/action_dispatch/http/mime_negotiation.rb +30 -41
  73. data/lib/action_dispatch/http/mime_type.rb +29 -22
  74. data/lib/action_dispatch/http/mime_types.rb +2 -0
  75. data/lib/action_dispatch/http/parameters.rb +11 -9
  76. data/lib/action_dispatch/http/permissions_policy.rb +27 -37
  77. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  78. data/lib/action_dispatch/http/request.rb +71 -71
  79. data/lib/action_dispatch/http/response.rb +61 -61
  80. data/lib/action_dispatch/http/upload.rb +18 -16
  81. data/lib/action_dispatch/http/url.rb +75 -73
  82. data/lib/action_dispatch/journey/formatter.rb +13 -6
  83. data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
  84. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
  85. data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
  86. data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
  87. data/lib/action_dispatch/journey/nodes/node.rb +6 -5
  88. data/lib/action_dispatch/journey/parser.rb +4 -3
  89. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  90. data/lib/action_dispatch/journey/path/pattern.rb +4 -1
  91. data/lib/action_dispatch/journey/route.rb +9 -7
  92. data/lib/action_dispatch/journey/router/utils.rb +16 -15
  93. data/lib/action_dispatch/journey/router.rb +4 -2
  94. data/lib/action_dispatch/journey/routes.rb +4 -2
  95. data/lib/action_dispatch/journey/scanner.rb +4 -2
  96. data/lib/action_dispatch/journey/visitors.rb +2 -0
  97. data/lib/action_dispatch/journey.rb +2 -0
  98. data/lib/action_dispatch/log_subscriber.rb +2 -0
  99. data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
  100. data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
  101. data/lib/action_dispatch/middleware/callbacks.rb +3 -1
  102. data/lib/action_dispatch/middleware/cookies.rb +119 -104
  103. data/lib/action_dispatch/middleware/debug_exceptions.rb +13 -5
  104. data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
  105. data/lib/action_dispatch/middleware/debug_view.rb +2 -0
  106. data/lib/action_dispatch/middleware/exception_wrapper.rb +6 -11
  107. data/lib/action_dispatch/middleware/executor.rb +8 -0
  108. data/lib/action_dispatch/middleware/flash.rb +63 -51
  109. data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
  110. data/lib/action_dispatch/middleware/public_exceptions.rb +8 -6
  111. data/lib/action_dispatch/middleware/reloader.rb +5 -3
  112. data/lib/action_dispatch/middleware/remote_ip.rb +77 -72
  113. data/lib/action_dispatch/middleware/request_id.rb +14 -9
  114. data/lib/action_dispatch/middleware/server_timing.rb +4 -2
  115. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
  116. data/lib/action_dispatch/middleware/session/cache_store.rb +13 -8
  117. data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
  118. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
  119. data/lib/action_dispatch/middleware/show_exceptions.rb +31 -21
  120. data/lib/action_dispatch/middleware/ssl.rb +43 -40
  121. data/lib/action_dispatch/middleware/stack.rb +11 -10
  122. data/lib/action_dispatch/middleware/static.rb +33 -31
  123. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +1 -1
  124. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -1
  125. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
  126. data/lib/action_dispatch/railtie.rb +2 -4
  127. data/lib/action_dispatch/request/session.rb +23 -21
  128. data/lib/action_dispatch/request/utils.rb +2 -0
  129. data/lib/action_dispatch/routing/endpoint.rb +2 -0
  130. data/lib/action_dispatch/routing/inspector.rb +5 -3
  131. data/lib/action_dispatch/routing/mapper.rb +670 -635
  132. data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
  133. data/lib/action_dispatch/routing/redirection.rb +37 -32
  134. data/lib/action_dispatch/routing/route_set.rb +59 -45
  135. data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
  136. data/lib/action_dispatch/routing/url_for.rb +130 -125
  137. data/lib/action_dispatch/routing.rb +150 -148
  138. data/lib/action_dispatch/system_test_case.rb +91 -81
  139. data/lib/action_dispatch/system_testing/browser.rb +10 -3
  140. data/lib/action_dispatch/system_testing/driver.rb +3 -1
  141. data/lib/action_dispatch/system_testing/server.rb +2 -0
  142. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
  143. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
  144. data/lib/action_dispatch/testing/assertion_response.rb +8 -6
  145. data/lib/action_dispatch/testing/assertions/response.rb +26 -23
  146. data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
  147. data/lib/action_dispatch/testing/assertions.rb +2 -0
  148. data/lib/action_dispatch/testing/integration.rb +223 -222
  149. data/lib/action_dispatch/testing/request_encoder.rb +2 -0
  150. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  151. data/lib/action_dispatch/testing/test_process.rb +12 -8
  152. data/lib/action_dispatch/testing/test_request.rb +3 -1
  153. data/lib/action_dispatch/testing/test_response.rb +27 -26
  154. data/lib/action_dispatch.rb +22 -28
  155. data/lib/action_pack/gem_version.rb +6 -4
  156. data/lib/action_pack/version.rb +3 -1
  157. data/lib/action_pack.rb +17 -16
  158. metadata +30 -13
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/object/try"
4
6
  require "active_support/core_ext/integer/time"
5
7
 
@@ -14,116 +16,124 @@ module ActionController
14
16
  end
15
17
 
16
18
  module ClassMethods
17
- # Allows you to consider additional controller-wide information when generating an ETag.
18
- # For example, if you serve pages tailored depending on who's logged in at the moment, you
19
- # may want to add the current user id to be part of the ETag to prevent unauthorized displaying
20
- # of cached pages.
19
+ # Allows you to consider additional controller-wide information when generating
20
+ # an ETag. For example, if you serve pages tailored depending on who's logged in
21
+ # at the moment, you may want to add the current user id to be part of the ETag
22
+ # to prevent unauthorized displaying of cached pages.
21
23
  #
22
- # class InvoicesController < ApplicationController
23
- # etag { current_user&.id }
24
+ # class InvoicesController < ApplicationController
25
+ # etag { current_user&.id }
24
26
  #
25
- # def show
26
- # # Etag will differ even for the same invoice when it's viewed by a different current_user
27
- # @invoice = Invoice.find(params[:id])
28
- # fresh_when etag: @invoice
27
+ # def show
28
+ # # Etag will differ even for the same invoice when it's viewed by a different current_user
29
+ # @invoice = Invoice.find(params[:id])
30
+ # fresh_when etag: @invoice
31
+ # end
29
32
  # end
30
- # end
31
33
  def etag(&etagger)
32
34
  self.etaggers += [etagger]
33
35
  end
34
36
  end
35
37
 
36
- # Sets the +etag+, +last_modified+, or both on the response, and renders a
37
- # <tt>304 Not Modified</tt> response if the request is already fresh.
38
- #
39
- # ==== Options
40
- #
41
- # [+:etag+]
42
- # Sets a "weak" ETag validator on the response. See the +:weak_etag+ option.
43
- # [+:weak_etag+]
44
- # Sets a "weak" ETag validator on the response. Requests that specify an
45
- # +If-None-Match+ header may receive a <tt>304 Not Modified</tt> response
46
- # if the ETag matches exactly.
47
- #
48
- # A weak ETag indicates semantic equivalence, not byte-for-byte equality,
49
- # so they're good for caching HTML pages in browser caches. They can't be
50
- # used for responses that must be byte-identical, like serving +Range+
51
- # requests within a PDF file.
52
- # [+:strong_etag+]
53
- # Sets a "strong" ETag validator on the response. Requests that specify an
54
- # +If-None-Match+ header may receive a <tt>304 Not Modified</tt> response
55
- # if the ETag matches exactly.
56
- #
57
- # A strong ETag implies exact equality -- the response must match byte for
58
- # byte. This is necessary for serving +Range+ requests within a large
59
- # video or PDF file, for example, or for compatibility with some CDNs that
60
- # don't support weak ETags.
61
- # [+:last_modified+]
62
- # Sets a "weak" last-update validator on the response. Subsequent requests
63
- # that specify an +If-Modified-Since+ header may receive a <tt>304 Not Modified</tt>
64
- # response if +last_modified+ <= +If-Modified-Since+.
65
- # [+:public+]
66
- # By default the +Cache-Control+ header is private. Set this option to
67
- # +true+ if you want your application to be cacheable by other devices,
68
- # such as proxy caches.
69
- # [+:cache_control+]
70
- # When given, will overwrite an existing +Cache-Control+ header. For a
71
- # list of +Cache-Control+ directives, see the {article on
72
- # MDN}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control].
73
- # [+:template+]
74
- # By default, the template digest for the current controller/action is
75
- # included in ETags. If the action renders a different template, you can
76
- # include its digest instead. If the action doesn't render a template at
77
- # all, you can pass <tt>template: false</tt> to skip any attempt to check
78
- # for a template digest.
79
- #
80
- # ==== Examples
81
- #
82
- # def show
83
- # @article = Article.find(params[:id])
84
- # fresh_when(etag: @article, last_modified: @article.updated_at, public: true)
85
- # end
86
- #
87
- # This will send a <tt>304 Not Modified</tt> response if the request
88
- # specifies a matching ETag and +If-Modified-Since+ header. Otherwise, it
89
- # will render the +show+ template.
38
+ # Sets the `etag`, `last_modified`, or both on the response, and renders a `304
39
+ # Not Modified` response if the request is already fresh.
40
+ #
41
+ # #### Options
42
+ #
43
+ # `:etag`
44
+ # : Sets a "weak" ETag validator on the response. See the `:weak_etag` option.
45
+ #
46
+ # `:weak_etag`
47
+ # : Sets a "weak" ETag validator on the response. Requests that specify an
48
+ # `If-None-Match` header may receive a `304 Not Modified` response if the
49
+ # ETag matches exactly.
50
+ #
51
+ # : A weak ETag indicates semantic equivalence, not byte-for-byte equality, so
52
+ # they're good for caching HTML pages in browser caches. They can't be used
53
+ # for responses that must be byte-identical, like serving `Range` requests
54
+ # within a PDF file.
55
+ #
56
+ # `:strong_etag`
57
+ # : Sets a "strong" ETag validator on the response. Requests that specify an
58
+ # `If-None-Match` header may receive a `304 Not Modified` response if the
59
+ # ETag matches exactly.
60
+ #
61
+ # : A strong ETag implies exact equality -- the response must match byte for
62
+ # byte. This is necessary for serving `Range` requests within a large video
63
+ # or PDF file, for example, or for compatibility with some CDNs that don't
64
+ # support weak ETags.
65
+ #
66
+ # `:last_modified`
67
+ # : Sets a "weak" last-update validator on the response. Subsequent requests
68
+ # that specify an `If-Modified-Since` header may receive a `304 Not
69
+ # Modified` response if `last_modified` <= `If-Modified-Since`.
70
+ #
71
+ # `:public`
72
+ # : By default the `Cache-Control` header is private. Set this option to
73
+ # `true` if you want your application to be cacheable by other devices, such
74
+ # as proxy caches.
75
+ #
76
+ # `:cache_control`
77
+ # : When given, will overwrite an existing `Cache-Control` header. For a list
78
+ # of `Cache-Control` directives, see the [article on
79
+ # MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Contr
80
+ # ol).
81
+ #
82
+ # `:template`
83
+ # : By default, the template digest for the current controller/action is
84
+ # included in ETags. If the action renders a different template, you can
85
+ # include its digest instead. If the action doesn't render a template at
86
+ # all, you can pass `template: false` to skip any attempt to check for a
87
+ # template digest.
88
+ #
89
+ #
90
+ # #### Examples
91
+ #
92
+ # def show
93
+ # @article = Article.find(params[:id])
94
+ # fresh_when(etag: @article, last_modified: @article.updated_at, public: true)
95
+ # end
96
+ #
97
+ # This will send a `304 Not Modified` response if the request specifies a
98
+ # matching ETag and `If-Modified-Since` header. Otherwise, it will render the
99
+ # `show` template.
90
100
  #
91
101
  # You can also just pass a record:
92
102
  #
93
- # def show
94
- # @article = Article.find(params[:id])
95
- # fresh_when(@article)
96
- # end
103
+ # def show
104
+ # @article = Article.find(params[:id])
105
+ # fresh_when(@article)
106
+ # end
97
107
  #
98
- # +etag+ will be set to the record, and +last_modified+ will be set to the
99
- # record's +updated_at+.
108
+ # `etag` will be set to the record, and `last_modified` will be set to the
109
+ # record's `updated_at`.
100
110
  #
101
- # You can also pass an object that responds to +maximum+, such as a
102
- # collection of records:
111
+ # You can also pass an object that responds to `maximum`, such as a collection
112
+ # of records:
103
113
  #
104
- # def index
105
- # @articles = Article.all
106
- # fresh_when(@articles)
107
- # end
114
+ # def index
115
+ # @articles = Article.all
116
+ # fresh_when(@articles)
117
+ # end
108
118
  #
109
- # In this case, +etag+ will be set to the collection, and +last_modified+
110
- # will be set to <tt>maximum(:updated_at)</tt> (the timestamp of the most
111
- # recently updated record).
119
+ # In this case, `etag` will be set to the collection, and `last_modified` will
120
+ # be set to `maximum(:updated_at)` (the timestamp of the most recently updated
121
+ # record).
112
122
  #
113
- # When passing a record or a collection, you can still specify other
114
- # options, such as +:public+ and +:cache_control+:
123
+ # When passing a record or a collection, you can still specify other options,
124
+ # such as `:public` and `:cache_control`:
115
125
  #
116
- # def show
117
- # @article = Article.find(params[:id])
118
- # fresh_when(@article, public: true, cache_control: { no_cache: true })
119
- # end
126
+ # def show
127
+ # @article = Article.find(params[:id])
128
+ # fresh_when(@article, public: true, cache_control: { no_cache: true })
129
+ # end
120
130
  #
121
- # The above will set <tt>Cache-Control: public, no-cache</tt> in the response.
131
+ # The above will set `Cache-Control: public, no-cache` in the response.
122
132
  #
123
133
  # When rendering a different template than the controller/action's default
124
134
  # template, you can indicate which digest to include in the ETag:
125
135
  #
126
- # before_action { fresh_when @article, template: "widgets/show" }
136
+ # before_action { fresh_when @article, template: "widgets/show" }
127
137
  #
128
138
  def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, cache_control: {}, template: nil)
129
139
  response.cache_control.delete(:no_store)
@@ -145,131 +155,135 @@ module ActionController
145
155
  head :not_modified if request.fresh?(response)
146
156
  end
147
157
 
148
- # Sets the +etag+ and/or +last_modified+ on the response and checks them
149
- # against the request. If the request doesn't match the provided options, it
150
- # is considered stale, and the response should be rendered from scratch.
151
- # Otherwise, it is fresh, and a <tt>304 Not Modified</tt> is sent.
158
+ # Sets the `etag` and/or `last_modified` on the response and checks them against
159
+ # the request. If the request doesn't match the provided options, it is
160
+ # considered stale, and the response should be rendered from scratch. Otherwise,
161
+ # it is fresh, and a `304 Not Modified` is sent.
152
162
  #
153
- # ==== Options
163
+ # #### Options
154
164
  #
155
165
  # See #fresh_when for supported options.
156
166
  #
157
- # ==== Examples
167
+ # #### Examples
158
168
  #
159
- # def show
160
- # @article = Article.find(params[:id])
169
+ # def show
170
+ # @article = Article.find(params[:id])
161
171
  #
162
- # if stale?(etag: @article, last_modified: @article.updated_at)
163
- # @statistics = @article.really_expensive_call
164
- # respond_to do |format|
165
- # # all the supported formats
172
+ # if stale?(etag: @article, last_modified: @article.updated_at)
173
+ # @statistics = @article.really_expensive_call
174
+ # respond_to do |format|
175
+ # # all the supported formats
176
+ # end
166
177
  # end
167
178
  # end
168
- # end
169
179
  #
170
180
  # You can also just pass a record:
171
181
  #
172
- # def show
173
- # @article = Article.find(params[:id])
182
+ # def show
183
+ # @article = Article.find(params[:id])
174
184
  #
175
- # if stale?(@article)
176
- # @statistics = @article.really_expensive_call
177
- # respond_to do |format|
178
- # # all the supported formats
185
+ # if stale?(@article)
186
+ # @statistics = @article.really_expensive_call
187
+ # respond_to do |format|
188
+ # # all the supported formats
189
+ # end
179
190
  # end
180
191
  # end
181
- # end
182
192
  #
183
- # +etag+ will be set to the record, and +last_modified+ will be set to the
184
- # record's +updated_at+.
193
+ # `etag` will be set to the record, and `last_modified` will be set to the
194
+ # record's `updated_at`.
185
195
  #
186
- # You can also pass an object that responds to +maximum+, such as a
187
- # collection of records:
196
+ # You can also pass an object that responds to `maximum`, such as a collection
197
+ # of records:
188
198
  #
189
- # def index
190
- # @articles = Article.all
199
+ # def index
200
+ # @articles = Article.all
191
201
  #
192
- # if stale?(@articles)
193
- # @statistics = @articles.really_expensive_call
194
- # respond_to do |format|
195
- # # all the supported formats
202
+ # if stale?(@articles)
203
+ # @statistics = @articles.really_expensive_call
204
+ # respond_to do |format|
205
+ # # all the supported formats
206
+ # end
196
207
  # end
197
208
  # end
198
- # end
199
209
  #
200
- # In this case, +etag+ will be set to the collection, and +last_modified+
201
- # will be set to <tt>maximum(:updated_at)</tt> (the timestamp of the most
202
- # recently updated record).
210
+ # In this case, `etag` will be set to the collection, and `last_modified` will
211
+ # be set to `maximum(:updated_at)` (the timestamp of the most recently updated
212
+ # record).
203
213
  #
204
- # When passing a record or a collection, you can still specify other
205
- # options, such as +:public+ and +:cache_control+:
214
+ # When passing a record or a collection, you can still specify other options,
215
+ # such as `:public` and `:cache_control`:
206
216
  #
207
- # def show
208
- # @article = Article.find(params[:id])
217
+ # def show
218
+ # @article = Article.find(params[:id])
209
219
  #
210
- # if stale?(@article, public: true, cache_control: { no_cache: true })
211
- # @statistics = @articles.really_expensive_call
212
- # respond_to do |format|
213
- # # all the supported formats
220
+ # if stale?(@article, public: true, cache_control: { no_cache: true })
221
+ # @statistics = @articles.really_expensive_call
222
+ # respond_to do |format|
223
+ # # all the supported formats
224
+ # end
214
225
  # end
215
226
  # end
216
- # end
217
227
  #
218
- # The above will set <tt>Cache-Control: public, no-cache</tt> in the response.
228
+ # The above will set `Cache-Control: public, no-cache` in the response.
219
229
  #
220
230
  # When rendering a different template than the controller/action's default
221
231
  # template, you can indicate which digest to include in the ETag:
222
232
  #
223
- # def show
224
- # super if stale?(@article, template: "widgets/show")
225
- # end
233
+ # def show
234
+ # super if stale?(@article, template: "widgets/show")
235
+ # end
226
236
  #
227
237
  def stale?(object = nil, **freshness_kwargs)
228
238
  fresh_when(object, **freshness_kwargs)
229
239
  !request.fresh?(response)
230
240
  end
231
241
 
232
- # Sets the +Cache-Control+ header, overwriting existing directives. This
233
- # method will also ensure an HTTP +Date+ header for client compatibility.
242
+ # Sets the `Cache-Control` header, overwriting existing directives. This method
243
+ # will also ensure an HTTP `Date` header for client compatibility.
244
+ #
245
+ # Defaults to issuing the `private` directive, so that intermediate caches must
246
+ # not cache the response.
247
+ #
248
+ # #### Options
249
+ #
250
+ # `:public`
251
+ # : If true, replaces the default `private` directive with the `public`
252
+ # directive.
253
+ #
254
+ # `:must_revalidate`
255
+ # : If true, adds the `must-revalidate` directive.
234
256
  #
235
- # Defaults to issuing the +private+ directive, so that intermediate caches
236
- # must not cache the response.
257
+ # `:stale_while_revalidate`
258
+ # : Sets the value of the `stale-while-revalidate` directive.
237
259
  #
238
- # ==== Options
260
+ # `:stale_if_error`
261
+ # : Sets the value of the `stale-if-error` directive.
239
262
  #
240
- # [+:public+]
241
- # If true, replaces the default +private+ directive with the +public+
242
- # directive.
243
- # [+:must_revalidate+]
244
- # If true, adds the +must-revalidate+ directive.
245
- # [+:stale_while_revalidate+]
246
- # Sets the value of the +stale-while-revalidate+ directive.
247
- # [+:stale_if_error+]
248
- # Sets the value of the +stale-if-error+ directive.
249
263
  #
250
- # Any additional key-value pairs are concatenated as directives. For a list
251
- # of supported +Cache-Control+ directives, see the {article on
252
- # MDN}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control].
264
+ # Any additional key-value pairs are concatenated as directives. For a list of
265
+ # supported `Cache-Control` directives, see the [article on
266
+ # MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control).
253
267
  #
254
- # ==== Examples
268
+ # #### Examples
255
269
  #
256
- # expires_in 10.minutes
257
- # # => Cache-Control: max-age=600, private
270
+ # expires_in 10.minutes
271
+ # # => Cache-Control: max-age=600, private
258
272
  #
259
- # expires_in 10.minutes, public: true
260
- # # => Cache-Control: max-age=600, public
273
+ # expires_in 10.minutes, public: true
274
+ # # => Cache-Control: max-age=600, public
261
275
  #
262
- # expires_in 10.minutes, public: true, must_revalidate: true
263
- # # => Cache-Control: max-age=600, public, must-revalidate
276
+ # expires_in 10.minutes, public: true, must_revalidate: true
277
+ # # => Cache-Control: max-age=600, public, must-revalidate
264
278
  #
265
- # expires_in 1.hour, stale_while_revalidate: 60.seconds
266
- # # => Cache-Control: max-age=3600, private, stale-while-revalidate=60
279
+ # expires_in 1.hour, stale_while_revalidate: 60.seconds
280
+ # # => Cache-Control: max-age=3600, private, stale-while-revalidate=60
267
281
  #
268
- # expires_in 1.hour, stale_if_error: 5.minutes
269
- # # => Cache-Control: max-age=3600, private, stale-if-error=300
282
+ # expires_in 1.hour, stale_if_error: 5.minutes
283
+ # # => Cache-Control: max-age=3600, private, stale-if-error=300
270
284
  #
271
- # expires_in 1.hour, public: true, "s-maxage": 3.hours, "no-transform": true
272
- # # => Cache-Control: max-age=3600, public, s-maxage=10800, no-transform=true
285
+ # expires_in 1.hour, public: true, "s-maxage": 3.hours, "no-transform": true
286
+ # # => Cache-Control: max-age=3600, public, s-maxage=10800, no-transform=true
273
287
  #
274
288
  def expires_in(seconds, options = {})
275
289
  response.cache_control.delete(:no_store)
@@ -286,8 +300,8 @@ module ActionController
286
300
  response.date = Time.now unless response.date?
287
301
  end
288
302
 
289
- # Sets an HTTP 1.1 +Cache-Control+ header of <tt>no-cache</tt>. This means the
290
- # resource will be marked as stale, so clients must always revalidate.
303
+ # Sets an HTTP 1.1 `Cache-Control` header of `no-cache`. This means the resource
304
+ # will be marked as stale, so clients must always revalidate.
291
305
  # Intermediate/browser caches may still store the asset.
292
306
  def expires_now
293
307
  response.cache_control.replace(no_cache: true)
@@ -295,12 +309,12 @@ module ActionController
295
309
 
296
310
  # Cache or yield the block. The cache is supposed to never expire.
297
311
  #
298
- # You can use this method when you have an HTTP response that never changes,
299
- # and the browser and proxies should cache it indefinitely.
312
+ # You can use this method when you have an HTTP response that never changes, and
313
+ # the browser and proxies should cache it indefinitely.
300
314
  #
301
- # * +public+: By default, HTTP responses are private, cached only on the
302
- # user's web browser. To allow proxies to cache the response, set +true+ to
303
- # indicate that they can serve the cached response to all users.
315
+ # * `public`: By default, HTTP responses are private, cached only on the
316
+ # user's web browser. To allow proxies to cache the response, set `true` to
317
+ # indicate that they can serve the cached response to all users.
304
318
  def http_cache_forever(public: false)
305
319
  expires_in 100.years, public: public
306
320
 
@@ -309,8 +323,8 @@ module ActionController
309
323
  public: public)
310
324
  end
311
325
 
312
- # Sets an HTTP 1.1 +Cache-Control+ header of <tt>no-store</tt>. This means the
313
- # resource may not be stored in any cache.
326
+ # Sets an HTTP 1.1 `Cache-Control` header of `no-store`. This means the resource
327
+ # may not be stored in any cache.
314
328
  def no_store
315
329
  response.cache_control.replace(no_store: true)
316
330
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController # :nodoc:
4
6
  module ContentSecurityPolicy
5
7
  extend ActiveSupport::Concern
@@ -13,29 +15,28 @@ module ActionController # :nodoc:
13
15
  end
14
16
 
15
17
  module ClassMethods
16
- # Overrides parts of the globally configured +Content-Security-Policy+
17
- # header:
18
+ # Overrides parts of the globally configured `Content-Security-Policy` header:
18
19
  #
19
- # class PostsController < ApplicationController
20
- # content_security_policy do |policy|
21
- # policy.base_uri "https://www.example.com"
20
+ # class PostsController < ApplicationController
21
+ # content_security_policy do |policy|
22
+ # policy.base_uri "https://www.example.com"
23
+ # end
22
24
  # end
23
- # end
24
25
  #
25
- # Options can be passed similar to +before_action+. For example, pass
26
- # <tt>only: :index</tt> to override the header on the index action only:
26
+ # Options can be passed similar to `before_action`. For example, pass `only:
27
+ # :index` to override the header on the index action only:
27
28
  #
28
- # class PostsController < ApplicationController
29
- # content_security_policy(only: :index) do |policy|
30
- # policy.default_src :self, :https
29
+ # class PostsController < ApplicationController
30
+ # content_security_policy(only: :index) do |policy|
31
+ # policy.default_src :self, :https
32
+ # end
31
33
  # end
32
- # end
33
34
  #
34
- # Pass +false+ to remove the +Content-Security-Policy+ header:
35
+ # Pass `false` to remove the `Content-Security-Policy` header:
35
36
  #
36
- # class PostsController < ApplicationController
37
- # content_security_policy false, only: :index
38
- # end
37
+ # class PostsController < ApplicationController
38
+ # content_security_policy false, only: :index
39
+ # end
39
40
  def content_security_policy(enabled = true, **options, &block)
40
41
  before_action(options) do
41
42
  if block_given?
@@ -50,18 +51,18 @@ module ActionController # :nodoc:
50
51
  end
51
52
  end
52
53
 
53
- # Overrides the globally configured +Content-Security-Policy-Report-Only+
54
+ # Overrides the globally configured `Content-Security-Policy-Report-Only`
54
55
  # header:
55
56
  #
56
- # class PostsController < ApplicationController
57
- # content_security_policy_report_only only: :index
58
- # end
57
+ # class PostsController < ApplicationController
58
+ # content_security_policy_report_only only: :index
59
+ # end
59
60
  #
60
- # Pass +false+ to remove the +Content-Security-Policy-Report-Only+ header:
61
+ # Pass `false` to remove the `Content-Security-Policy-Report-Only` header:
61
62
  #
62
- # class PostsController < ApplicationController
63
- # content_security_policy_report_only false, only: :index
64
- # end
63
+ # class PostsController < ApplicationController
64
+ # content_security_policy_report_only false, only: :index
65
+ # end
65
66
  def content_security_policy_report_only(report_only = true, **options)
66
67
  before_action(options) do
67
68
  request.content_security_policy_report_only = report_only
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionController # :nodoc:
4
6
  module Cookies
5
7
  extend ActiveSupport::Concern
@@ -9,8 +11,8 @@ module ActionController # :nodoc:
9
11
  end
10
12
 
11
13
  private
12
- # The cookies for the current request. See ActionDispatch::Cookies for
13
- # more information.
14
+ # The cookies for the current request. See ActionDispatch::Cookies for more
15
+ # information.
14
16
  def cookies # :doc:
15
17
  request.cookie_jar
16
18
  end