actionpack 7.1.5.1 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +61 -642
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +102 -98
- data/lib/abstract_controller/caching/fragments.rb +50 -53
- data/lib/abstract_controller/caching.rb +2 -0
- data/lib/abstract_controller/callbacks.rb +66 -64
- data/lib/abstract_controller/collector.rb +6 -6
- data/lib/abstract_controller/deprecator.rb +2 -0
- data/lib/abstract_controller/error.rb +2 -0
- data/lib/abstract_controller/helpers.rb +70 -85
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +13 -12
- data/lib/abstract_controller/translation.rb +12 -13
- data/lib/abstract_controller/url_for.rb +8 -6
- data/lib/abstract_controller.rb +2 -0
- data/lib/action_controller/api/api_rendering.rb +2 -0
- data/lib/action_controller/api.rb +74 -72
- data/lib/action_controller/base.rb +155 -117
- data/lib/action_controller/caching.rb +15 -12
- data/lib/action_controller/deprecator.rb +2 -0
- data/lib/action_controller/form_builder.rb +20 -17
- data/lib/action_controller/log_subscriber.rb +3 -1
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
- data/lib/action_controller/metal/conditional_get.rb +188 -174
- data/lib/action_controller/metal/content_security_policy.rb +25 -24
- data/lib/action_controller/metal/cookies.rb +4 -2
- data/lib/action_controller/metal/data_streaming.rb +64 -55
- data/lib/action_controller/metal/default_headers.rb +5 -3
- data/lib/action_controller/metal/etag_with_flash.rb +3 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
- data/lib/action_controller/metal/exceptions.rb +11 -9
- data/lib/action_controller/metal/flash.rb +12 -10
- data/lib/action_controller/metal/head.rb +12 -10
- data/lib/action_controller/metal/helpers.rb +63 -55
- data/lib/action_controller/metal/http_authentication.rb +214 -203
- data/lib/action_controller/metal/implicit_render.rb +17 -15
- data/lib/action_controller/metal/instrumentation.rb +15 -12
- data/lib/action_controller/metal/live.rb +113 -107
- data/lib/action_controller/metal/logging.rb +6 -4
- data/lib/action_controller/metal/mime_responds.rb +151 -142
- data/lib/action_controller/metal/parameter_encoding.rb +34 -32
- data/lib/action_controller/metal/params_wrapper.rb +57 -59
- data/lib/action_controller/metal/permissions_policy.rb +13 -12
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +108 -82
- data/lib/action_controller/metal/renderers.rb +50 -49
- data/lib/action_controller/metal/rendering.rb +103 -75
- data/lib/action_controller/metal/request_forgery_protection.rb +162 -133
- data/lib/action_controller/metal/rescue.rb +11 -9
- data/lib/action_controller/metal/streaming.rb +138 -136
- data/lib/action_controller/metal/strong_parameters.rb +483 -478
- data/lib/action_controller/metal/testing.rb +2 -0
- data/lib/action_controller/metal/url_for.rb +17 -15
- data/lib/action_controller/metal.rb +58 -57
- data/lib/action_controller/railtie.rb +3 -0
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +42 -36
- data/lib/action_controller/template_assertions.rb +4 -2
- data/lib/action_controller/test_case.rb +146 -126
- data/lib/action_controller.rb +5 -1
- data/lib/action_dispatch/constants.rb +2 -0
- data/lib/action_dispatch/deprecator.rb +2 -0
- data/lib/action_dispatch/http/cache.rb +27 -26
- data/lib/action_dispatch/http/content_disposition.rb +2 -0
- data/lib/action_dispatch/http/content_security_policy.rb +48 -59
- data/lib/action_dispatch/http/filter_parameters.rb +13 -14
- data/lib/action_dispatch/http/filter_redirect.rb +15 -1
- data/lib/action_dispatch/http/headers.rb +22 -22
- data/lib/action_dispatch/http/mime_negotiation.rb +30 -41
- data/lib/action_dispatch/http/mime_type.rb +25 -21
- data/lib/action_dispatch/http/mime_types.rb +2 -0
- data/lib/action_dispatch/http/parameters.rb +11 -9
- data/lib/action_dispatch/http/permissions_policy.rb +26 -36
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +75 -95
- data/lib/action_dispatch/http/response.rb +61 -61
- data/lib/action_dispatch/http/upload.rb +18 -16
- data/lib/action_dispatch/http/url.rb +75 -73
- data/lib/action_dispatch/journey/formatter.rb +13 -6
- data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
- data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
- data/lib/action_dispatch/journey/nodes/node.rb +6 -5
- data/lib/action_dispatch/journey/parser.rb +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +2 -0
- data/lib/action_dispatch/journey/path/pattern.rb +4 -1
- data/lib/action_dispatch/journey/route.rb +9 -7
- data/lib/action_dispatch/journey/router/utils.rb +16 -15
- data/lib/action_dispatch/journey/router.rb +4 -2
- data/lib/action_dispatch/journey/routes.rb +4 -2
- data/lib/action_dispatch/journey/scanner.rb +4 -2
- data/lib/action_dispatch/journey/visitors.rb +2 -0
- data/lib/action_dispatch/journey.rb +2 -0
- data/lib/action_dispatch/log_subscriber.rb +2 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
- data/lib/action_dispatch/middleware/callbacks.rb +3 -1
- data/lib/action_dispatch/middleware/cookies.rb +119 -104
- data/lib/action_dispatch/middleware/debug_exceptions.rb +13 -5
- data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
- data/lib/action_dispatch/middleware/debug_view.rb +2 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +6 -11
- data/lib/action_dispatch/middleware/executor.rb +2 -0
- data/lib/action_dispatch/middleware/flash.rb +63 -51
- data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
- data/lib/action_dispatch/middleware/public_exceptions.rb +8 -6
- data/lib/action_dispatch/middleware/reloader.rb +5 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +77 -72
- data/lib/action_dispatch/middleware/request_id.rb +14 -9
- data/lib/action_dispatch/middleware/server_timing.rb +4 -2
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +13 -8
- data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +16 -16
- data/lib/action_dispatch/middleware/ssl.rb +43 -40
- data/lib/action_dispatch/middleware/stack.rb +11 -10
- data/lib/action_dispatch/middleware/static.rb +33 -31
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
- data/lib/action_dispatch/railtie.rb +2 -3
- data/lib/action_dispatch/request/session.rb +23 -21
- data/lib/action_dispatch/request/utils.rb +2 -0
- data/lib/action_dispatch/routing/endpoint.rb +2 -0
- data/lib/action_dispatch/routing/inspector.rb +6 -4
- data/lib/action_dispatch/routing/mapper.rb +623 -625
- data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
- data/lib/action_dispatch/routing/redirection.rb +37 -32
- data/lib/action_dispatch/routing/route_set.rb +60 -46
- data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
- data/lib/action_dispatch/routing/url_for.rb +130 -125
- data/lib/action_dispatch/routing.rb +150 -148
- data/lib/action_dispatch/system_test_case.rb +91 -81
- data/lib/action_dispatch/system_testing/browser.rb +4 -2
- data/lib/action_dispatch/system_testing/driver.rb +2 -0
- data/lib/action_dispatch/system_testing/server.rb +2 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
- data/lib/action_dispatch/testing/assertion_response.rb +8 -6
- data/lib/action_dispatch/testing/assertions/response.rb +26 -23
- data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
- data/lib/action_dispatch/testing/assertions.rb +2 -0
- data/lib/action_dispatch/testing/integration.rb +223 -222
- data/lib/action_dispatch/testing/request_encoder.rb +2 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +12 -8
- data/lib/action_dispatch/testing/test_request.rb +3 -1
- data/lib/action_dispatch/testing/test_response.rb +27 -26
- data/lib/action_dispatch.rb +22 -32
- data/lib/action_pack/gem_version.rb +6 -4
- data/lib/action_pack/version.rb +3 -1
- data/lib/action_pack.rb +17 -16
- metadata +33 -16
@@ -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
|
18
|
-
# For example, if you serve pages tailored depending on who's logged in
|
19
|
-
# may want to add the current user id to be part of the ETag
|
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
|
-
#
|
23
|
-
#
|
24
|
+
# class InvoicesController < ApplicationController
|
25
|
+
# etag { current_user&.id }
|
24
26
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
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
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
# Sets a "weak" ETag validator on the response. See the
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
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
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
103
|
+
# def show
|
104
|
+
# @article = Article.find(params[:id])
|
105
|
+
# fresh_when(@article)
|
106
|
+
# end
|
97
107
|
#
|
98
|
-
#
|
99
|
-
# record's
|
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
|
102
|
-
#
|
111
|
+
# You can also pass an object that responds to `maximum`, such as a collection
|
112
|
+
# of records:
|
103
113
|
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
114
|
+
# def index
|
115
|
+
# @articles = Article.all
|
116
|
+
# fresh_when(@articles)
|
117
|
+
# end
|
108
118
|
#
|
109
|
-
# In this case,
|
110
|
-
#
|
111
|
-
#
|
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
|
-
#
|
123
|
+
# When passing a record or a collection, you can still specify other options,
|
124
|
+
# such as `:public` and `:cache_control`:
|
115
125
|
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
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
|
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
|
-
#
|
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
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
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
|
-
#
|
163
|
+
# #### Options
|
154
164
|
#
|
155
165
|
# See #fresh_when for supported options.
|
156
166
|
#
|
157
|
-
#
|
167
|
+
# #### Examples
|
158
168
|
#
|
159
|
-
#
|
160
|
-
#
|
169
|
+
# def show
|
170
|
+
# @article = Article.find(params[:id])
|
161
171
|
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
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
|
-
#
|
173
|
-
#
|
182
|
+
# def show
|
183
|
+
# @article = Article.find(params[:id])
|
174
184
|
#
|
175
|
-
#
|
176
|
-
#
|
177
|
-
#
|
178
|
-
#
|
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
|
-
#
|
184
|
-
# record's
|
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
|
187
|
-
#
|
196
|
+
# You can also pass an object that responds to `maximum`, such as a collection
|
197
|
+
# of records:
|
188
198
|
#
|
189
|
-
#
|
190
|
-
#
|
199
|
+
# def index
|
200
|
+
# @articles = Article.all
|
191
201
|
#
|
192
|
-
#
|
193
|
-
#
|
194
|
-
#
|
195
|
-
#
|
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,
|
201
|
-
#
|
202
|
-
#
|
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
|
-
#
|
214
|
+
# When passing a record or a collection, you can still specify other options,
|
215
|
+
# such as `:public` and `:cache_control`:
|
206
216
|
#
|
207
|
-
#
|
208
|
-
#
|
217
|
+
# def show
|
218
|
+
# @article = Article.find(params[:id])
|
209
219
|
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
213
|
-
#
|
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
|
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
|
-
#
|
224
|
-
#
|
225
|
-
#
|
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
|
233
|
-
#
|
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
|
-
#
|
236
|
-
#
|
257
|
+
# `:stale_while_revalidate`
|
258
|
+
# : Sets the value of the `stale-while-revalidate` directive.
|
237
259
|
#
|
238
|
-
#
|
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
|
-
#
|
252
|
-
# MDN
|
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
|
-
#
|
268
|
+
# #### Examples
|
255
269
|
#
|
256
|
-
#
|
257
|
-
#
|
270
|
+
# expires_in 10.minutes
|
271
|
+
# # => Cache-Control: max-age=600, private
|
258
272
|
#
|
259
|
-
#
|
260
|
-
#
|
273
|
+
# expires_in 10.minutes, public: true
|
274
|
+
# # => Cache-Control: max-age=600, public
|
261
275
|
#
|
262
|
-
#
|
263
|
-
#
|
276
|
+
# expires_in 10.minutes, public: true, must_revalidate: true
|
277
|
+
# # => Cache-Control: max-age=600, public, must-revalidate
|
264
278
|
#
|
265
|
-
#
|
266
|
-
#
|
279
|
+
# expires_in 1.hour, stale_while_revalidate: 60.seconds
|
280
|
+
# # => Cache-Control: max-age=3600, private, stale-while-revalidate=60
|
267
281
|
#
|
268
|
-
#
|
269
|
-
#
|
282
|
+
# expires_in 1.hour, stale_if_error: 5.minutes
|
283
|
+
# # => Cache-Control: max-age=3600, private, stale-if-error=300
|
270
284
|
#
|
271
|
-
#
|
272
|
-
#
|
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
|
290
|
-
#
|
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
|
-
#
|
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
|
-
# *
|
302
|
-
#
|
303
|
-
#
|
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
|
313
|
-
#
|
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
|
17
|
-
# header:
|
18
|
+
# Overrides parts of the globally configured `Content-Security-Policy` header:
|
18
19
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
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
|
26
|
-
#
|
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
|
-
#
|
29
|
-
#
|
30
|
-
#
|
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
|
35
|
+
# Pass `false` to remove the `Content-Security-Policy` header:
|
35
36
|
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
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
|
54
|
+
# Overrides the globally configured `Content-Security-Policy-Report-Only`
|
54
55
|
# header:
|
55
56
|
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
57
|
+
# class PostsController < ApplicationController
|
58
|
+
# content_security_policy_report_only only: :index
|
59
|
+
# end
|
59
60
|
#
|
60
|
-
# Pass
|
61
|
+
# Pass `false` to remove the `Content-Security-Policy-Report-Only` header:
|
61
62
|
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
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
|
-
#
|
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
|