1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

use built-in exception handling in live controllers

when an exception happens in an action before the response has been
committed, then we should re-raise the exception in the main thread.
This lets us reuse the existing exception handling.
This commit is contained in:
Aaron Patterson 2014-02-28 15:39:08 -08:00
parent 30d21dfcb7
commit a7b059ec7f
2 changed files with 22 additions and 17 deletions

View file

@ -203,6 +203,7 @@ module ActionController
t1 = Thread.current
locals = t1.keys.map { |key| [key, t1[key]] }
error = nil
# This processes the action in a child thread. It lets us return the
# response code and headers back up the rack stack, and still process
# the body in parallel with sending data to the client
@ -217,8 +218,9 @@ module ActionController
begin
super(name)
rescue => e
@_response.status = 500 unless @_response.committed?
@_response.status = 400 if e.class == ActionController::BadRequest
unless @_response.committed?
error = e
end
begin
@_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html
@_response.stream.call_on_error
@ -234,6 +236,7 @@ module ActionController
}
@_response.await_commit
raise error if error
end
def log_error(exception)

View file

@ -90,6 +90,9 @@ module ActionController
end
class LiveStreamTest < ActionController::TestCase
class Exception < StandardError
end
class TestController < ActionController::Base
include ActionController::Live
@ -152,11 +155,12 @@ module ActionController
response.stream.close
end
response.stream.write "" # make sure the response is committed
raise 'An exception occurred...'
end
def exception_in_controller
raise 'Exception in controller'
raise Exception, 'Exception in controller'
end
def bad_request_error
@ -168,6 +172,7 @@ module ActionController
response.stream.on_error do
raise 'We need to go deeper.'
end
response.stream.write ''
response.stream.write params[:widget][:didnt_check_for_nil]
end
end
@ -246,24 +251,19 @@ module ActionController
end
def test_exception_handling_html
capture_log_output do |output|
assert_raises(ActionView::MissingTemplate) do
get :exception_in_view
assert_match %r((window\.location = "/500\.html"</script></html>)$), response.body
assert_match 'Missing template test/doesntexist', output.rewind && output.read
assert_stream_closed
end
assert_stream_closed
end
def test_exception_handling_plain_text
capture_log_output do |output|
assert_raises(ActionView::MissingTemplate) do
get :exception_in_view, format: :json
assert_equal '', response.body
assert_match 'Missing template test/doesntexist', output.rewind && output.read
assert_stream_closed
end
end
def test_exception_callback
def test_exception_callback_when_committed
capture_log_output do |output|
get :exception_with_callback, format: 'text/event-stream'
assert_equal %(data: "500 Internal Server Error"\n\n), response.body
@ -273,16 +273,18 @@ module ActionController
end
def test_exception_in_controller_before_streaming
response = get :exception_in_controller, format: 'text/event-stream'
assert_equal 500, response.status
assert_raises(ActionController::LiveStreamTest::Exception) do
get :exception_in_controller, format: 'text/event-stream'
end
end
def test_bad_request_in_controller_before_streaming
response = get :bad_request_error, format: 'text/event-stream'
assert_equal 400, response.status
assert_raises(ActionController::BadRequest) do
get :bad_request_error, format: 'text/event-stream'
end
end
def test_exceptions_raised_handling_exceptions
def test_exceptions_raised_handling_exceptions_and_committed
capture_log_output do |output|
get :exception_in_exception_callback, format: 'text/event-stream'
assert_equal '', response.body