discourse/lib/middleware/discourse_public_exceptions.rb
Sam Saffron 423ad5f0a4 FIX: do not log if an invalid mime type is passed to app
Previously our custom exception handler was unable to handle situations
where an invalid mime type was sent, resulting in a warning log

This ensures we pretend a request is HTML for the purpose of rendering
the error page if an invalid mime type from a scanner is shipped to the app
2019-11-21 15:51:34 +11:00

59 lines
2.0 KiB
Ruby

# frozen_string_literal: true
# since all the rescue from clauses are not caught by the application controller for matches
# we need to handle certain exceptions here
module Middleware
class DiscoursePublicExceptions < ::ActionDispatch::PublicExceptions
def initialize(path)
super
end
def call(env)
# this is so so gnarly
# sometimes we leak out exceptions prior to creating a controller instance
# this can happen if we have an exception in a route constraint in some cases
# this code re-dispatches the exception to our application controller so we can
# properly translate the exception to a page
exception = env["action_dispatch.exception"]
response = ActionDispatch::Response.new
# Special handling for invalid params, in this case we can not re-dispatch
# the Request object has a "broken" .params which can not be accessed
exception = nil if Rack::QueryParser::InvalidParameterError === exception
# We also can not dispatch bad requests as no proper params
exception = nil if ActionController::BadRequest === exception
if exception
begin
fake_controller = ApplicationController.new
fake_controller.response = response
fake_controller.request = request = ActionDispatch::Request.new(env)
begin
request.format
rescue Mime::Type::InvalidMimeType
# got to do something here, we can not ship invalid format
# to the exception handler cause it will explode
request.format = "html"
end
if ApplicationController.rescue_with_handler(exception, object: fake_controller)
body = response.body
if String === body
body = [body]
end
return [response.status, response.headers, body]
end
rescue => e
Discourse.warn_exception(e, message: "Failed to handle exception in exception app middleware")
end
end
super
end
end
end