mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 22:43:33 +08:00
FEATURE: if site is under extreme load show anon view
If a particular path is being hit extremely hard by logged on users, revert to anonymous cached view. This will only come into effect if 3 requests queue for longer than 2 seconds on a *single* path. This can happen if a URL is shared with the entire forum base and everyone is logged on
This commit is contained in:
@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_dependency "mobile_detection"
|
||||
require_dependency "crawler_detection"
|
||||
require_dependency "guardian"
|
||||
@ -10,9 +12,9 @@ module Middleware
|
||||
end
|
||||
|
||||
class Helper
|
||||
USER_AGENT = "HTTP_USER_AGENT".freeze
|
||||
RACK_SESSION = "rack.session".freeze
|
||||
ACCEPT_ENCODING = "HTTP_ACCEPT_ENCODING".freeze
|
||||
USER_AGENT = "HTTP_USER_AGENT"
|
||||
RACK_SESSION = "rack.session"
|
||||
ACCEPT_ENCODING = "HTTP_ACCEPT_ENCODING"
|
||||
|
||||
def initialize(env)
|
||||
@env = env
|
||||
@ -86,7 +88,40 @@ module Middleware
|
||||
|
||||
def no_cache_bypass
|
||||
request = Rack::Request.new(@env)
|
||||
request.cookies['_bypass_cache'].nil?
|
||||
request.cookies['_bypass_cache'].nil? &&
|
||||
request[Auth::DefaultCurrentUserProvider::API_KEY].nil? &&
|
||||
@env[Auth::DefaultCurrentUserProvider::USER_API_KEY].nil?
|
||||
end
|
||||
|
||||
def force_anonymous!
|
||||
@env[Auth::DefaultCurrentUserProvider::USER_API_KEY] = nil
|
||||
@env['HTTP_COOKIE'] = nil
|
||||
@env['rack.request.cookie.hash'] = {}
|
||||
@env['rack.request.cookie.string'] = ''
|
||||
@env['_bypass_cache'] = nil
|
||||
request = Rack::Request.new(@env)
|
||||
request.delete_param('api_username')
|
||||
request.delete_param('api_key')
|
||||
end
|
||||
|
||||
def check_logged_in_rate_limit!
|
||||
limiter = RateLimiter.new(
|
||||
nil,
|
||||
"logged_in_anon_cache_#{@env["HOST"]}/#{@env["REQUEST_URI"]}",
|
||||
GlobalSetting.force_anonymous_min_per_10_seconds,
|
||||
10
|
||||
)
|
||||
!limiter.performed!(raise_error: false)
|
||||
end
|
||||
|
||||
def should_force_anonymous?
|
||||
if queue_time = @env['REQUEST_QUEUE_SECONDS']
|
||||
if queue_time > GlobalSetting.force_anonymous_min_queue_seconds && get?
|
||||
return check_logged_in_rate_limit!
|
||||
end
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def cacheable?
|
||||
@ -142,13 +177,26 @@ module Middleware
|
||||
|
||||
def call(env)
|
||||
helper = Helper.new(env)
|
||||
force_anon = false
|
||||
|
||||
if helper.cacheable?
|
||||
helper.cached || helper.cache(@app.call(env))
|
||||
else
|
||||
@app.call(env)
|
||||
if helper.should_force_anonymous?
|
||||
force_anon = env["DISCOURSE_FORCE_ANON"] = true
|
||||
helper.force_anonymous!
|
||||
end
|
||||
|
||||
result =
|
||||
if helper.cacheable?
|
||||
helper.cached || helper.cache(@app.call(env))
|
||||
else
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
if force_anon
|
||||
result[1]["Set-Cookie"] = "dosp=1"
|
||||
end
|
||||
|
||||
result
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
Reference in New Issue
Block a user