diff --git a/spec/invidious/subtitle_cache_spec.cr b/spec/invidious/subtitle_cache_spec.cr index 0a6f22ce0..cf6b3fe5f 100644 --- a/spec/invidious/subtitle_cache_spec.cr +++ b/spec/invidious/subtitle_cache_spec.cr @@ -81,6 +81,13 @@ Spectator.describe Invidious::SubtitleCache do expect(cache.get("video:123|label:Chinese|lang:zh|tlang:").try &.body).to eq(vtt_zh) end + it "builds cache keys that isolate delimiter-containing values" do + key_a = Invidious::SubtitleCache.caption_cache_key("video", "English|lang:x", "en", "") + key_b = Invidious::SubtitleCache.caption_cache_key("video", "English", "lang:x", "") + + expect(key_a).not_to eq(key_b) + end + it "returns miss on first fetch and hit on subsequent fetch" do cache = Invidious::SubtitleCache.new fetch_count = 0 diff --git a/src/invidious/helpers/subtitle_cache.cr b/src/invidious/helpers/subtitle_cache.cr index 224cd94e7..311766df5 100644 --- a/src/invidious/helpers/subtitle_cache.cr +++ b/src/invidious/helpers/subtitle_cache.cr @@ -72,6 +72,10 @@ module Invidious header_end == trimmed.size || " \t\r\n".includes?(trimmed[header_end]) end + def self.caption_cache_key(video_id : String, label : String, lang : String, tlang : String) : String + [video_id, label, lang, tlang].map { |value| Base64.urlsafe_encode(value) }.join('|') + end + def self.read_limited_body(input : IO, limit : Int32 = MAX_ENTRY_BYTES) : LimitedBody output = IO::Memory.new buffer = Bytes.new(READ_CHUNK_BYTES) diff --git a/src/invidious/routes/companion.cr b/src/invidious/routes/companion.cr index bfae5be12..8b7be7db5 100644 --- a/src/invidious/routes/companion.cr +++ b/src/invidious/routes/companion.cr @@ -80,7 +80,7 @@ module Invidious::Routes::Companion return end - cache_key = "video:#{video_id}|label:#{label}|lang:#{lang}|tlang:#{tlang}" + cache_key = Invidious::SubtitleCache.caption_cache_key(video_id, label, lang, tlang) result = SUBTITLE_CACHE.get_or_fetch(cache_key) do fetch_from_companion(url, env.request.headers)