mirror of
https://github.com/discourse/discourse.git
synced 2024-11-23 19:35:13 +08:00
bca855f239
- 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
120 lines
4.1 KiB
Ruby
120 lines
4.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# we want MessageBus to be close to the front
|
|
# this is important cause the vast majority of web requests go to it
|
|
# this allows us to avoid full middleware crawls each time
|
|
#
|
|
# We aren't manipulating the middleware stack directly because of
|
|
# https://github.com/rails/rails/pull/27936
|
|
|
|
Rails.configuration.middleware.unshift(MessageBus::Rack::Middleware)
|
|
|
|
# no reason to track this in development, that is 300+ redis calls saved per
|
|
# page view (we serve all assets out of thin in development)
|
|
if Rails.env != "development" || ENV["TRACK_REQUESTS"]
|
|
require "middleware/request_tracker"
|
|
Rails.configuration.middleware.unshift Middleware::RequestTracker
|
|
|
|
MethodProfiler.ensure_discourse_instrumentation! if GlobalSetting.enable_performance_http_headers
|
|
end
|
|
|
|
if Rails.env.test?
|
|
# In test mode we can't insert/remove middlewares
|
|
# Therefore we insert a small helper which effectively switches the multisite
|
|
# middleware on/off based on the Rails.configuration.multisite value
|
|
class TestMultisiteMiddleware < RailsMultisite::Middleware
|
|
def call(env)
|
|
return @app.call(env) if !Rails.configuration.multisite
|
|
super(env)
|
|
end
|
|
end
|
|
|
|
Rails.configuration.middleware.unshift TestMultisiteMiddleware,
|
|
RailsMultisite::DiscoursePatches.config
|
|
|
|
class BlockRequestsMiddleware
|
|
RSPEC_CURRENT_EXAMPLE_COOKIE_STRING = "rspec_current_example_location"
|
|
|
|
cattr_accessor :current_example_location
|
|
|
|
@@block_requests = false
|
|
|
|
def self.block_requests!
|
|
@@block_requests = true
|
|
end
|
|
|
|
def self.allow_requests!
|
|
@@block_requests = false
|
|
end
|
|
|
|
def initialize(app)
|
|
@app = app
|
|
end
|
|
|
|
def call(env)
|
|
request = Rack::Request.new(env)
|
|
|
|
if (
|
|
@@block_requests ||
|
|
(
|
|
request.xhr? && self.class.current_example_location.present? &&
|
|
self.class.current_example_location !=
|
|
request.cookies[RSPEC_CURRENT_EXAMPLE_COOKIE_STRING]
|
|
)
|
|
)
|
|
return [
|
|
503,
|
|
{ "Content-Type" => "text/plain" },
|
|
[
|
|
"Blocked by BlockRequestsMiddleware for requests initiated by #{request.cookies[RSPEC_CURRENT_EXAMPLE_COOKIE_STRING]} when running #{self.class.current_example_location}",
|
|
]
|
|
]
|
|
end
|
|
|
|
status, headers, body = @app.call(env)
|
|
if headers["Content-Type"]&.match?(/html/) && BlockRequestsMiddleware.current_example_location
|
|
headers["Set-Cookie"] = [
|
|
headers["Set-Cookie"],
|
|
"#{RSPEC_CURRENT_EXAMPLE_COOKIE_STRING}=#{BlockRequestsMiddleware.current_example_location}; path=/;",
|
|
].compact.join("\n")
|
|
end
|
|
[status, headers, body]
|
|
end
|
|
end
|
|
|
|
Rails.configuration.middleware.unshift BlockRequestsMiddleware
|
|
elsif Rails.configuration.multisite
|
|
assets_hostnames = GlobalSetting.cdn_hostnames
|
|
|
|
if assets_hostnames.empty?
|
|
assets_hostnames = Discourse::Application.config.database_configuration[Rails.env]["host_names"]
|
|
end
|
|
|
|
RailsMultisite::ConnectionManagement.asset_hostnames = assets_hostnames
|
|
|
|
# Multisite needs to be first, because the request tracker and message bus rely on it
|
|
Rails.configuration.middleware.unshift RailsMultisite::Middleware,
|
|
RailsMultisite::DiscoursePatches.config
|
|
Rails.configuration.middleware.delete ActionDispatch::Executor
|
|
|
|
if defined?(RailsFailover::ActiveRecord) && Rails.configuration.active_record_rails_failover
|
|
Rails.configuration.middleware.insert_after(
|
|
RailsMultisite::Middleware,
|
|
RailsFailover::ActiveRecord::Middleware,
|
|
)
|
|
end
|
|
|
|
if Rails.env.development?
|
|
# Automatically allow development multisite hosts
|
|
RailsMultisite::ConnectionManagement.instance.db_spec_cache.each do |db, specification|
|
|
next if db == "default"
|
|
Rails.configuration.hosts.concat(specification.spec.configuration_hash[:host_names])
|
|
end
|
|
end
|
|
elsif defined?(RailsFailover::ActiveRecord) && Rails.configuration.active_record_rails_failover
|
|
Rails.configuration.middleware.insert_before(
|
|
MessageBus::Rack::Middleware,
|
|
RailsFailover::ActiveRecord::Middleware,
|
|
)
|
|
end
|