actionpack 6.0.3.2 → 6.1.0
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 +258 -223
- data/MIT-LICENSE +1 -1
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/base.rb +35 -2
- data/lib/abstract_controller/callbacks.rb +2 -2
- data/lib/abstract_controller/helpers.rb +105 -90
- data/lib/abstract_controller/rendering.rb +9 -9
- data/lib/abstract_controller/translation.rb +8 -2
- data/lib/action_controller.rb +2 -3
- data/lib/action_controller/api.rb +2 -2
- data/lib/action_controller/base.rb +4 -2
- data/lib/action_controller/caching.rb +0 -1
- data/lib/action_controller/log_subscriber.rb +3 -3
- data/lib/action_controller/metal.rb +2 -2
- data/lib/action_controller/metal/conditional_get.rb +10 -2
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/cookies.rb +3 -1
- data/lib/action_controller/metal/data_streaming.rb +1 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -4
- data/lib/action_controller/metal/exceptions.rb +33 -0
- data/lib/action_controller/metal/head.rb +7 -4
- data/lib/action_controller/metal/helpers.rb +11 -1
- data/lib/action_controller/metal/http_authentication.rb +4 -2
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +11 -9
- data/lib/action_controller/metal/live.rb +1 -1
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +6 -2
- data/lib/action_controller/metal/parameter_encoding.rb +35 -4
- data/lib/action_controller/metal/params_wrapper.rb +14 -8
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +1 -1
- data/lib/action_controller/metal/rendering.rb +6 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +48 -24
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/strong_parameters.rb +103 -15
- data/lib/action_controller/renderer.rb +24 -13
- data/lib/action_controller/test_case.rb +62 -56
- data/lib/action_dispatch.rb +3 -2
- data/lib/action_dispatch/http/cache.rb +12 -10
- data/lib/action_dispatch/http/content_disposition.rb +2 -2
- data/lib/action_dispatch/http/content_security_policy.rb +5 -1
- data/lib/action_dispatch/http/filter_parameters.rb +1 -1
- data/lib/action_dispatch/http/filter_redirect.rb +1 -1
- data/lib/action_dispatch/http/headers.rb +3 -2
- data/lib/action_dispatch/http/mime_negotiation.rb +20 -8
- data/lib/action_dispatch/http/mime_type.rb +28 -15
- data/lib/action_dispatch/http/parameters.rb +1 -19
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/request.rb +26 -8
- data/lib/action_dispatch/http/response.rb +17 -16
- data/lib/action_dispatch/http/url.rb +3 -2
- data/lib/action_dispatch/journey.rb +0 -2
- data/lib/action_dispatch/journey/formatter.rb +53 -28
- data/lib/action_dispatch/journey/gtg/builder.rb +22 -36
- data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -4
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
- data/lib/action_dispatch/journey/nodes/node.rb +4 -3
- data/lib/action_dispatch/journey/parser.rb +13 -13
- data/lib/action_dispatch/journey/parser.y +1 -1
- data/lib/action_dispatch/journey/path/pattern.rb +13 -18
- data/lib/action_dispatch/journey/route.rb +7 -18
- data/lib/action_dispatch/journey/router.rb +26 -30
- data/lib/action_dispatch/journey/router/utils.rb +6 -4
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +9 -2
- data/lib/action_dispatch/middleware/cookies.rb +74 -33
- data/lib/action_dispatch/middleware/debug_exceptions.rb +10 -17
- data/lib/action_dispatch/middleware/debug_view.rb +1 -1
- data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -17
- data/lib/action_dispatch/middleware/host_authorization.rb +25 -5
- data/lib/action_dispatch/middleware/public_exceptions.rb +1 -1
- data/lib/action_dispatch/middleware/remote_ip.rb +5 -4
- data/lib/action_dispatch/middleware/request_id.rb +4 -5
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -2
- data/lib/action_dispatch/middleware/session/cookie_store.rb +2 -2
- data/lib/action_dispatch/middleware/ssl.rb +9 -6
- data/lib/action_dispatch/middleware/stack.rb +18 -0
- data/lib/action_dispatch/middleware/static.rb +154 -93
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +2 -5
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +100 -8
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +12 -1
- data/lib/action_dispatch/railtie.rb +3 -2
- data/lib/action_dispatch/request/session.rb +2 -8
- data/lib/action_dispatch/request/utils.rb +26 -2
- data/lib/action_dispatch/routing/inspector.rb +8 -7
- data/lib/action_dispatch/routing/mapper.rb +102 -71
- data/lib/action_dispatch/routing/polymorphic_routes.rb +12 -11
- data/lib/action_dispatch/routing/redirection.rb +3 -3
- data/lib/action_dispatch/routing/route_set.rb +49 -41
- data/lib/action_dispatch/routing/url_for.rb +1 -0
- data/lib/action_dispatch/system_test_case.rb +29 -24
- data/lib/action_dispatch/system_testing/browser.rb +33 -27
- data/lib/action_dispatch/system_testing/driver.rb +6 -7
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +47 -6
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +4 -7
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +2 -4
- data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
- data/lib/action_dispatch/testing/integration.rb +38 -27
- data/lib/action_dispatch/testing/test_process.rb +29 -4
- data/lib/action_dispatch/testing/test_request.rb +3 -3
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/gem_version.rb +3 -3
- metadata +21 -22
- data/lib/action_controller/metal/force_ssl.rb +0 -58
- data/lib/action_dispatch/http/parameter_filter.rb +0 -12
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -119
@@ -65,7 +65,7 @@ module ActionController
|
|
65
65
|
def initialize(controller, env, defaults)
|
66
66
|
@controller = controller
|
67
67
|
@defaults = defaults
|
68
|
-
@env = normalize_keys defaults
|
68
|
+
@env = normalize_keys defaults, env
|
69
69
|
end
|
70
70
|
|
71
71
|
# Render templates with any options from ActionController::Base#render_to_string.
|
@@ -82,8 +82,12 @@ module ActionController
|
|
82
82
|
# need to call <tt>.to_json</tt> on the object you want to render.
|
83
83
|
# * <tt>:body</tt> - Renders provided text and sets content type of <tt>text/plain</tt>.
|
84
84
|
#
|
85
|
-
# If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified,
|
86
|
-
#
|
85
|
+
# If no <tt>options</tt> hash is passed or if <tt>:update</tt> is specified, then:
|
86
|
+
#
|
87
|
+
# If an object responding to `render_in` is passed, `render_in` is called on the object,
|
88
|
+
# passing in the current view context.
|
89
|
+
#
|
90
|
+
# Otherwise, a partial is rendered using the second parameter as the locals hash.
|
87
91
|
def render(*args)
|
88
92
|
raise "missing controller" unless controller
|
89
93
|
|
@@ -95,11 +99,18 @@ module ActionController
|
|
95
99
|
instance.set_response! controller.make_response!(request)
|
96
100
|
instance.render_to_string(*args)
|
97
101
|
end
|
102
|
+
alias_method :render_to_string, :render # :nodoc:
|
98
103
|
|
99
104
|
private
|
100
|
-
def normalize_keys(env)
|
105
|
+
def normalize_keys(defaults, env)
|
101
106
|
new_env = {}
|
102
107
|
env.each_pair { |k, v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
|
108
|
+
|
109
|
+
defaults.each_pair do |k, v|
|
110
|
+
key = rack_key_for(k)
|
111
|
+
new_env[key] = rack_value_for(k, v) unless new_env.key?(key)
|
112
|
+
end
|
113
|
+
|
103
114
|
new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
|
104
115
|
new_env
|
105
116
|
end
|
@@ -112,19 +123,19 @@ module ActionController
|
|
112
123
|
input: "rack.input"
|
113
124
|
}
|
114
125
|
|
115
|
-
IDENTITY = ->(_) { _ }
|
116
|
-
|
117
|
-
RACK_VALUE_TRANSLATION = {
|
118
|
-
https: ->(v) { v ? "on" : "off" },
|
119
|
-
method: ->(v) { -v.upcase },
|
120
|
-
}
|
121
|
-
|
122
126
|
def rack_key_for(key)
|
123
|
-
RACK_KEY_TRANSLATION
|
127
|
+
RACK_KEY_TRANSLATION[key] || key.to_s
|
124
128
|
end
|
125
129
|
|
126
130
|
def rack_value_for(key, value)
|
127
|
-
|
131
|
+
case key
|
132
|
+
when :https
|
133
|
+
value ? "on" : "off"
|
134
|
+
when :method
|
135
|
+
-value.upcase
|
136
|
+
else
|
137
|
+
value
|
138
|
+
end
|
128
139
|
end
|
129
140
|
end
|
130
141
|
end
|
@@ -84,7 +84,7 @@ module ActionController
|
|
84
84
|
value = value.to_param
|
85
85
|
end
|
86
86
|
|
87
|
-
path_parameters[key] = value
|
87
|
+
path_parameters[key.to_sym] = value
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -492,57 +492,8 @@ module ActionController
|
|
492
492
|
parameters[:format] = format
|
493
493
|
end
|
494
494
|
|
495
|
-
|
496
|
-
|
497
|
-
query_string_keys = query_parameter_names(generated_extras)
|
498
|
-
|
499
|
-
@request.assign_parameters(@routes, controller_class_name, action, parameters, generated_path, query_string_keys)
|
500
|
-
|
501
|
-
@request.session.update(session) if session
|
502
|
-
@request.flash.update(flash || {})
|
503
|
-
|
504
|
-
if xhr
|
505
|
-
@request.set_header "HTTP_X_REQUESTED_WITH", "XMLHttpRequest"
|
506
|
-
@request.fetch_header("HTTP_ACCEPT") do |k|
|
507
|
-
@request.set_header k, [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(", ")
|
508
|
-
end
|
509
|
-
end
|
510
|
-
|
511
|
-
@request.fetch_header("SCRIPT_NAME") do |k|
|
512
|
-
@request.set_header k, @controller.config.relative_url_root
|
513
|
-
end
|
514
|
-
|
515
|
-
begin
|
516
|
-
@controller.recycle!
|
517
|
-
@controller.dispatch(action, @request, @response)
|
518
|
-
ensure
|
519
|
-
@request = @controller.request
|
520
|
-
@response = @controller.response
|
521
|
-
|
522
|
-
if @request.have_cookie_jar?
|
523
|
-
unless @request.cookie_jar.committed?
|
524
|
-
@request.cookie_jar.write(@response)
|
525
|
-
cookies.update(@request.cookie_jar.instance_variable_get(:@cookies))
|
526
|
-
end
|
527
|
-
end
|
528
|
-
@response.prepare!
|
529
|
-
|
530
|
-
if flash_value = @request.flash.to_session_value
|
531
|
-
@request.session["flash"] = flash_value
|
532
|
-
else
|
533
|
-
@request.session.delete("flash")
|
534
|
-
end
|
535
|
-
|
536
|
-
if xhr
|
537
|
-
@request.delete_header "HTTP_X_REQUESTED_WITH"
|
538
|
-
@request.delete_header "HTTP_ACCEPT"
|
539
|
-
end
|
540
|
-
@request.query_string = ""
|
541
|
-
|
542
|
-
@response.sent!
|
543
|
-
end
|
544
|
-
|
545
|
-
@response
|
495
|
+
setup_request(controller_class_name, action, parameters, session, flash, xhr)
|
496
|
+
process_controller_response(action, cookies, xhr)
|
546
497
|
end
|
547
498
|
|
548
499
|
def controller_class_name
|
@@ -598,11 +549,66 @@ module ActionController
|
|
598
549
|
end
|
599
550
|
|
600
551
|
private
|
552
|
+
def setup_request(controller_class_name, action, parameters, session, flash, xhr)
|
553
|
+
generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action))
|
554
|
+
generated_path = generated_path(generated_extras)
|
555
|
+
query_string_keys = query_parameter_names(generated_extras)
|
556
|
+
|
557
|
+
@request.assign_parameters(@routes, controller_class_name, action, parameters, generated_path, query_string_keys)
|
558
|
+
|
559
|
+
@request.session.update(session) if session
|
560
|
+
@request.flash.update(flash || {})
|
561
|
+
|
562
|
+
if xhr
|
563
|
+
@request.set_header "HTTP_X_REQUESTED_WITH", "XMLHttpRequest"
|
564
|
+
@request.fetch_header("HTTP_ACCEPT") do |k|
|
565
|
+
@request.set_header k, [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(", ")
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
@request.fetch_header("SCRIPT_NAME") do |k|
|
570
|
+
@request.set_header k, @controller.config.relative_url_root
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
def process_controller_response(action, cookies, xhr)
|
575
|
+
begin
|
576
|
+
@controller.recycle!
|
577
|
+
@controller.dispatch(action, @request, @response)
|
578
|
+
ensure
|
579
|
+
@request = @controller.request
|
580
|
+
@response = @controller.response
|
581
|
+
|
582
|
+
if @request.have_cookie_jar?
|
583
|
+
unless @request.cookie_jar.committed?
|
584
|
+
@request.cookie_jar.write(@response)
|
585
|
+
cookies.update(@request.cookie_jar.instance_variable_get(:@cookies))
|
586
|
+
end
|
587
|
+
end
|
588
|
+
@response.prepare!
|
589
|
+
|
590
|
+
if flash_value = @request.flash.to_session_value
|
591
|
+
@request.session["flash"] = flash_value
|
592
|
+
else
|
593
|
+
@request.session.delete("flash")
|
594
|
+
end
|
595
|
+
|
596
|
+
if xhr
|
597
|
+
@request.delete_header "HTTP_X_REQUESTED_WITH"
|
598
|
+
@request.delete_header "HTTP_ACCEPT"
|
599
|
+
end
|
600
|
+
@request.query_string = ""
|
601
|
+
|
602
|
+
@response.sent!
|
603
|
+
end
|
604
|
+
|
605
|
+
@response
|
606
|
+
end
|
607
|
+
|
601
608
|
def scrub_env!(env)
|
602
|
-
env.delete_if
|
603
|
-
|
604
|
-
|
605
|
-
env.delete "action_dispatch.request.request_parameters"
|
609
|
+
env.delete_if do |k, _|
|
610
|
+
k.start_with?("rack.request", "action_dispatch.request", "action_dispatch.rescue")
|
611
|
+
end
|
606
612
|
env["rack.input"] = StringIO.new
|
607
613
|
env.delete "CONTENT_LENGTH"
|
608
614
|
env.delete "RAW_POST_DATA"
|
data/lib/action_dispatch.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (c) 2004-
|
4
|
+
# Copyright (c) 2004-2020 David Heinemeier Hansson
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
7
7
|
# a copy of this software and associated documentation files (the
|
@@ -46,6 +46,7 @@ module ActionDispatch
|
|
46
46
|
eager_autoload do
|
47
47
|
autoload_under "http" do
|
48
48
|
autoload :ContentSecurityPolicy
|
49
|
+
autoload :PermissionsPolicy
|
49
50
|
autoload :Request
|
50
51
|
autoload :Response
|
51
52
|
end
|
@@ -82,7 +83,6 @@ module ActionDispatch
|
|
82
83
|
autoload :Headers
|
83
84
|
autoload :MimeNegotiation
|
84
85
|
autoload :Parameters
|
85
|
-
autoload :ParameterFilter
|
86
86
|
autoload :UploadedFile, "action_dispatch/http/upload"
|
87
87
|
autoload :URL
|
88
88
|
end
|
@@ -115,4 +115,5 @@ autoload :Mime, "action_dispatch/http/mime_type"
|
|
115
115
|
ActiveSupport.on_load(:action_view) do
|
116
116
|
ActionView::Base.default_formats ||= Mime::SET.symbols
|
117
117
|
ActionView::Template::Types.delegate_to Mime
|
118
|
+
ActionView::LookupContext::DetailsKey.clear
|
118
119
|
end
|
@@ -114,7 +114,7 @@ module ActionDispatch
|
|
114
114
|
|
115
115
|
# True if an ETag is set and it's a weak validator (preceded with W/)
|
116
116
|
def weak_etag?
|
117
|
-
etag? && etag.
|
117
|
+
etag? && etag.start_with?('W/"')
|
118
118
|
end
|
119
119
|
|
120
120
|
# True if an ETag is set and it isn't a weak validator (not preceded with W/)
|
@@ -125,7 +125,7 @@ module ActionDispatch
|
|
125
125
|
private
|
126
126
|
DATE = "Date"
|
127
127
|
LAST_MODIFIED = "Last-Modified"
|
128
|
-
SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate])
|
128
|
+
SPECIAL_KEYS = Set.new(%w[extras no-store no-cache max-age public private must-revalidate])
|
129
129
|
|
130
130
|
def generate_weak_etag(validators)
|
131
131
|
"W/#{generate_strong_etag(validators)}"
|
@@ -150,8 +150,8 @@ module ActionDispatch
|
|
150
150
|
directive, argument = segment.split("=", 2)
|
151
151
|
|
152
152
|
if SPECIAL_KEYS.include? directive
|
153
|
-
|
154
|
-
cache_control[
|
153
|
+
directive.tr!("-", "_")
|
154
|
+
cache_control[directive.to_sym] = argument || true
|
155
155
|
else
|
156
156
|
cache_control[:extras] ||= []
|
157
157
|
cache_control[:extras] << segment
|
@@ -166,6 +166,7 @@ module ActionDispatch
|
|
166
166
|
end
|
167
167
|
|
168
168
|
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
|
169
|
+
NO_STORE = "no-store"
|
169
170
|
NO_CACHE = "no-cache"
|
170
171
|
PUBLIC = "public"
|
171
172
|
PRIVATE = "private"
|
@@ -182,19 +183,20 @@ module ActionDispatch
|
|
182
183
|
end
|
183
184
|
|
184
185
|
def merge_and_normalize_cache_control!(cache_control)
|
185
|
-
control =
|
186
|
-
|
187
|
-
if
|
186
|
+
control = cache_control_headers
|
187
|
+
|
188
|
+
return if control.empty? && cache_control.empty? # Let middleware handle default behavior
|
189
|
+
|
190
|
+
if extras = control.delete(:extras)
|
188
191
|
cache_control[:extras] ||= []
|
189
192
|
cache_control[:extras] += extras
|
190
193
|
cache_control[:extras].uniq!
|
191
194
|
end
|
192
195
|
|
193
|
-
control.merge! cc_headers
|
194
196
|
control.merge! cache_control
|
195
197
|
|
196
|
-
if control
|
197
|
-
|
198
|
+
if control[:no_store]
|
199
|
+
self._cache_control = NO_STORE
|
198
200
|
elsif control[:no_cache]
|
199
201
|
options = []
|
200
202
|
options << PUBLIC if control[:public]
|
@@ -14,13 +14,13 @@ module ActionDispatch
|
|
14
14
|
@filename = filename
|
15
15
|
end
|
16
16
|
|
17
|
-
TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9
|
17
|
+
TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!\#$+.^_`|~-]/
|
18
18
|
|
19
19
|
def ascii_filename
|
20
20
|
'filename="' + percent_escape(I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
|
21
21
|
end
|
22
22
|
|
23
|
-
RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9
|
23
|
+
RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!\#$&+.^_`|~-]/
|
24
24
|
|
25
25
|
def utf8_filename
|
26
26
|
"filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR)
|
@@ -33,7 +33,7 @@ module ActionDispatch #:nodoc:
|
|
33
33
|
private
|
34
34
|
def html_response?(headers)
|
35
35
|
if content_type = headers[CONTENT_TYPE]
|
36
|
-
|
36
|
+
/html/.match?(content_type)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -137,7 +137,11 @@ module ActionDispatch #:nodoc:
|
|
137
137
|
object_src: "object-src",
|
138
138
|
prefetch_src: "prefetch-src",
|
139
139
|
script_src: "script-src",
|
140
|
+
script_src_attr: "script-src-attr",
|
141
|
+
script_src_elem: "script-src-elem",
|
140
142
|
style_src: "style-src",
|
143
|
+
style_src_attr: "style-src-attr",
|
144
|
+
style_src_elem: "style-src-elem",
|
141
145
|
worker_src: "worker-src"
|
142
146
|
}.freeze
|
143
147
|
|
@@ -23,7 +23,7 @@ module ActionDispatch
|
|
23
23
|
# change { file: { code: "xxxx"} }
|
24
24
|
#
|
25
25
|
# env["action_dispatch.parameter_filter"] = -> (k, v) do
|
26
|
-
# v.reverse! if k
|
26
|
+
# v.reverse! if k.match?(/secret/i)
|
27
27
|
# end
|
28
28
|
# => reverses the value to all keys matching /secret/i
|
29
29
|
module FilterParameters
|
@@ -121,8 +121,9 @@ module ActionDispatch
|
|
121
121
|
def env_name(key)
|
122
122
|
key = key.to_s
|
123
123
|
if HTTP_HEADER.match?(key)
|
124
|
-
key = key.upcase
|
125
|
-
key
|
124
|
+
key = key.upcase
|
125
|
+
key.tr!("-", "_")
|
126
|
+
key.prepend("HTTP_") unless CGI_VARIABLES.include?(key)
|
126
127
|
end
|
127
128
|
key
|
128
129
|
end
|
@@ -7,6 +7,8 @@ module ActionDispatch
|
|
7
7
|
module MimeNegotiation
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
|
+
class InvalidType < ::Mime::Type::InvalidMimeType; end
|
11
|
+
|
10
12
|
RESCUABLE_MIME_FORMAT_ERRORS = [
|
11
13
|
ActionController::BadRequest,
|
12
14
|
ActionDispatch::Http::Parameters::ParseError,
|
@@ -25,6 +27,8 @@ module ActionDispatch
|
|
25
27
|
nil
|
26
28
|
end
|
27
29
|
set_header k, v
|
30
|
+
rescue ::Mime::Type::InvalidMimeType => e
|
31
|
+
raise InvalidType, e.message
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
@@ -47,6 +51,8 @@ module ActionDispatch
|
|
47
51
|
Mime::Type.parse(header)
|
48
52
|
end
|
49
53
|
set_header k, v
|
54
|
+
rescue ::Mime::Type::InvalidMimeType => e
|
55
|
+
raise InvalidType, e.message
|
50
56
|
end
|
51
57
|
end
|
52
58
|
|
@@ -62,13 +68,7 @@ module ActionDispatch
|
|
62
68
|
|
63
69
|
def formats
|
64
70
|
fetch_header("action_dispatch.request.formats") do |k|
|
65
|
-
|
66
|
-
parameters[:format]
|
67
|
-
rescue *RESCUABLE_MIME_FORMAT_ERRORS
|
68
|
-
false
|
69
|
-
end
|
70
|
-
|
71
|
-
v = if params_readable
|
71
|
+
v = if params_readable?
|
72
72
|
Array(Mime[parameters[:format]])
|
73
73
|
elsif use_accept_header && valid_accept_header
|
74
74
|
accepts
|
@@ -153,12 +153,24 @@ module ActionDispatch
|
|
153
153
|
order.include?(Mime::ALL) ? format : nil
|
154
154
|
end
|
155
155
|
|
156
|
+
def should_apply_vary_header?
|
157
|
+
!params_readable? && use_accept_header && valid_accept_header
|
158
|
+
end
|
159
|
+
|
156
160
|
private
|
161
|
+
# We use normal content negotiation unless you include */* in your list,
|
162
|
+
# in which case we assume you're a browser and send HTML.
|
157
163
|
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
|
158
164
|
|
165
|
+
def params_readable? # :doc:
|
166
|
+
parameters[:format]
|
167
|
+
rescue *RESCUABLE_MIME_FORMAT_ERRORS
|
168
|
+
false
|
169
|
+
end
|
170
|
+
|
159
171
|
def valid_accept_header # :doc:
|
160
172
|
(xhr? && (accept.present? || content_mime_type)) ||
|
161
|
-
(accept.present? && accept
|
173
|
+
(accept.present? && !accept.match?(BROWSER_LIKE_ACCEPTS))
|
162
174
|
end
|
163
175
|
|
164
176
|
def use_accept_header # :doc:
|
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "singleton"
|
4
|
-
require "active_support/core_ext/
|
4
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
5
5
|
|
6
6
|
module Mime
|
7
7
|
class Mimes
|
8
|
+
attr_reader :symbols
|
9
|
+
|
8
10
|
include Enumerable
|
9
11
|
|
10
12
|
def initialize
|
11
13
|
@mimes = []
|
12
|
-
@symbols =
|
14
|
+
@symbols = []
|
13
15
|
end
|
14
16
|
|
15
17
|
def each
|
@@ -18,15 +20,16 @@ module Mime
|
|
18
20
|
|
19
21
|
def <<(type)
|
20
22
|
@mimes << type
|
21
|
-
@symbols
|
23
|
+
@symbols << type.to_sym
|
22
24
|
end
|
23
25
|
|
24
26
|
def delete_if
|
25
|
-
@mimes.delete_if
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
@mimes.delete_if do |x|
|
28
|
+
if yield x
|
29
|
+
@symbols.delete(x.to_sym)
|
30
|
+
true
|
31
|
+
end
|
32
|
+
end
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
@@ -114,7 +117,7 @@ module Mime
|
|
114
117
|
type = list[idx]
|
115
118
|
break if type.q < app_xml.q
|
116
119
|
|
117
|
-
if type.name.
|
120
|
+
if type.name.end_with? "+xml"
|
118
121
|
list[app_xml_idx], list[idx] = list[idx], app_xml
|
119
122
|
app_xml_idx = idx
|
120
123
|
end
|
@@ -202,7 +205,7 @@ module Mime
|
|
202
205
|
# For an input of <tt>'application'</tt>, returns <tt>[Mime[:html], Mime[:js],
|
203
206
|
# Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]</tt>.
|
204
207
|
def parse_data_with_trailing_star(type)
|
205
|
-
Mime::SET.select { |m| m
|
208
|
+
Mime::SET.select { |m| m.match?(type) }
|
206
209
|
end
|
207
210
|
|
208
211
|
# This method is opposite of register method.
|
@@ -283,8 +286,14 @@ module Mime
|
|
283
286
|
@synonyms.any? { |synonym| synonym.to_s =~ regexp } || @string =~ regexp
|
284
287
|
end
|
285
288
|
|
289
|
+
def match?(mime_type)
|
290
|
+
return false unless mime_type
|
291
|
+
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
|
292
|
+
@synonyms.any? { |synonym| synonym.to_s.match?(regexp) } || @string.match?(regexp)
|
293
|
+
end
|
294
|
+
|
286
295
|
def html?
|
287
|
-
symbol == :html || @string
|
296
|
+
(symbol == :html) || /html/.match?(@string)
|
288
297
|
end
|
289
298
|
|
290
299
|
def all?; false; end
|
@@ -297,7 +306,7 @@ module Mime
|
|
297
306
|
def to_a; end
|
298
307
|
|
299
308
|
def method_missing(method, *args)
|
300
|
-
if method.
|
309
|
+
if method.end_with?("?")
|
301
310
|
method[0..-2].downcase.to_sym == to_sym
|
302
311
|
else
|
303
312
|
super
|
@@ -305,7 +314,7 @@ module Mime
|
|
305
314
|
end
|
306
315
|
|
307
316
|
def respond_to_missing?(method, include_private = false)
|
308
|
-
|
317
|
+
method.end_with?("?") || super
|
309
318
|
end
|
310
319
|
end
|
311
320
|
|
@@ -332,15 +341,19 @@ module Mime
|
|
332
341
|
true
|
333
342
|
end
|
334
343
|
|
344
|
+
def to_s
|
345
|
+
""
|
346
|
+
end
|
347
|
+
|
335
348
|
def ref; end
|
336
349
|
|
337
350
|
private
|
338
351
|
def respond_to_missing?(method, _)
|
339
|
-
method.
|
352
|
+
method.end_with?("?")
|
340
353
|
end
|
341
354
|
|
342
355
|
def method_missing(method, *args)
|
343
|
-
false if method.
|
356
|
+
false if method.end_with?("?")
|
344
357
|
end
|
345
358
|
end
|
346
359
|
end
|