Skip to content

Commit 61accb7

Browse files
authored
Merge pull request rails#45867 from jdufresne/show-rescuable-exceptions
Make the test environment show rescuable exceptions in responses
2 parents a19b13b + 5e34a92 commit 61accb7

File tree

27 files changed

+245
-121
lines changed

27 files changed

+245
-121
lines changed

actionmailbox/test/dummy/config/environments/test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
config.cache_store = :null_store
3030

3131
# Raise exceptions instead of rendering exception templates.
32-
config.action_dispatch.show_exceptions = false
32+
config.action_dispatch.show_exceptions = :rescuable
3333

3434
# Disable request forgery protection in test environment.
3535
config.action_controller.allow_forgery_protection = false

actionpack/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
* Change `action_dispatch.show_exceptions` to one of `:all`, `:rescuable`, or
2+
`:none`. `:all` and `:none` behave the same as the previous `true` and
3+
`false` respectively. The new `:rescuable` option will only show exceptions
4+
that can be rescued (e.g. `ActiveRecord::RecordNotFound`). `:rescuable` is
5+
now the default for the test environment.
6+
7+
*Jon Dufresne*
8+
19
* `config.action_dispatch.cookies_serializer` now accepts `:message_pack` and
210
`:message_pack_allow_marshal` as serializers. These serializers require the
311
[`msgpack` gem](https://rubygems.org/gems/msgpack) (>= 1.7.0).

actionpack/lib/action_dispatch/http/request.rb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,6 @@ def http_auth_salt
191191
get_header "action_dispatch.http_auth_salt"
192192
end
193193

194-
def show_exceptions? # :nodoc:
195-
# We're treating `nil` as "unset", and we want the default setting to be
196-
# `true`. This logic should be extracted to `env_config` and calculated
197-
# once.
198-
!(get_header("action_dispatch.show_exceptions") == false)
199-
end
200-
201194
# Returns a symbol form of the #request_method.
202195
def request_method_symbol
203196
HTTP_METHOD_LOOKUP[request_method]

actionpack/lib/action_dispatch/middleware/debug_exceptions.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def call(env)
4040
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
4141

4242
invoke_interceptors(request, exception, wrapper)
43-
raise exception unless request.show_exceptions?
43+
raise exception unless wrapper.show?(request)
4444
render_exception(request, exception, wrapper)
4545
end
4646

actionpack/lib/action_dispatch/middleware/exception_wrapper.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,29 @@ def self.status_code_for_exception(class_name)
174174
Rack::Utils.status_code(@@rescue_responses[class_name])
175175
end
176176

177+
def show?(request)
178+
# We're treating `nil` as "unset", and we want the default setting to be
179+
# `:all`. This logic should be extracted to `env_config` and calculated
180+
# once.
181+
config = request.get_header("action_dispatch.show_exceptions")
182+
183+
# Include true and false for backwards compatibility.
184+
case config
185+
when :none
186+
false
187+
when :rescuable
188+
rescue_response?
189+
when true
190+
ActionDispatch.deprecator.warn("Setting action_dispatch.show_exceptions to true is deprecated. Set to :all instead.")
191+
true
192+
when false
193+
ActionDispatch.deprecator.warn("Setting action_dispatch.show_exceptions to false is deprecated. Set to :none instead.")
194+
false
195+
else
196+
true
197+
end
198+
end
199+
177200
def rescue_response?
178201
@@rescue_responses.key?(exception.class.name)
179202
end

actionpack/lib/action_dispatch/middleware/show_exceptions.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ def call(env)
3131
@app.call(env)
3232
rescue Exception => exception
3333
request = ActionDispatch::Request.new env
34-
if request.show_exceptions?
35-
render_exception(request, exception)
34+
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
35+
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
36+
if wrapper.show?(request)
37+
render_exception(request, wrapper)
3638
else
3739
raise exception
3840
end
3941
end
4042

4143
private
42-
def render_exception(request, exception)
43-
backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
44-
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
45-
status = wrapper.status_code
44+
def render_exception(request, wrapper)
45+
status = wrapper.status_code
4646
request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
4747
request.set_header "action_dispatch.original_path", request.path_info
4848
request.set_header "action_dispatch.original_request_method", request.raw_request_method

actionpack/lib/action_dispatch/railtie.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Railtie < Rails::Railtie # :nodoc:
99
config.action_dispatch = ActiveSupport::OrderedOptions.new
1010
config.action_dispatch.x_sendfile_header = nil
1111
config.action_dispatch.ip_spoofing_check = true
12-
config.action_dispatch.show_exceptions = true
12+
config.action_dispatch.show_exceptions = :all
1313
config.action_dispatch.tld_length = 1
1414
config.action_dispatch.ignore_accept_header = false
1515
config.action_dispatch.rescue_templates = {}

actionpack/test/controller/new_base/render_action_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def setup
8989

9090
test "rendering with layout => true" do
9191
assert_raise(ArgumentError) do
92-
get "/render_action/basic/hello_world_with_layout", headers: { "action_dispatch.show_exceptions" => false }
92+
get "/render_action/basic/hello_world_with_layout", headers: { "action_dispatch.show_exceptions" => :none }
9393
end
9494
end
9595

@@ -109,7 +109,7 @@ def setup
109109

110110
test "rendering with layout => 'greetings'" do
111111
assert_raise(ActionView::MissingTemplate) do
112-
get "/render_action/basic/hello_world_with_custom_layout", headers: { "action_dispatch.show_exceptions" => false }
112+
get "/render_action/basic/hello_world_with_custom_layout", headers: { "action_dispatch.show_exceptions" => :none }
113113
end
114114
end
115115
end

actionpack/test/controller/new_base/render_test.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class RenderTest < Rack::TestCase
7979
end
8080

8181
assert_raises(AbstractController::DoubleRenderError) do
82-
get "/render/double_render", headers: { "action_dispatch.show_exceptions" => false }
82+
get "/render/double_render", headers: { "action_dispatch.show_exceptions" => :none }
8383
end
8484
end
8585
end
@@ -89,13 +89,13 @@ class TestOnlyRenderPublicActions < Rack::TestCase
8989
# Only public methods on actual controllers are callable actions
9090
test "raises an exception when a method of Object is called" do
9191
assert_raises(AbstractController::ActionNotFound) do
92-
get "/render/blank_render/clone", headers: { "action_dispatch.show_exceptions" => false }
92+
get "/render/blank_render/clone", headers: { "action_dispatch.show_exceptions" => :none }
9393
end
9494
end
9595

9696
test "raises an exception when a private method is called" do
9797
assert_raises(AbstractController::ActionNotFound) do
98-
get "/render/blank_render/secretz", headers: { "action_dispatch.show_exceptions" => false }
98+
get "/render/blank_render/secretz", headers: { "action_dispatch.show_exceptions" => :none }
9999
end
100100
end
101101
end

actionpack/test/dispatch/content_security_policy_test.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ def call(env)
331331
env["action_dispatch.content_security_policy"] = POLICY
332332
env["action_dispatch.content_security_policy_nonce_generator"] = proc { "iyhD0Yc0W+c=" }
333333
env["action_dispatch.content_security_policy_report_only"] = false
334-
env["action_dispatch.show_exceptions"] = false
334+
env["action_dispatch.show_exceptions"] = :none
335335

336336
@app.call(env)
337337
end
@@ -481,7 +481,7 @@ def call(env)
481481
env["action_dispatch.content_security_policy"] = POLICY
482482
env["action_dispatch.content_security_policy_nonce_generator"] = proc { "iyhD0Yc0W+c=" }
483483
env["action_dispatch.content_security_policy_report_only"] = false
484-
env["action_dispatch.show_exceptions"] = false
484+
env["action_dispatch.show_exceptions"] = :none
485485

486486
@app.call(env)
487487
end
@@ -597,7 +597,7 @@ def call(env)
597597
env["action_dispatch.content_security_policy"] = nil
598598
env["action_dispatch.content_security_policy_nonce_generator"] = nil
599599
env["action_dispatch.content_security_policy_report_only"] = false
600-
env["action_dispatch.show_exceptions"] = false
600+
env["action_dispatch.show_exceptions"] = :none
601601

602602
@app.call(env)
603603
end
@@ -653,7 +653,7 @@ def call(env)
653653
env["action_dispatch.content_security_policy_nonce_generator"] = proc { "iyhD0Yc0W+c=" }
654654
env["action_dispatch.content_security_policy_report_only"] = false
655655
env["action_dispatch.content_security_policy_nonce_directives"] = %w(script-src)
656-
env["action_dispatch.show_exceptions"] = false
656+
env["action_dispatch.show_exceptions"] = :none
657657

658658
@app.call(env)
659659
end
@@ -725,7 +725,7 @@ def call(env)
725725
env["action_dispatch.content_security_policy"] = POLICY
726726
env["action_dispatch.content_security_policy_nonce_generator"] = proc { "iyhD0Yc0W+c=" }
727727
env["action_dispatch.content_security_policy_report_only"] = false
728-
env["action_dispatch.show_exceptions"] = false
728+
env["action_dispatch.show_exceptions"] = :none
729729

730730
@app.call(env)
731731
end

0 commit comments

Comments
 (0)