Files
aliasvault/apps/server/AliasVault.Admin/Services/VersionedContentService.cs
2025-09-03 14:59:14 +02:00

60 lines
2.2 KiB
C#

//-----------------------------------------------------------------------
// <copyright file="VersionedContentService.cs" company="aliasvault">
// Copyright (c) aliasvault. All rights reserved.
// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
namespace AliasVault.Admin.Services;
using System.Security.Cryptography;
/// <summary>
/// Service to provide versioned content paths for cache busting of static files.
/// </summary>
public class VersionedContentService
{
private readonly Dictionary<string, string> _hashCache = new();
private readonly string _webRootPath;
/// <summary>
/// Initializes a new instance of the <see cref="VersionedContentService"/> class.
/// </summary>
/// <param name="webRootPath">Web root path.</param>
/// <exception cref="ArgumentNullException">Thrown if webRootPath is not provided.</exception>
public VersionedContentService(string webRootPath)
{
_webRootPath = webRootPath ?? throw new ArgumentNullException(nameof(webRootPath));
}
/// <summary>
/// Get the versioned path for a content file.
/// </summary>
/// <param name="contentPath">Content path to the file.</param>
/// <returns>Path with version suffix added.</returns>
public string GetVersionedPath(string contentPath)
{
if (!_hashCache.TryGetValue(contentPath, out var version))
{
var serverPath = Path.Combine(_webRootPath, contentPath.TrimStart('/'));
version = GetVersionHashFrom(serverPath);
_hashCache[contentPath] = version;
}
return $"{contentPath}?v={version}";
}
/// <summary>
/// Calculate the version hash for a file.
/// </summary>
/// <param name="serverPath">Path to the file on the server.</param>
/// <returns>MD5 hash.</returns>
private static string GetVersionHashFrom(string serverPath)
{
using var md5 = MD5.Create();
using var stream = File.OpenRead(serverPath);
byte[] hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();
}
}