actionpack 5.2.4.4 → 6.1.1
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 +264 -322
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/base.rb +38 -4
- data/lib/abstract_controller/caching.rb +1 -1
- data/lib/abstract_controller/caching/fragments.rb +6 -22
- data/lib/abstract_controller/callbacks.rb +14 -2
- data/lib/abstract_controller/collector.rb +1 -2
- data/lib/abstract_controller/helpers.rb +106 -90
- data/lib/abstract_controller/railties/routes_helpers.rb +1 -1
- data/lib/abstract_controller/rendering.rb +9 -9
- data/lib/abstract_controller/translation.rb +11 -5
- data/lib/action_controller.rb +7 -4
- data/lib/action_controller/api.rb +4 -3
- data/lib/action_controller/base.rb +6 -9
- data/lib/action_controller/caching.rb +1 -3
- data/lib/action_controller/log_subscriber.rb +10 -7
- data/lib/action_controller/metal.rb +10 -8
- data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
- data/lib/action_controller/metal/conditional_get.rb +19 -5
- data/lib/action_controller/metal/content_security_policy.rb +1 -2
- data/lib/action_controller/metal/cookies.rb +3 -1
- data/lib/action_controller/metal/data_streaming.rb +6 -7
- data/lib/action_controller/metal/default_headers.rb +17 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +3 -5
- data/lib/action_controller/metal/exceptions.rb +56 -2
- data/lib/action_controller/metal/flash.rb +5 -5
- data/lib/action_controller/metal/head.rb +7 -4
- data/lib/action_controller/metal/helpers.rb +14 -5
- data/lib/action_controller/metal/http_authentication.rb +24 -23
- data/lib/action_controller/metal/implicit_render.rb +5 -15
- data/lib/action_controller/metal/instrumentation.rb +13 -14
- data/lib/action_controller/metal/live.rb +30 -32
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +19 -4
- data/lib/action_controller/metal/parameter_encoding.rb +35 -4
- data/lib/action_controller/metal/params_wrapper.rb +31 -22
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +6 -6
- data/lib/action_controller/metal/renderers.rb +4 -4
- data/lib/action_controller/metal/rendering.rb +8 -3
- data/lib/action_controller/metal/request_forgery_protection.rb +62 -34
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/streaming.rb +0 -1
- data/lib/action_controller/metal/strong_parameters.rb +167 -58
- data/lib/action_controller/metal/url_for.rb +1 -1
- data/lib/action_controller/railties/helpers.rb +1 -1
- data/lib/action_controller/renderer.rb +37 -13
- data/lib/action_controller/template_assertions.rb +1 -1
- data/lib/action_controller/test_case.rb +70 -65
- data/lib/action_dispatch.rb +9 -3
- data/lib/action_dispatch/http/cache.rb +26 -21
- data/lib/action_dispatch/http/content_disposition.rb +45 -0
- data/lib/action_dispatch/http/content_security_policy.rb +33 -19
- data/lib/action_dispatch/http/filter_parameters.rb +9 -8
- data/lib/action_dispatch/http/filter_redirect.rb +2 -3
- data/lib/action_dispatch/http/headers.rb +4 -4
- data/lib/action_dispatch/http/mime_negotiation.rb +26 -13
- data/lib/action_dispatch/http/mime_type.rb +42 -23
- data/lib/action_dispatch/http/parameters.rb +14 -23
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/request.rb +45 -22
- data/lib/action_dispatch/http/response.rb +45 -25
- data/lib/action_dispatch/http/upload.rb +9 -1
- data/lib/action_dispatch/http/url.rb +82 -82
- data/lib/action_dispatch/journey.rb +0 -2
- data/lib/action_dispatch/journey/formatter.rb +54 -30
- data/lib/action_dispatch/journey/gtg/builder.rb +22 -37
- data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -5
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
- data/lib/action_dispatch/journey/nodes/node.rb +13 -11
- 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 +19 -21
- data/lib/action_dispatch/journey/route.rb +10 -20
- data/lib/action_dispatch/journey/router.rb +26 -34
- data/lib/action_dispatch/journey/router/utils.rb +14 -12
- data/lib/action_dispatch/journey/routes.rb +0 -2
- data/lib/action_dispatch/journey/scanner.rb +10 -4
- data/lib/action_dispatch/journey/visitors.rb +1 -4
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -4
- data/lib/action_dispatch/middleware/cookies.rb +128 -109
- data/lib/action_dispatch/middleware/debug_exceptions.rb +43 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
- data/lib/action_dispatch/middleware/debug_view.rb +66 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -30
- data/lib/action_dispatch/middleware/flash.rb +1 -1
- data/lib/action_dispatch/middleware/host_authorization.rb +121 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +14 -16
- data/lib/action_dispatch/middleware/request_id.rb +5 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +3 -9
- data/lib/action_dispatch/middleware/show_exceptions.rb +3 -2
- data/lib/action_dispatch/middleware/ssl.rb +20 -15
- data/lib/action_dispatch/middleware/stack.rb +56 -2
- data/lib/action_dispatch/middleware/static.rb +153 -93
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +6 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +104 -8
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +24 -1
- data/lib/action_dispatch/railtie.rb +8 -2
- data/lib/action_dispatch/request/session.rb +10 -9
- data/lib/action_dispatch/request/utils.rb +26 -2
- data/lib/action_dispatch/routing.rb +21 -20
- data/lib/action_dispatch/routing/inspector.rb +100 -52
- data/lib/action_dispatch/routing/mapper.rb +155 -103
- data/lib/action_dispatch/routing/polymorphic_routes.rb +13 -15
- data/lib/action_dispatch/routing/redirection.rb +3 -3
- data/lib/action_dispatch/routing/route_set.rb +71 -69
- data/lib/action_dispatch/routing/url_for.rb +2 -2
- data/lib/action_dispatch/system_test_case.rb +54 -11
- data/lib/action_dispatch/system_testing/browser.rb +53 -16
- data/lib/action_dispatch/system_testing/driver.rb +11 -3
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +49 -7
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -10
- data/lib/action_dispatch/testing/assertion_response.rb +0 -1
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +4 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +20 -8
- data/lib/action_dispatch/testing/integration.rb +61 -28
- data/lib/action_dispatch/testing/request_encoder.rb +2 -2
- data/lib/action_dispatch/testing/test_process.rb +29 -4
- data/lib/action_dispatch/testing/test_request.rb +3 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -32
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/gem_version.rb +4 -4
- metadata +38 -26
- data/lib/action_controller/metal/force_ssl.rb +0 -99
- data/lib/action_dispatch/http/parameter_filter.rb +0 -86
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -49
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -120
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/hash/keys"
|
4
|
-
|
5
3
|
module ActionController
|
6
4
|
# ActionController::Renderer allows you to render arbitrary templates
|
7
5
|
# without requirement of being in controller actions.
|
@@ -67,10 +65,29 @@ module ActionController
|
|
67
65
|
def initialize(controller, env, defaults)
|
68
66
|
@controller = controller
|
69
67
|
@defaults = defaults
|
70
|
-
@env = normalize_keys defaults
|
68
|
+
@env = normalize_keys defaults, env
|
71
69
|
end
|
72
70
|
|
73
71
|
# Render templates with any options from ActionController::Base#render_to_string.
|
72
|
+
#
|
73
|
+
# The primary options are:
|
74
|
+
# * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt> for details.
|
75
|
+
# * <tt>:file</tt> - Renders an explicit template file. Add <tt>:locals</tt> to pass in, if so desired.
|
76
|
+
# It shouldn’t be used directly with unsanitized user input due to lack of validation.
|
77
|
+
# * <tt>:inline</tt> - Renders an ERB template string.
|
78
|
+
# * <tt>:plain</tt> - Renders provided text and sets the content type as <tt>text/plain</tt>.
|
79
|
+
# * <tt>:html</tt> - Renders the provided HTML safe string, otherwise
|
80
|
+
# performs HTML escape on the string first. Sets the content type as <tt>text/html</tt>.
|
81
|
+
# * <tt>:json</tt> - Renders the provided hash or object in JSON. You don't
|
82
|
+
# need to call <tt>.to_json</tt> on the object you want to render.
|
83
|
+
# * <tt>:body</tt> - Renders provided text and sets content type of <tt>text/plain</tt>.
|
84
|
+
#
|
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.
|
74
91
|
def render(*args)
|
75
92
|
raise "missing controller" unless controller
|
76
93
|
|
@@ -82,11 +99,18 @@ module ActionController
|
|
82
99
|
instance.set_response! controller.make_response!(request)
|
83
100
|
instance.render_to_string(*args)
|
84
101
|
end
|
102
|
+
alias_method :render_to_string, :render # :nodoc:
|
85
103
|
|
86
104
|
private
|
87
|
-
def normalize_keys(env)
|
105
|
+
def normalize_keys(defaults, env)
|
88
106
|
new_env = {}
|
89
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
|
+
|
90
114
|
new_env["rack.url_scheme"] = new_env["HTTPS"] == "on" ? "https" : "http"
|
91
115
|
new_env
|
92
116
|
end
|
@@ -99,19 +123,19 @@ module ActionController
|
|
99
123
|
input: "rack.input"
|
100
124
|
}
|
101
125
|
|
102
|
-
IDENTITY = ->(_) { _ }
|
103
|
-
|
104
|
-
RACK_VALUE_TRANSLATION = {
|
105
|
-
https: ->(v) { v ? "on" : "off" },
|
106
|
-
method: ->(v) { v.upcase },
|
107
|
-
}
|
108
|
-
|
109
126
|
def rack_key_for(key)
|
110
|
-
RACK_KEY_TRANSLATION
|
127
|
+
RACK_KEY_TRANSLATION[key] || key.to_s
|
111
128
|
end
|
112
129
|
|
113
130
|
def rack_value_for(key, value)
|
114
|
-
|
131
|
+
case key
|
132
|
+
when :https
|
133
|
+
value ? "on" : "off"
|
134
|
+
when :method
|
135
|
+
-value.upcase
|
136
|
+
else
|
137
|
+
value
|
138
|
+
end
|
115
139
|
end
|
116
140
|
end
|
117
141
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionController
|
4
|
-
module TemplateAssertions
|
4
|
+
module TemplateAssertions # :nodoc:
|
5
5
|
def assert_template(options = {}, message = nil)
|
6
6
|
raise NoMethodError,
|
7
7
|
"assert_template has been extracted to a gem. To continue using it,
|
@@ -26,7 +26,7 @@ module ActionController
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
# ActionController::TestCase will be deprecated and moved to a gem in
|
29
|
+
# ActionController::TestCase will be deprecated and moved to a gem in the future.
|
30
30
|
# Please use ActionDispatch::IntegrationTest going forward.
|
31
31
|
class TestRequest < ActionDispatch::TestRequest #:nodoc:
|
32
32
|
DEFAULT_ENV = ActionDispatch::TestRequest::DEFAULT_ENV.dup
|
@@ -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
|
|
@@ -158,7 +158,6 @@ module ActionController
|
|
158
158
|
end.new
|
159
159
|
|
160
160
|
private
|
161
|
-
|
162
161
|
def params_parsers
|
163
162
|
super.merge @custom_param_parsers
|
164
163
|
end
|
@@ -177,12 +176,12 @@ module ActionController
|
|
177
176
|
|
178
177
|
# Methods #destroy and #load! are overridden to avoid calling methods on the
|
179
178
|
# @store object, which does not exist for the TestSession class.
|
180
|
-
class TestSession < Rack::Session::Abstract::
|
179
|
+
class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash #:nodoc:
|
181
180
|
DEFAULT_OPTIONS = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS
|
182
181
|
|
183
182
|
def initialize(session = {})
|
184
183
|
super(nil, nil)
|
185
|
-
@id = SecureRandom.hex(16)
|
184
|
+
@id = Rack::Session::SessionId.new(SecureRandom.hex(16))
|
186
185
|
@data = stringify_keys(session)
|
187
186
|
@loaded = true
|
188
187
|
end
|
@@ -203,12 +202,16 @@ module ActionController
|
|
203
202
|
clear
|
204
203
|
end
|
205
204
|
|
205
|
+
def dig(*keys)
|
206
|
+
keys = keys.map.with_index { |key, i| i.zero? ? key.to_s : key }
|
207
|
+
@data.dig(*keys)
|
208
|
+
end
|
209
|
+
|
206
210
|
def fetch(key, *args, &block)
|
207
211
|
@data.fetch(key.to_s, *args, &block)
|
208
212
|
end
|
209
213
|
|
210
214
|
private
|
211
|
-
|
212
215
|
def load!
|
213
216
|
@id
|
214
217
|
end
|
@@ -276,9 +279,6 @@ module ActionController
|
|
276
279
|
# after calling +post+. If the various assert methods are not sufficient, then you
|
277
280
|
# may use this object to inspect the HTTP response in detail.
|
278
281
|
#
|
279
|
-
# (Earlier versions of \Rails required each functional test to subclass
|
280
|
-
# Test::Unit::TestCase and define @controller, @request, @response in +setup+.)
|
281
|
-
#
|
282
282
|
# == Controller is automatically inferred
|
283
283
|
#
|
284
284
|
# ActionController::TestCase will automatically infer the controller under test
|
@@ -460,7 +460,7 @@ module ActionController
|
|
460
460
|
def process(action, method: "GET", params: nil, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil)
|
461
461
|
check_required_ivars
|
462
462
|
|
463
|
-
action = action.to_s
|
463
|
+
action = +action.to_s
|
464
464
|
http_method = method.to_s.upcase
|
465
465
|
|
466
466
|
@html_document = nil
|
@@ -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,12 +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
|
601
607
|
|
602
608
|
def scrub_env!(env)
|
603
|
-
env.delete_if
|
604
|
-
|
605
|
-
|
606
|
-
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
|
607
612
|
env["rack.input"] = StringIO.new
|
608
613
|
env.delete "CONTENT_LENGTH"
|
609
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
|
@@ -40,20 +40,27 @@ module ActionDispatch
|
|
40
40
|
class IllegalStateError < StandardError
|
41
41
|
end
|
42
42
|
|
43
|
+
class MissingController < NameError
|
44
|
+
end
|
45
|
+
|
43
46
|
eager_autoload do
|
44
47
|
autoload_under "http" do
|
45
48
|
autoload :ContentSecurityPolicy
|
49
|
+
autoload :PermissionsPolicy
|
46
50
|
autoload :Request
|
47
51
|
autoload :Response
|
48
52
|
end
|
49
53
|
end
|
50
54
|
|
51
55
|
autoload_under "middleware" do
|
56
|
+
autoload :HostAuthorization
|
52
57
|
autoload :RequestId
|
53
58
|
autoload :Callbacks
|
54
59
|
autoload :Cookies
|
60
|
+
autoload :ActionableExceptions
|
55
61
|
autoload :DebugExceptions
|
56
62
|
autoload :DebugLocks
|
63
|
+
autoload :DebugView
|
57
64
|
autoload :ExceptionWrapper
|
58
65
|
autoload :Executor
|
59
66
|
autoload :Flash
|
@@ -76,8 +83,6 @@ module ActionDispatch
|
|
76
83
|
autoload :Headers
|
77
84
|
autoload :MimeNegotiation
|
78
85
|
autoload :Parameters
|
79
|
-
autoload :ParameterFilter
|
80
|
-
autoload :Upload
|
81
86
|
autoload :UploadedFile, "action_dispatch/http/upload"
|
82
87
|
autoload :URL
|
83
88
|
end
|
@@ -110,4 +115,5 @@ autoload :Mime, "action_dispatch/http/mime_type"
|
|
110
115
|
ActiveSupport.on_load(:action_view) do
|
111
116
|
ActionView::Base.default_formats ||= Mime::SET.symbols
|
112
117
|
ActionView::Template::Types.delegate_to Mime
|
118
|
+
ActionView::LookupContext::DetailsKey.clear
|
113
119
|
end
|
@@ -4,8 +4,8 @@ module ActionDispatch
|
|
4
4
|
module Http
|
5
5
|
module Cache
|
6
6
|
module Request
|
7
|
-
HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE"
|
8
|
-
HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH"
|
7
|
+
HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE"
|
8
|
+
HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH"
|
9
9
|
|
10
10
|
def if_modified_since
|
11
11
|
if since = get_header(HTTP_IF_MODIFIED_SINCE)
|
@@ -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/)
|
@@ -123,10 +123,9 @@ module ActionDispatch
|
|
123
123
|
end
|
124
124
|
|
125
125
|
private
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public private must-revalidate])
|
126
|
+
DATE = "Date"
|
127
|
+
LAST_MODIFIED = "Last-Modified"
|
128
|
+
SPECIAL_KEYS = Set.new(%w[extras no-store no-cache max-age public private must-revalidate])
|
130
129
|
|
131
130
|
def generate_weak_etag(validators)
|
132
131
|
"W/#{generate_strong_etag(validators)}"
|
@@ -151,8 +150,8 @@ module ActionDispatch
|
|
151
150
|
directive, argument = segment.split("=", 2)
|
152
151
|
|
153
152
|
if SPECIAL_KEYS.include? directive
|
154
|
-
|
155
|
-
cache_control[
|
153
|
+
directive.tr!("-", "_")
|
154
|
+
cache_control[directive.to_sym] = argument || true
|
156
155
|
else
|
157
156
|
cache_control[:extras] ||= []
|
158
157
|
cache_control[:extras] << segment
|
@@ -166,11 +165,12 @@ module ActionDispatch
|
|
166
165
|
@cache_control = cache_control_headers
|
167
166
|
end
|
168
167
|
|
169
|
-
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
168
|
+
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
|
169
|
+
NO_STORE = "no-store"
|
170
|
+
NO_CACHE = "no-cache"
|
171
|
+
PUBLIC = "public"
|
172
|
+
PRIVATE = "private"
|
173
|
+
MUST_REVALIDATE = "must-revalidate"
|
174
174
|
|
175
175
|
def handle_conditional_get!
|
176
176
|
# Normally default cache control setting is handled by ETag
|
@@ -183,19 +183,20 @@ module ActionDispatch
|
|
183
183
|
end
|
184
184
|
|
185
185
|
def merge_and_normalize_cache_control!(cache_control)
|
186
|
-
control =
|
187
|
-
|
188
|
-
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)
|
189
191
|
cache_control[:extras] ||= []
|
190
192
|
cache_control[:extras] += extras
|
191
193
|
cache_control[:extras].uniq!
|
192
194
|
end
|
193
195
|
|
194
|
-
control.merge! cc_headers
|
195
196
|
control.merge! cache_control
|
196
197
|
|
197
|
-
if control
|
198
|
-
|
198
|
+
if control[:no_store]
|
199
|
+
self._cache_control = NO_STORE
|
199
200
|
elsif control[:no_cache]
|
200
201
|
options = []
|
201
202
|
options << PUBLIC if control[:public]
|
@@ -204,13 +205,17 @@ module ActionDispatch
|
|
204
205
|
|
205
206
|
self._cache_control = options.join(", ")
|
206
207
|
else
|
207
|
-
extras
|
208
|
+
extras = control[:extras]
|
208
209
|
max_age = control[:max_age]
|
210
|
+
stale_while_revalidate = control[:stale_while_revalidate]
|
211
|
+
stale_if_error = control[:stale_if_error]
|
209
212
|
|
210
213
|
options = []
|
211
214
|
options << "max-age=#{max_age.to_i}" if max_age
|
212
215
|
options << (control[:public] ? PUBLIC : PRIVATE)
|
213
216
|
options << MUST_REVALIDATE if control[:must_revalidate]
|
217
|
+
options << "stale-while-revalidate=#{stale_while_revalidate.to_i}" if stale_while_revalidate
|
218
|
+
options << "stale-if-error=#{stale_if_error.to_i}" if stale_if_error
|
214
219
|
options.concat(extras) if extras
|
215
220
|
|
216
221
|
self._cache_control = options.join(", ")
|