discourse/lib/middleware/default_headers.rb
Kelv 305039b1c3
DEV: ensure Rails application default headers are present in responses (#31619)
Follow up from https://github.com/discourse/discourse/pull/31559.

We expect some standard headers to be added from
`Rails.application.config.action_dispatch.default_headers` for
responses, however these were found to be removed in some error paths. 
For more detail on this behaviour, refer to https://github.com/discourse/discourse/pull/31619#issuecomment-2699644232.

This PR adds those headers back if they aren't there, with the caveats
that we don't add headers that are irrelevant for non-HTML responses,
and neither do we add X-Frame-Options which is intentionally removed for
embeddables.
2025-03-05 13:19:09 +08:00

40 lines
1009 B
Ruby

# frozen_string_literal: true
module Middleware
class DefaultHeaders
HTML_ONLY_HEADERS = Set.new(%w[X-XSS-Protection])
EXCLUDED_HEADERS = Set.new(%w[X-Frame-Options])
def initialize(app, settings = {})
@app = app
end
def call(env)
status, headers, body = @app.call(env)
is_html_response = html_response?(headers)
default_headers =
Rails.application.config.action_dispatch.default_headers.to_h.except(*EXCLUDED_HEADERS)
default_headers.each do |header_name, value|
next if !is_html_response && HTML_ONLY_HEADERS.include?(header_name)
headers[header_name] ||= value
end
headers[
"Cross-Origin-Opener-Policy"
] = SiteSetting.cross_origin_opener_policy_header if is_html_response &&
headers["Cross-Origin-Opener-Policy"].nil?
[status, headers, body]
end
private
def html_response?(headers)
headers["Content-Type"] && headers["Content-Type"] =~ /html/
end
end
end