FIX: Improve handling of 'PublicExceptions' when bootstrap_error_pages enabled (#26700)

- Run the CSP-nonce-related middlewares on the generated response

- Fix the readonly mode checking to avoid empty strings being passed (the `check_readonly_mode` before_action will not execute in the case of these re-dispatched exceptions)

- Move the BlockRequestsMiddleware cookie-setting to the middleware, so that it is included even for unusual HTML responses like these exceptions
This commit is contained in:
David Taylor
2024-04-24 09:40:13 +01:00
committed by GitHub
parent 25bcee43c6
commit bca855f239
7 changed files with 65 additions and 16 deletions

View File

@@ -4,6 +4,12 @@
# we need to handle certain exceptions here
module Middleware
class DiscoursePublicExceptions < ::ActionDispatch::PublicExceptions
# These middlewares will be re-run when the exception response is generated
EXCEPTION_RESPONSE_MIDDLEWARES = [
ContentSecurityPolicy::Middleware,
Middleware::CspScriptNonceInjector,
]
INVALID_REQUEST_ERRORS =
Set.new(
[
@@ -60,7 +66,10 @@ module Middleware
if ApplicationController.rescue_with_handler(exception, object: fake_controller)
body = response.body
body = [body] if String === body
return response.status, response.headers, body
rack_response = [response.status, response.headers, body]
app = lambda { |env| rack_response }
EXCEPTION_RESPONSE_MIDDLEWARES.each { |middleware| app = middleware.new(app) }
return app.call(env)
end
rescue => e
return super if INVALID_REQUEST_ERRORS.include?(e.class)

View File

@@ -32,6 +32,16 @@ module ReadOnlyMixin
end
end
def get_or_check_readonly_mode
check_readonly_mode if @readonly_mode.nil?
@readonly_mode
end
def get_or_check_staff_writes_only_mode
check_readonly_mode if @readonly_mode.nil?
@readonly_mode
end
def add_readonly_header
response.headers["Discourse-Readonly"] = "true" if @readonly_mode
end