Simplify StaticAssetsHandler implementation

Overriding `#call` or patching out `serve_file_compressed` provides
only minimal benefits over the ease of maintenance granted by only
overriding what we need to for the caching behavior.
This commit is contained in:
syeopite 2025-06-03 09:04:33 -07:00
parent 748ef23326
commit 628f45de01
No known key found for this signature in database
GPG Key ID: A73C186DA3955A1A

View File

@ -9,52 +9,30 @@ module Invidious::HttpServer
# rest of the class's methods, imitating the object allows us to only lookup # rest of the class's methods, imitating the object allows us to only lookup
# the cache hash once for every request. # the cache hash once for every request.
# #
private record CachedFile, data : Bytes, size : Int64, modification_time : Time private record CachedFile, data : Bytes, size : Int64, modification_time : Time do
def directory?
false
end
def file?
true
end
end
CACHE_LIMIT = 5_000_000 # 5MB CACHE_LIMIT = 5_000_000 # 5MB
@@cached_files = {} of Path => CachedFile @@cached_files = {} of Path => CachedFile
# A simplified version of `#call` for Invidious to improve performance. # Returns metadata for the requested file
# #
# This is basically the same as what we inherited but just with the directory listing # If the requested file is cached, a `CachedFile` is returned instead of a `File::Stat`.
# features stripped out. This removes some conditional checks and calls which improves # This represents the metadata info of a cached file and implements all the methods of `File::Stat` that
# performance slightly but otherwise is entirely unneeded. # is used by the `StaticAssetsHandler`.
# #
# Really, all the cache feature actually needs is to override the much simplifier `file_info` # The `CachedFile` also stores the raw bytes of the cached file, and this method serves as the place where
# method to return a `CachedFile` or `File::Stat` depending on whether the file is cached. # the cached file is retrieved if it exists. Though the data will only be read in `#serve_file`
def call(context) : Nil private def file_info(expanded_path : Path)
check_request_method!(context) || return
request_path = request_path(context)
check_request_path!(context, request_path) || return
request_path = Path.posix(request_path)
expanded_path = request_path.expand("/")
# The path normalization can be simplified to just this since
# we don't need to care about normalizing directory urls.
if request_path != expanded_path
redirect_to context, expanded_path
end
file_path = @public_dir.join(expanded_path.to_kind(Path::Kind.native)) file_path = @public_dir.join(expanded_path.to_kind(Path::Kind.native))
{@@cached_files[file_path]? || File.info?(file_path), file_path}
if cached_info = @@cached_files[file_path]?
return serve_file_with_cache(context, cached_info, file_path)
end
file_info = File.info?(file_path)
return call_next(context) unless file_info
if file_info.file?
# Actually means to serve file *with cache headers*
# The actual logic for serving the file is done in `#serve_file`
serve_file_with_cache(context, file_info, file_path)
else # Not a normal file (FIFO/device/socket)
call_next(context)
end
end end
# Add "Cache-Control" header to the response # Add "Cache-Control" header to the response
@ -111,11 +89,6 @@ module Invidious::HttpServer
end end
end end
# Skips the stdlib logic for serving pre-gzipped files
private def serve_file_compressed(context : HTTP::Server::Context, file_info, file_path : Path, last_modified : Time)
serve_file(context, file_info, file_path, file_path, last_modified)
end
# If we're serving the full file right away then there's no need for an IO at all. # If we're serving the full file right away then there's no need for an IO at all.
private def serve_file_full(context : HTTP::Server::Context, file : Bytes, file_info) private def serve_file_full(context : HTTP::Server::Context, file : Bytes, file_info)
context.response.status = :ok context.response.status = :ok