Skip to content

Commit

Permalink
Merge pull request #43104 from ghiculescu/http-406-crash
Browse files Browse the repository at this point in the history
Fix crash in `ActionController::Instrumentation` with invalid HTTP formats
  • Loading branch information
rafaelfranca committed Sep 21, 2021
1 parent 4ac2eca commit 4503b2d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
10 changes: 10 additions & 0 deletions actionpack/lib/action_dispatch/middleware/show_exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def render_exception(request, exception)
request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
request.set_header "action_dispatch.original_path", request.path_info
request.set_header "action_dispatch.original_request_method", request.raw_request_method
fallback_to_html_format_if_invalid_mime_type(request)
request.path_info = "/#{status}"
request.request_method = "GET"
response = @exceptions_app.call(request.env)
Expand All @@ -56,6 +57,15 @@ def render_exception(request, exception)
FAILSAFE_RESPONSE
end

def fallback_to_html_format_if_invalid_mime_type(request)
# If the MIME type for the request is invalid then the
# @exceptions_app may not be able to handle it. To make it
# easier to handle, we switch to HTML.
request.formats
rescue ActionDispatch::Http::MimeNegotiation::InvalidType
request.set_header "HTTP_ACCEPT", "text/html"
end

def pass_response(status)
[status, { "Content-Type" => "text/html; charset=#{Response.default_charset}", "Content-Length" => "0" }, []]
end
Expand Down
29 changes: 29 additions & 0 deletions railties/test/application/middleware/exceptions_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,35 @@ def index
assert_equal 405, last_response.status
end

test "renders unknown http formats as 406 when routes are used as the custom exceptions app" do
controller :foo, <<-RUBY
class FooController < ActionController::Base
def index
render plain: "rendering index!"
end
def not_acceptable
render json: { error: "some error message" }, status: :not_acceptable
end
end
RUBY

app_file "config/routes.rb", <<-RUBY
Rails.application.routes.draw do
get "/foo", to: "foo#index"
match "/406", to: "foo#not_acceptable", via: :all
end
RUBY

add_to_config "config.exceptions_app = self.routes"
add_to_config "config.action_dispatch.show_exceptions = true"
add_to_config "config.consider_all_requests_local = false"

get "/foo", {}, { "HTTP_ACCEPT" => "invalid" }
assert_equal 406, last_response.status
assert_not_equal "rendering index!", last_response.body
end

test "uses custom exceptions app" do
add_to_config <<-RUBY
config.exceptions_app = lambda do |env|
Expand Down

0 comments on commit 4503b2d

Please sign in to comment.