Skip to content

Commit

Permalink
Optimze, split & niceify
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanBout committed Nov 26, 2024
1 parent a08b0a1 commit a72e592
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 81 deletions.
84 changes: 6 additions & 78 deletions SimpleCDN/CDNLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<CDNConfiguration> options)
public class CDNLoader(IWebHostEnvironment environment, IOptionsMonitor<CDNConfiguration> options, IndexGenerator generator)
{
private readonly IWebHostEnvironment _environment = environment;
private readonly IndexGenerator _indexGenerator = generator;

private readonly SizeLimitedCache _cache = new(options.CurrentValue.MaxMemoryCacheSize * 1000, StringComparer.OrdinalIgnoreCase);

Expand Down Expand Up @@ -140,7 +142,7 @@ public class CDNLoader(IWebHostEnvironment environment, IOptionsMonitor<CDNConfi
}


private static (MimeType type, byte[]? content) TryLoadIndex(string absolutePath, string rootRelativePath)
private (MimeType type, byte[]? content) TryLoadIndex(string absolutePath, string rootRelativePath)
{
if (!Directory.Exists(absolutePath)) return MimeTypeHelpers.Empty;

Expand All @@ -162,85 +164,11 @@ private static (MimeType type, byte[]? content) TryLoadIndex(string absolutePath
return (MimeType.HTML, GenerateIndex(absolutePath, rootRelativePath));
}

private static byte[]? GenerateIndex(string absolutePath, string rootRelativePath)
{
if (!Directory.Exists(absolutePath))
{
return null;
}

var directory = new DirectoryInfo(absolutePath);

var index = new StringBuilder();

index.AppendFormat(
"""
<html>
<head>
<meta name="robots" content="noindex,nofollow">
<link rel="stylesheet" href="/_cdn/styles.css">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0">
</head>
<body>
<h1>Index of {0}</h1>
<table>
<thead><tr>
<th>Name</th>
<th>Size</th>
<th>Last Modified</th>
</tr></thead>
<tbody>
""", 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("</tbody></table></body></html>");

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("""<tr><td><a href="{0}">{1}</a></td>""", href, name);
index.AppendFormat("""<td>{0}</td>""", size < 0 ? "-" : size.FormatByteCount());
index.AppendFormat("""<td>{0}</td></tr>""", 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;

Expand Down
2 changes: 2 additions & 0 deletions SimpleCDN/Configuration/CDNConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ public class CDNConfiguration
/// The maximum size of the in-memory cache in kB
/// </summary>
public uint MaxMemoryCacheSize { get; set; } = 500;

public string Footer { get; set; } = """<a href="https://github.com/jonathanbout/simplecdn">Powered by SimpleCDN</a>""";
}
}
2 changes: 1 addition & 1 deletion SimpleCDN/Helpers/GZipHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace SimpleCDN.Helpers
public class GZipHelpers
{
/// <summary>
/// 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.
/// </summary>
/// <param name="data">The data to compress</param>
/// <returns><see langword="false"/> if the compressed data is not smaller than the original data. Otherwise, <see langword="true"/></returns>
Expand Down
89 changes: 89 additions & 0 deletions SimpleCDN/Helpers/IndexGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using Microsoft.Extensions.Options;
using SimpleCDN.Configuration;
using System.Text;

namespace SimpleCDN.Helpers
{
public class IndexGenerator(IOptionsMonitor<CDNConfiguration> options)
{
private readonly IOptionsMonitor<CDNConfiguration> _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(
"""
<html>
<head>
<meta name="robots" content="noindex,nofollow">
<link rel="stylesheet" href="/_cdn/styles.css">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0">
</head>
<body>
<header>
<h1>Index of {0}</h1>
</header>
<main>
<table>
<thead><tr>
<th>Name</th>
<th>Size</th>
<th>Last Modified (UTC)</th>
</tr></thead>
<tbody>
""", rootRelativePath.Replace("/", "<wbr>/"));

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("</tbody></table></main><footer>{0}</footer></body></html>", _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("""<tr><td><a href="{0}">{1}</a></td>""", href, name);
index.AppendFormat("""<td>{0}</td>""", size < 0 ? "-" : size.FormatByteCount());
index.AppendFormat("""<td>{0}</td></tr>""", lastModified.ToString("dd/MM/yyyy HH:mm"));
}
}
}
2 changes: 2 additions & 0 deletions SimpleCDN/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using SimpleCDN;
using SimpleCDN.Configuration;
using SimpleCDN.Helpers;
using System.IO.Compression;

var builder = WebApplication.CreateSlimBuilder(args);
Expand All @@ -21,6 +22,7 @@
.BindConfiguration("CDN");

builder.Services.AddSingleton<CDNLoader>();
builder.Services.AddSingleton<IndexGenerator>();

builder.Services.AddMemoryCache();

Expand Down
32 changes: 30 additions & 2 deletions SimpleCDN/wwwroot/styles.css
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit a72e592

Please sign in to comment.