feat: do all the backend balancing on the invidious side

This will make invidious easier to maintain and escalate without the need of an overcomplicated reverse proxy configuration and multiple invidious instances with each one with a different configuration (in this case, invidious companion)
This commit is contained in:
Fijxu
2025-03-30 20:08:15 -03:00
parent ddf6802d76
commit d47aa3dd6a
13 changed files with 341 additions and 265 deletions

View File

@@ -9,7 +9,8 @@ module Invidious::Routes::API::Manifest
region = env.params.query["region"]?
if CONFIG.invidious_companion.present?
invidious_companion = CONFIG.invidious_companion.sample
current_companion = env.get("current_companion").as(Int32)
invidious_companion = CONFIG.invidious_companion[current_companion]
return env.redirect "#{invidious_companion.public_url}/api/manifest/dash/id/#{id}?#{env.params.query}"
end

View File

@@ -0,0 +1,16 @@
{% skip_file if flag?(:api_only) %}
module Invidious::Routes::BackendSwitcher
def self.switch(env)
referer = get_referer(env)
backend_id = env.params.query["backend_id"]?.try &.to_i
if backend_id.nil?
return error_template(400, "Backend ID is required")
end
env.response.cookies[CONFIG.server_id_cookie_name] = Invidious::User::Cookies.server_id(env.request.headers["Host"], backend_id)
env.redirect referer
end
end

View File

@@ -24,12 +24,33 @@ module Invidious::Routes::BeforeAll
extra_connect_csp = ""
if CONFIG.invidious_companion.present?
extra_media_csp = " #{CONFIG.invidious_companion.sample.public_url}"
extra_connect_csp = " #{CONFIG.invidious_companion.sample.public_url}"
exvpp_url = BackendInfo.get_exvpp
if !exvpp_url.empty?
extra_media_csp += " #{exvpp_url}"
extra_connect_csp += " #{exvpp_url}"
if env.request.cookies[CONFIG.server_id_cookie_name]?.nil?
env.response.cookies[CONFIG.server_id_cookie_name] = Invidious::User::Cookies.server_id(env.request.headers["Host"])
end
begin
current_companion = env.request.cookies[CONFIG.server_id_cookie_name].value.try &.to_i
rescue
current_companion = rand(CONFIG.invidious_companion.size)
end
if current_companion > CONFIG.invidious_companion.size
current_companion = current_companion % CONFIG.invidious_companion.size
env.response.cookies[CONFIG.server_id_cookie_name] = Invidious::User::Cookies.server_id(env.request.headers["Host"], current_companion)
end
env.set "current_companion", current_companion
CONFIG.invidious_companion.each do |companion|
extra_media_csp += " #{companion.public_url}"
extra_connect_csp += " #{companion.public_url}"
end
exvpp_urls = BackendInfo.get_exvpp
exvpp_urls.each do |exvpp_url|
if !exvpp_url.empty?
extra_media_csp += " #{exvpp_url}"
extra_connect_csp += " #{exvpp_url}"
end
end
end

View File

@@ -267,7 +267,8 @@ module Invidious::Routes::VideoPlayback
# so we have a mechanism here to redirect to the latest version
def self.latest_version(env)
if CONFIG.invidious_companion.present?
invidious_companion = CONFIG.invidious_companion.sample
current_companion = env.get("current_companion").as(Int32)
invidious_companion = CONFIG.invidious_companion[current_companion]
return env.redirect "#{invidious_companion.public_url}/latest_version?#{env.params.query}"
end

View File

@@ -52,7 +52,7 @@ module Invidious::Routes::Watch
env.params.query.delete_all("listen")
begin
video = get_video(id, region: params.region)
video = get_video(id, region: params.region, env: env)
rescue ex : NotFoundException
LOGGER.error("get_video not found: #{id} : #{ex.message}")
return error_template(404, ex)
@@ -214,7 +214,8 @@ module Invidious::Routes::Watch
end
if CONFIG.invidious_companion.present?
invidious_companion = CONFIG.invidious_companion.sample
current_companion = env.get("current_companion").as(Int32)
invidious_companion = CONFIG.invidious_companion[current_companion]
env.response.headers["Content-Security-Policy"] =
env.response.headers["Content-Security-Policy"]
.gsub("media-src", "media-src #{invidious_companion.public_url}")
@@ -350,8 +351,9 @@ module Invidious::Routes::Watch
env.params.query["local"] = "true"
if (CONFIG.invidious_companion.present?)
video = get_video(video_id)
invidious_companion = CONFIG.invidious_companion.sample
video = get_video(video_id, env: env)
current_companion = env.get("current_companion").as(Int32)
invidious_companion = CONFIG.invidious_companion[current_companion]
return env.redirect "#{invidious_companion.public_url}/latest_version?#{env.params.query}"
else
return Invidious::Routes::VideoPlayback.latest_version(env)