actionpack 7.1.3.2 → 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 +70 -530
- 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 +11 -10
- 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 +209 -201
- 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 +525 -480
- 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 +10 -3
- 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 +44 -38
- data/lib/action_dispatch/http/filter_parameters.rb +9 -5
- 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 +29 -22
- 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 +20 -37
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +71 -71
- 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 +8 -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 +31 -21
- 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/rescues/missing_exact_template.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
- data/lib/action_dispatch/railtie.rb +2 -4
- 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 +5 -3
- data/lib/action_dispatch/routing/mapper.rb +670 -635
- 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 +59 -45
- 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 +10 -3
- data/lib/action_dispatch/system_testing/driver.rb +3 -1
- 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 -28
- 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 +30 -13
@@ -1,28 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "active_support/core_ext/object/deep_dup"
|
4
6
|
require "active_support/core_ext/array/wrap"
|
5
7
|
|
6
8
|
module ActionDispatch # :nodoc:
|
7
|
-
#
|
9
|
+
# # Action Dispatch Content Security Policy
|
8
10
|
#
|
9
|
-
# Configures the HTTP
|
10
|
-
#
|
11
|
-
# response header to help protect against XSS and
|
11
|
+
# Configures the HTTP [Content-Security-Policy]
|
12
|
+
# (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
|
13
|
+
# response header to help protect against XSS and
|
14
|
+
# injection attacks.
|
12
15
|
#
|
13
16
|
# Example global policy:
|
14
17
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
18
|
+
# Rails.application.config.content_security_policy do |policy|
|
19
|
+
# policy.default_src :self, :https
|
20
|
+
# policy.font_src :self, :https, :data
|
21
|
+
# policy.img_src :self, :https, :data
|
22
|
+
# policy.object_src :none
|
23
|
+
# policy.script_src :self, :https
|
24
|
+
# policy.style_src :self, :https
|
22
25
|
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
+
# # Specify URI for violation reports
|
27
|
+
# policy.report_uri "/csp-violation-report-endpoint"
|
28
|
+
# end
|
26
29
|
class ContentSecurityPolicy
|
27
30
|
class Middleware
|
28
31
|
def initialize(app)
|
@@ -32,8 +35,8 @@ module ActionDispatch # :nodoc:
|
|
32
35
|
def call(env)
|
33
36
|
status, headers, _ = response = @app.call(env)
|
34
37
|
|
35
|
-
# Returning CSP headers with a 304 Not Modified is harmful, since nonces in the
|
36
|
-
# CSP headers might not match nonces in the cached HTML.
|
38
|
+
# Returning CSP headers with a 304 Not Modified is harmful, since nonces in the
|
39
|
+
# new CSP headers might not match nonces in the cached HTML.
|
37
40
|
return response if status == 304
|
38
41
|
|
39
42
|
return response if policy_present?(headers)
|
@@ -190,14 +193,14 @@ module ActionDispatch # :nodoc:
|
|
190
193
|
end
|
191
194
|
end
|
192
195
|
|
193
|
-
# Specify whether to prevent the user agent from loading any assets over
|
194
|
-
#
|
196
|
+
# Specify whether to prevent the user agent from loading any assets over HTTP
|
197
|
+
# when the page uses HTTPS:
|
195
198
|
#
|
196
|
-
#
|
199
|
+
# policy.block_all_mixed_content
|
197
200
|
#
|
198
|
-
# Pass
|
201
|
+
# Pass `false` to allow it again:
|
199
202
|
#
|
200
|
-
#
|
203
|
+
# policy.block_all_mixed_content false
|
201
204
|
#
|
202
205
|
def block_all_mixed_content(enabled = true)
|
203
206
|
if enabled
|
@@ -209,11 +212,11 @@ module ActionDispatch # :nodoc:
|
|
209
212
|
|
210
213
|
# Restricts the set of plugins that can be embedded:
|
211
214
|
#
|
212
|
-
#
|
215
|
+
# policy.plugin_types "application/x-shockwave-flash"
|
213
216
|
#
|
214
217
|
# Leave empty to allow all plugins:
|
215
218
|
#
|
216
|
-
#
|
219
|
+
# policy.plugin_types
|
217
220
|
#
|
218
221
|
def plugin_types(*types)
|
219
222
|
if types.first
|
@@ -223,23 +226,25 @@ module ActionDispatch # :nodoc:
|
|
223
226
|
end
|
224
227
|
end
|
225
228
|
|
226
|
-
# Enable the
|
227
|
-
#
|
229
|
+
# Enable the [report-uri]
|
230
|
+
# (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri)
|
231
|
+
# directive. Violation reports will be sent to the
|
232
|
+
# specified URI:
|
228
233
|
#
|
229
|
-
#
|
234
|
+
# policy.report_uri "/csp-violation-report-endpoint"
|
230
235
|
#
|
231
236
|
def report_uri(uri)
|
232
237
|
@directives["report-uri"] = [uri]
|
233
238
|
end
|
234
239
|
|
235
|
-
# Specify asset types for which
|
236
|
-
# is required:
|
240
|
+
# Specify asset types for which [Subresource Integrity]
|
241
|
+
# (https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) is required:
|
237
242
|
#
|
238
|
-
#
|
243
|
+
# policy.require_sri_for :script, :style
|
239
244
|
#
|
240
245
|
# Leave empty to not require Subresource Integrity:
|
241
246
|
#
|
242
|
-
#
|
247
|
+
# policy.require_sri_for
|
243
248
|
#
|
244
249
|
def require_sri_for(*types)
|
245
250
|
if types.first
|
@@ -249,18 +254,19 @@ module ActionDispatch # :nodoc:
|
|
249
254
|
end
|
250
255
|
end
|
251
256
|
|
252
|
-
# Specify whether a
|
257
|
+
# Specify whether a [sandbox]
|
258
|
+
# (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox)
|
253
259
|
# should be enabled for the requested resource:
|
254
260
|
#
|
255
|
-
#
|
261
|
+
# policy.sandbox
|
256
262
|
#
|
257
263
|
# Values can be passed as arguments:
|
258
264
|
#
|
259
|
-
#
|
265
|
+
# policy.sandbox "allow-scripts", "allow-modals"
|
260
266
|
#
|
261
|
-
# Pass
|
267
|
+
# Pass `false` to disable the sandbox:
|
262
268
|
#
|
263
|
-
#
|
269
|
+
# policy.sandbox false
|
264
270
|
#
|
265
271
|
def sandbox(*values)
|
266
272
|
if values.empty?
|
@@ -274,11 +280,11 @@ module ActionDispatch # :nodoc:
|
|
274
280
|
|
275
281
|
# Specify whether user agents should treat any assets over HTTP as HTTPS:
|
276
282
|
#
|
277
|
-
#
|
283
|
+
# policy.upgrade_insecure_requests
|
278
284
|
#
|
279
|
-
# Pass
|
285
|
+
# Pass `false` to disable it:
|
280
286
|
#
|
281
|
-
#
|
287
|
+
# policy.upgrade_insecure_requests false
|
282
288
|
#
|
283
289
|
def upgrade_insecure_requests(enabled = true)
|
284
290
|
if enabled
|
@@ -1,18 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "active_support/parameter_filter"
|
4
6
|
|
5
7
|
module ActionDispatch
|
6
8
|
module Http
|
7
|
-
#
|
9
|
+
# # Action Dispatch HTTP Filter Parameters
|
8
10
|
#
|
9
11
|
# Allows you to specify sensitive query string and POST parameters to filter
|
10
12
|
# from the request log.
|
11
13
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
+
# # Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
|
15
|
+
# env["action_dispatch.parameter_filter"] = [:foo, "bar"]
|
14
16
|
#
|
15
|
-
# For more information about filter behavior, see
|
17
|
+
# For more information about filter behavior, see
|
18
|
+
# ActiveSupport::ParameterFilter.
|
16
19
|
module FilterParameters
|
17
20
|
ENV_MATCH = [/RAW_POST_DATA/, "rack.request.form_vars"] # :nodoc:
|
18
21
|
NULL_PARAM_FILTER = ActiveSupport::ParameterFilter.new # :nodoc:
|
@@ -43,7 +46,8 @@ module ActionDispatch
|
|
43
46
|
@filtered_path ||= query_string.empty? ? path : "#{path}?#{filtered_query_string}"
|
44
47
|
end
|
45
48
|
|
46
|
-
# Returns the
|
49
|
+
# Returns the `ActiveSupport::ParameterFilter` object used to filter in this
|
50
|
+
# request.
|
47
51
|
def parameter_filter
|
48
52
|
@parameter_filter ||= if has_header?("action_dispatch.parameter_filter")
|
49
53
|
parameter_filter_for get_header("action_dispatch.parameter_filter")
|
@@ -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 FilterRedirect
|
@@ -9,7 +11,7 @@ module ActionDispatch
|
|
9
11
|
if location_filter_match?
|
10
12
|
FILTERED
|
11
13
|
else
|
12
|
-
|
14
|
+
parameter_filtered_location
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
@@ -31,6 +33,18 @@ module ActionDispatch
|
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
36
|
+
|
37
|
+
def parameter_filtered_location
|
38
|
+
uri = URI.parse(location)
|
39
|
+
unless uri.query.nil? || uri.query.empty?
|
40
|
+
uri.query.gsub!(FilterParameters::PAIR_RE) do
|
41
|
+
request.parameter_filter.filter($1 => $2).first.join("=")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
uri.to_s
|
45
|
+
rescue URI::Error
|
46
|
+
FILTERED
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
@@ -1,28 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
module ActionDispatch
|
4
6
|
module Http
|
5
|
-
#
|
7
|
+
# # Action Dispatch HTTP Headers
|
6
8
|
#
|
7
9
|
# Provides access to the request's HTTP headers from the environment.
|
8
10
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# env = { "CONTENT_TYPE" => "text/plain", "HTTP_USER_AGENT" => "curl/7.43.0" }
|
12
|
+
# headers = ActionDispatch::Http::Headers.from_hash(env)
|
13
|
+
# headers["Content-Type"] # => "text/plain"
|
14
|
+
# headers["User-Agent"] # => "curl/7.43.0"
|
13
15
|
#
|
14
16
|
# Also note that when headers are mapped to CGI-like variables by the Rack
|
15
17
|
# server, both dashes and underscores are converted to underscores. This
|
16
18
|
# ambiguity cannot be resolved at this stage anymore. Both underscores and
|
17
19
|
# dashes have to be interpreted as if they were originally sent as dashes.
|
18
20
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
21
|
+
# # GET / HTTP/1.1
|
22
|
+
# # ...
|
23
|
+
# # User-Agent: curl/7.43.0
|
24
|
+
# # X_Custom_Header: token
|
23
25
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
+
# headers["X_Custom_Header"] # => nil
|
27
|
+
# headers["X-Custom-Header"] # => "token"
|
26
28
|
class Headers
|
27
29
|
CGI_VARIABLES = Set.new(%W[
|
28
30
|
AUTH_TYPE
|
@@ -67,7 +69,7 @@ module ActionDispatch
|
|
67
69
|
@req.set_header env_name(key), value
|
68
70
|
end
|
69
71
|
|
70
|
-
# Add a value to a multivalued header like
|
72
|
+
# Add a value to a multivalued header like `Vary` or `Accept-Encoding`.
|
71
73
|
def add(key, value)
|
72
74
|
@req.add_header env_name(key), value
|
73
75
|
end
|
@@ -81,11 +83,10 @@ module ActionDispatch
|
|
81
83
|
|
82
84
|
# Returns the value for the given key mapped to @env.
|
83
85
|
#
|
84
|
-
# If the key is not found and an optional code block is not provided,
|
85
|
-
#
|
86
|
+
# If the key is not found and an optional code block is not provided, raises a
|
87
|
+
# `KeyError` exception.
|
86
88
|
#
|
87
|
-
# If the code block is provided, then it will be run and
|
88
|
-
# its result returned.
|
89
|
+
# If the code block is provided, then it will be run and its result returned.
|
89
90
|
def fetch(key, default = DEFAULT)
|
90
91
|
@req.fetch_header(env_name(key)) do
|
91
92
|
return default unless default == DEFAULT
|
@@ -99,16 +100,15 @@ module ActionDispatch
|
|
99
100
|
end
|
100
101
|
|
101
102
|
# Returns a new Http::Headers instance containing the contents of
|
102
|
-
#
|
103
|
+
# `headers_or_env` and the original instance.
|
103
104
|
def merge(headers_or_env)
|
104
105
|
headers = @req.dup.headers
|
105
106
|
headers.merge!(headers_or_env)
|
106
107
|
headers
|
107
108
|
end
|
108
109
|
|
109
|
-
# Adds the contents of
|
110
|
-
#
|
111
|
-
# <tt>headers_or_env</tt>.
|
110
|
+
# Adds the contents of `headers_or_env` to original instance entries; duplicate
|
111
|
+
# keys are overwritten with the values from `headers_or_env`.
|
112
112
|
def merge!(headers_or_env)
|
113
113
|
headers_or_env.each do |key, value|
|
114
114
|
@req.set_header env_name(key), value
|
@@ -118,8 +118,8 @@ module ActionDispatch
|
|
118
118
|
def env; @req.env.dup; end
|
119
119
|
|
120
120
|
private
|
121
|
-
# Converts an HTTP header name to an environment variable name if it is
|
122
|
-
#
|
121
|
+
# Converts an HTTP header name to an environment variable name if it is not
|
122
|
+
# contained within the headers hash.
|
123
123
|
def env_name(key)
|
124
124
|
key = key.to_s
|
125
125
|
if HTTP_HEADER.match?(key)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
require "active_support/core_ext/module/attribute_accessors"
|
4
6
|
|
5
7
|
module ActionDispatch
|
@@ -16,23 +18,9 @@ module ActionDispatch
|
|
16
18
|
|
17
19
|
included do
|
18
20
|
mattr_accessor :ignore_accept_header, default: false
|
19
|
-
|
20
|
-
def return_only_media_type_on_content_type=(value)
|
21
|
-
ActionDispatch.deprecator.warn(
|
22
|
-
"`config.action_dispatch.return_only_request_media_type_on_content_type` is deprecated and will" \
|
23
|
-
" be removed in Rails 7.2."
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
def return_only_media_type_on_content_type
|
28
|
-
ActionDispatch.deprecator.warn(
|
29
|
-
"`config.action_dispatch.return_only_request_media_type_on_content_type` is deprecated and will" \
|
30
|
-
" be removed in Rails 7.2."
|
31
|
-
)
|
32
|
-
end
|
33
21
|
end
|
34
22
|
|
35
|
-
# The MIME type of the HTTP request, such as Mime
|
23
|
+
# The MIME type of the HTTP request, such as [Mime](:xml).
|
36
24
|
def content_mime_type
|
37
25
|
fetch_header("action_dispatch.request.content_type") do |k|
|
38
26
|
v = if get_header("CONTENT_TYPE") =~ /^([^,;]*)/
|
@@ -66,11 +54,11 @@ module ActionDispatch
|
|
66
54
|
end
|
67
55
|
end
|
68
56
|
|
69
|
-
# Returns the MIME type for the
|
57
|
+
# Returns the MIME type for the format used in the request.
|
70
58
|
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
59
|
+
# GET /posts/5.xml | request.format => Mime[:xml]
|
60
|
+
# GET /posts/5.xhtml | request.format => Mime[:html]
|
61
|
+
# GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first
|
74
62
|
#
|
75
63
|
def format(_view_path = nil)
|
76
64
|
formats.first || Mime::NullType.instance
|
@@ -98,7 +86,7 @@ module ActionDispatch
|
|
98
86
|
end
|
99
87
|
end
|
100
88
|
|
101
|
-
# Sets the
|
89
|
+
# Sets the variant for template.
|
102
90
|
def variant=(variant)
|
103
91
|
variant = Array(variant)
|
104
92
|
|
@@ -113,36 +101,37 @@ module ActionDispatch
|
|
113
101
|
@variant ||= ActiveSupport::ArrayInquirer.new
|
114
102
|
end
|
115
103
|
|
116
|
-
# Sets the
|
104
|
+
# Sets the format by string extension, which can be used to force custom formats
|
117
105
|
# that are not controlled by the extension.
|
118
106
|
#
|
119
|
-
#
|
120
|
-
#
|
107
|
+
# class ApplicationController < ActionController::Base
|
108
|
+
# before_action :adjust_format_for_iphone
|
121
109
|
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
110
|
+
# private
|
111
|
+
# def adjust_format_for_iphone
|
112
|
+
# request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
|
113
|
+
# end
|
114
|
+
# end
|
127
115
|
def format=(extension)
|
128
116
|
parameters[:format] = extension.to_s
|
129
117
|
set_header "action_dispatch.request.formats", [Mime::Type.lookup_by_extension(parameters[:format])]
|
130
118
|
end
|
131
119
|
|
132
|
-
# Sets the
|
133
|
-
# to set multiple, ordered formats, which is useful when you want to have a
|
120
|
+
# Sets the formats by string extensions. This differs from #format= by allowing
|
121
|
+
# you to set multiple, ordered formats, which is useful when you want to have a
|
122
|
+
# fallback.
|
134
123
|
#
|
135
|
-
# In this example, the
|
136
|
-
# to the
|
124
|
+
# In this example, the `:iphone` format will be used if it's available,
|
125
|
+
# otherwise it'll fall back to the `:html` format.
|
137
126
|
#
|
138
|
-
#
|
139
|
-
#
|
127
|
+
# class ApplicationController < ActionController::Base
|
128
|
+
# before_action :adjust_format_for_iphone_with_html_fallback
|
140
129
|
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
130
|
+
# private
|
131
|
+
# def adjust_format_for_iphone_with_html_fallback
|
132
|
+
# request.formats = [ :iphone, :html ] if request.env["HTTP_USER_AGENT"][/iPhone/]
|
133
|
+
# end
|
134
|
+
# end
|
146
135
|
def formats=(extensions)
|
147
136
|
parameters[:format] = extensions.first.to_s
|
148
137
|
set_header "action_dispatch.request.formats", extensions.collect { |extension|
|
@@ -168,8 +157,8 @@ module ActionDispatch
|
|
168
157
|
end
|
169
158
|
|
170
159
|
private
|
171
|
-
# We use normal content negotiation unless you include
|
172
|
-
#
|
160
|
+
# We use normal content negotiation unless you include **/** in your list, in
|
161
|
+
# which case we assume you're a browser and send HTML.
|
173
162
|
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
|
174
163
|
|
175
164
|
def params_readable?
|
@@ -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
|
@@ -65,19 +67,20 @@ module Mime
|
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
68
|
-
# Encapsulates the notion of a MIME type. Can be used at render time, for
|
70
|
+
# Encapsulates the notion of a MIME type. Can be used at render time, for
|
71
|
+
# example, with:
|
69
72
|
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
+
# class PostsController < ActionController::Base
|
74
|
+
# def show
|
75
|
+
# @post = Post.find(params[:id])
|
73
76
|
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
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
|
78
82
|
# end
|
79
83
|
# end
|
80
|
-
# end
|
81
84
|
class Type
|
82
85
|
attr_reader :symbol
|
83
86
|
|
@@ -162,16 +165,20 @@ module Mime
|
|
162
165
|
end
|
163
166
|
|
164
167
|
def lookup(string)
|
168
|
+
return LOOKUP[string] if LOOKUP.key?(string)
|
169
|
+
|
165
170
|
# fallback to the media-type without parameters if it was not found
|
166
|
-
|
171
|
+
string = string.split(";", 2)[0]&.rstrip
|
172
|
+
LOOKUP[string] || Type.new(string)
|
167
173
|
end
|
168
174
|
|
169
175
|
def lookup_by_extension(extension)
|
170
176
|
EXTENSION_LOOKUP[extension.to_s]
|
171
177
|
end
|
172
178
|
|
173
|
-
# Registers an alias that's not used on MIME type lookup, but can be referenced
|
174
|
-
# rendering different HTML versions depending on
|
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.
|
175
182
|
def register_alias(string, symbol, extension_synonyms = [])
|
176
183
|
register(string, symbol, [], extension_synonyms, true)
|
177
184
|
end
|
@@ -221,11 +228,11 @@ module Mime
|
|
221
228
|
parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
|
222
229
|
end
|
223
230
|
|
224
|
-
# For an input of
|
225
|
-
# Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]]
|
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]]`.
|
226
233
|
#
|
227
|
-
# For an input of
|
228
|
-
# Mime[:
|
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]]`.
|
229
236
|
def parse_data_with_trailing_star(type)
|
230
237
|
Mime::SET.select { |m| m.match?(type) }
|
231
238
|
end
|
@@ -234,7 +241,7 @@ module Mime
|
|
234
241
|
#
|
235
242
|
# To unregister a MIME type:
|
236
243
|
#
|
237
|
-
#
|
244
|
+
# Mime::Type.unregister(:mobile)
|
238
245
|
def unregister(symbol)
|
239
246
|
symbol = symbol.downcase
|
240
247
|
if mime = Mime[symbol]
|
@@ -326,7 +333,7 @@ module Mime
|
|
326
333
|
def to_ary; end
|
327
334
|
def to_a; end
|
328
335
|
|
329
|
-
def method_missing(method,
|
336
|
+
def method_missing(method, ...)
|
330
337
|
if method.end_with?("?")
|
331
338
|
method[0..-2].downcase.to_sym == to_sym
|
332
339
|
else
|
@@ -350,9 +357,9 @@ module Mime
|
|
350
357
|
def html?; true; end
|
351
358
|
end
|
352
359
|
|
353
|
-
# ALL isn't a real MIME type, so we don't register it for lookup with the
|
354
|
-
#
|
355
|
-
#
|
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.
|
356
363
|
ALL = AllType.instance
|
357
364
|
|
358
365
|
class NullType
|
@@ -373,7 +380,7 @@ module Mime
|
|
373
380
|
method.end_with?("?")
|
374
381
|
end
|
375
382
|
|
376
|
-
def method_missing(method,
|
383
|
+
def method_missing(method, ...)
|
377
384
|
false if method.end_with?("?")
|
378
385
|
end
|
379
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 )
|
@@ -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
|
-
#
|
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
|
-
#
|
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
|
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
|
-
#
|
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
|
80
|
+
# Returns a hash with the parameters used to form the path of the request.
|
79
81
|
# Returned hash keys are symbols:
|
80
82
|
#
|
81
|
-
#
|
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
|