From a72e59280b02dfbe3d63a542fad2f4e8dc7b79d3 Mon Sep 17 00:00:00 2001 From: Jonathan Bout Date: Tue, 26 Nov 2024 18:16:28 +0100 Subject: [PATCH] Optimze, split & niceify --- SimpleCDN/CDNLoader.cs | 84 ++----------------- SimpleCDN/Configuration/CDNConfiguration.cs | 2 + SimpleCDN/Helpers/GZipHelpers.cs | 2 +- SimpleCDN/Helpers/IndexGenerator.cs | 89 +++++++++++++++++++++ SimpleCDN/Program.cs | 2 + SimpleCDN/wwwroot/styles.css | 32 +++++++- 6 files changed, 130 insertions(+), 81 deletions(-) create mode 100644 SimpleCDN/Helpers/IndexGenerator.cs diff --git a/SimpleCDN/CDNLoader.cs b/SimpleCDN/CDNLoader.cs index d7c5701..ba5ced5 100644 --- a/SimpleCDN/CDNLoader.cs +++ b/SimpleCDN/CDNLoader.cs @@ -7,14 +7,16 @@ using SimpleCDN.Helpers; using System.IO.Compression; using System.Net.Mime; +using System.Runtime.CompilerServices; using System.Text; namespace SimpleCDN { public record CDNFile(byte[] Content, string MediaType, DateTimeOffset LastModified, bool IsCompressed); - public class CDNLoader(IWebHostEnvironment environment, IOptionsMonitor options) + public class CDNLoader(IWebHostEnvironment environment, IOptionsMonitor options, IndexGenerator generator) { private readonly IWebHostEnvironment _environment = environment; + private readonly IndexGenerator _indexGenerator = generator; private readonly SizeLimitedCache _cache = new(options.CurrentValue.MaxMemoryCacheSize * 1000, StringComparer.OrdinalIgnoreCase); @@ -140,7 +142,7 @@ public class CDNLoader(IWebHostEnvironment environment, IOptionsMonitor - - - - - - -

Index of {0}

- - - - - - - - """, rootRelativePath); - - if (rootRelativePath is not "/" and not "" && directory.Parent is DirectoryInfo parent) - { - var lastSlashIndex = rootRelativePath.LastIndexOf('/'); - - string parentRootRelativePath; - - if (lastSlashIndex is < 1) - { - parentRootRelativePath = "/"; - } else - { - parentRootRelativePath = rootRelativePath[..lastSlashIndex]; - } - - AppendRow(index, parentRootRelativePath, "Parent Directory", -1, parent.LastWriteTimeUtc); - } - - foreach (var subDirectory in directory.EnumerateDirectories()) - { - var name = subDirectory.Name; - - AppendRow(index, Path.Combine(rootRelativePath, name), name, -1, subDirectory.LastWriteTimeUtc); - } - - foreach (var file in directory.EnumerateFiles()) - { - var name = file.Name; - - AppendRow(index, Path.Combine(rootRelativePath, name), name, file.Length, file.LastWriteTimeUtc); - } - - index.Append("
NameSizeLast Modified
"); - - var bytes = Encoding.UTF8.GetBytes(index.ToString()); - - return bytes; - } - - private static void AppendRow(StringBuilder index, string href, string name, long size, DateTimeOffset lastModified) - { - index.AppendFormat("""{1}""", href, name); - index.AppendFormat("""{0}""", size < 0 ? "-" : size.FormatByteCount()); - index.AppendFormat("""{0}""", lastModified); - } + private byte[]? GenerateIndex(string absolutePath, string rootRelativePath) => _indexGenerator.GenerateIndex(absolutePath, rootRelativePath); private static (MimeType type, byte[]? content) LoadFileFromDisk(string absolutePath) { - if (!Path.IsPathRooted(absolutePath)) - return MimeTypeHelpers.Empty; + if (!Path.IsPathRooted(absolutePath)) return MimeTypeHelpers.Empty; if (!File.Exists(absolutePath)) return MimeTypeHelpers.Empty; diff --git a/SimpleCDN/Configuration/CDNConfiguration.cs b/SimpleCDN/Configuration/CDNConfiguration.cs index 1ff50e0..d6763d7 100644 --- a/SimpleCDN/Configuration/CDNConfiguration.cs +++ b/SimpleCDN/Configuration/CDNConfiguration.cs @@ -10,5 +10,7 @@ public class CDNConfiguration /// The maximum size of the in-memory cache in kB /// public uint MaxMemoryCacheSize { get; set; } = 500; + + public string Footer { get; set; } = """Powered by SimpleCDN"""; } } diff --git a/SimpleCDN/Helpers/GZipHelpers.cs b/SimpleCDN/Helpers/GZipHelpers.cs index a354d33..aefbee9 100644 --- a/SimpleCDN/Helpers/GZipHelpers.cs +++ b/SimpleCDN/Helpers/GZipHelpers.cs @@ -5,7 +5,7 @@ namespace SimpleCDN.Helpers public class GZipHelpers { /// - /// Compresses the data using GZip. + /// Compresses the data using GZip, in-place. If the compressed data is not smaller than the original data, the original data is left unchanged. /// /// The data to compress /// if the compressed data is not smaller than the original data. Otherwise, diff --git a/SimpleCDN/Helpers/IndexGenerator.cs b/SimpleCDN/Helpers/IndexGenerator.cs new file mode 100644 index 0000000..e7e3f90 --- /dev/null +++ b/SimpleCDN/Helpers/IndexGenerator.cs @@ -0,0 +1,89 @@ +using Microsoft.Extensions.Options; +using SimpleCDN.Configuration; +using System.Text; + +namespace SimpleCDN.Helpers +{ + public class IndexGenerator(IOptionsMonitor options) + { + private readonly IOptionsMonitor _options = options; + + public byte[]? GenerateIndex(string absolutePath, string rootRelativePath) + { + if (!Directory.Exists(absolutePath)) + { + return null; + } + + var directory = new DirectoryInfo(absolutePath); + + var index = new StringBuilder(); + + index.AppendFormat( + """ + + + + + + + +
+

Index of {0}

+
+
+ + + + + + + + """, rootRelativePath.Replace("/", "/")); + + if (rootRelativePath is not "/" and not "" && directory.Parent is DirectoryInfo parent) + { + var lastSlashIndex = rootRelativePath.LastIndexOf('/'); + + string parentRootRelativePath; + + if (lastSlashIndex is < 1) + { + parentRootRelativePath = "/"; + } else + { + parentRootRelativePath = rootRelativePath[..lastSlashIndex]; + } + + AppendRow(index, parentRootRelativePath, "Parent Directory", -1, parent.LastWriteTimeUtc); + } + + foreach (var subDirectory in directory.EnumerateDirectories()) + { + var name = subDirectory.Name; + + AppendRow(index, Path.Combine(rootRelativePath, name), name, -1, subDirectory.LastWriteTimeUtc); + } + + foreach (var file in directory.EnumerateFiles()) + { + var name = file.Name; + + AppendRow(index, Path.Combine(rootRelativePath, name), name, file.Length, file.LastWriteTimeUtc); + } + + index.AppendFormat("
NameSizeLast Modified (UTC)
{0}
", _options.CurrentValue.Footer); + + var bytes = Encoding.UTF8.GetBytes(index.ToString()); + + return bytes; + } + + private static void AppendRow(StringBuilder index, string href, string name, long size, DateTimeOffset lastModified) + { + index.AppendFormat("""{1}""", href, name); + index.AppendFormat("""{0}""", size < 0 ? "-" : size.FormatByteCount()); + index.AppendFormat("""{0}""", lastModified.ToString("dd/MM/yyyy HH:mm")); + } + } +} diff --git a/SimpleCDN/Program.cs b/SimpleCDN/Program.cs index 18306f6..d1718c2 100644 --- a/SimpleCDN/Program.cs +++ b/SimpleCDN/Program.cs @@ -1,5 +1,6 @@ using SimpleCDN; using SimpleCDN.Configuration; +using SimpleCDN.Helpers; using System.IO.Compression; var builder = WebApplication.CreateSlimBuilder(args); @@ -21,6 +22,7 @@ .BindConfiguration("CDN"); builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddMemoryCache(); diff --git a/SimpleCDN/wwwroot/styles.css b/SimpleCDN/wwwroot/styles.css index f508ff7..fcc33dd 100644 --- a/SimpleCDN/wwwroot/styles.css +++ b/SimpleCDN/wwwroot/styles.css @@ -1,26 +1,54 @@ @font-face { font-family: Code; font-display: swap; - src: local("Cascadia Code"),url(/CascadiaCode/woff2/CascadiaCode.woff2) format("woff2"),url(/CascadiaCode/ttf/CascadiaCode.ttf) format("truetype"),url(/CascadiaCode/CascadiaCode.ttf) format("truetype"),url(/CascadiaCode/otf/static/CascadiaCodeNF-Regular.otf) format("opentype"),local("Cascadia Mono"),monospace + src: local("Cascadia Code"),url(/CascadiaCode/woff2/CascadiaCode.woff2) format("woff2"),url(/CascadiaCode/ttf/CascadiaCode.ttf) format("truetype"),url(/CascadiaCode/CascadiaCode.ttf) format("truetype"),url(/CascadiaCode/otf/static/CascadiaCodeNF-Regular.otf) format("opentype"),local("Cascadia Mono"),monospace; } :root { font-family: Code; } +* { + box-sizing: border-box; +} + +body { + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 100vh; + margin: 0; + padding: 0; + padding-block: 5px; + max-width: 100vw; + overflow-x: hidden; +} + +main { + overflow: auto; +} + table { margin: auto; + overflow: auto; } h1 { text-align: center; + overflow: auto; + padding-inline: 5px; + } th, td { padding: .2em 1em; } -table > thead > tr > th { +thead th { font-size: 1.2rem; border-bottom: 1px solid black; +} + +footer { + text-align: center; } \ No newline at end of file