73 lines
2.1 KiB
C#
73 lines
2.1 KiB
C#
using Microsoft.Extensions.Options;
|
|
using Web.Settings;
|
|
|
|
namespace Web.Middleware;
|
|
|
|
public sealed class SiteModeMiddleware(RequestDelegate next, IOptions<SiteSettings> options)
|
|
{
|
|
private static readonly string[] StaticAssetPrefixes =
|
|
[
|
|
"/css/",
|
|
"/js/",
|
|
"/img/",
|
|
"/logo/",
|
|
"/fonts/"
|
|
];
|
|
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
var mode = ResolveMode(options.Value.Mode);
|
|
if (mode == SiteModes.Normal)
|
|
{
|
|
await next(context);
|
|
return;
|
|
}
|
|
|
|
var path = context.Request.Path.Value ?? "/";
|
|
var statusPath = GetStatusPath(mode);
|
|
|
|
if (IsAllowedPath(path, statusPath))
|
|
{
|
|
if (mode == SiteModes.Unavailable &&
|
|
path.Equals("/site-unavailable.html", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;
|
|
context.Response.Headers.RetryAfter = "3600";
|
|
}
|
|
|
|
await next(context);
|
|
return;
|
|
}
|
|
|
|
context.Response.Redirect(statusPath);
|
|
}
|
|
|
|
private static string ResolveMode(string? configuredMode)
|
|
{
|
|
if (string.Equals(configuredMode, SiteModes.UnderConstruction, StringComparison.OrdinalIgnoreCase))
|
|
return SiteModes.UnderConstruction;
|
|
|
|
if (string.Equals(configuredMode, SiteModes.Unavailable, StringComparison.OrdinalIgnoreCase))
|
|
return SiteModes.Unavailable;
|
|
|
|
return SiteModes.Normal;
|
|
}
|
|
|
|
private static string GetStatusPath(string mode) =>
|
|
mode == SiteModes.UnderConstruction
|
|
? "/under-construction.html"
|
|
: "/site-unavailable.html";
|
|
|
|
private static bool IsAllowedPath(string path, string statusPath)
|
|
{
|
|
if (path.Equals(statusPath, StringComparison.OrdinalIgnoreCase))
|
|
return true;
|
|
|
|
if (path.Equals("/favicon.ico", StringComparison.OrdinalIgnoreCase))
|
|
return true;
|
|
|
|
return StaticAssetPrefixes.Any(prefix =>
|
|
path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
}
|