Skip to content

Commit 30e54b8

Browse files
authored
Merge pull request rails#43104 from ghiculescu/http-406-crash
Fix crash in `ActionController::Instrumentation` with invalid HTTP formats
2 parents ce72a8a + 2a434d0 commit 30e54b8

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

actionpack/lib/action_dispatch/middleware/show_exceptions.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def render_exception(request, exception)
4040
request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
4141
request.set_header "action_dispatch.original_path", request.path_info
4242
request.set_header "action_dispatch.original_request_method", request.raw_request_method
43+
fallback_to_html_format_if_invalid_mime_type(request)
4344
request.path_info = "/#{status}"
4445
request.request_method = "GET"
4546
response = @exceptions_app.call(request.env)
@@ -54,6 +55,15 @@ def render_exception(request, exception)
5455
"went wrong."]]
5556
end
5657

58+
def fallback_to_html_format_if_invalid_mime_type(request)
59+
# If the MIME type for the request is invalid then the
60+
# @exceptions_app may not be able to handle it. To make it
61+
# easier to handle, we switch to HTML.
62+
request.formats
63+
rescue ActionDispatch::Http::MimeNegotiation::InvalidType
64+
request.set_header "HTTP_ACCEPT", "text/html"
65+
end
66+
5767
def pass_response(status)
5868
[status, { "Content-Type" => "text/html; charset=#{Response.default_charset}", "Content-Length" => "0" }, []]
5969
end

railties/test/application/middleware/exceptions_test.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,35 @@ def index
6565
assert_equal 405, last_response.status
6666
end
6767

68+
test "renders unknown http formats as 406 when routes are used as the custom exceptions app" do
69+
controller :foo, <<-RUBY
70+
class FooController < ActionController::Base
71+
def index
72+
render plain: "rendering index!"
73+
end
74+
75+
def not_acceptable
76+
render json: { error: "some error message" }, status: :not_acceptable
77+
end
78+
end
79+
RUBY
80+
81+
app_file "config/routes.rb", <<-RUBY
82+
Rails.application.routes.draw do
83+
get "/foo", to: "foo#index"
84+
match "/406", to: "foo#not_acceptable", via: :all
85+
end
86+
RUBY
87+
88+
add_to_config "config.exceptions_app = self.routes"
89+
add_to_config "config.action_dispatch.show_exceptions = true"
90+
add_to_config "config.consider_all_requests_local = false"
91+
92+
get "/foo", {}, { "HTTP_ACCEPT" => "invalid" }
93+
assert_equal 406, last_response.status
94+
assert_not_equal "rendering index!", last_response.body
95+
end
96+
6897
test "uses custom exceptions app" do
6998
add_to_config <<-RUBY
7099
config.exceptions_app = lambda do |env|

0 commit comments

Comments
 (0)