Serve 503 when PocketBase is unavailable across all content pages
This commit is contained in:
1 parent
0f7e968c16
commit
e242eaf79a
25 files changed
+492
-253
No files matched your search
@@ -0,0 +1,21 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Elternbeirat.Web.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Shared <see cref="CultureInfo"/> instances used to format visitor-facing
|
||||
/// text.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Kept in one place so every component renders month and weekday names the
|
||||
/// same way, rather than each holding its own <c>de-DE</c> lookup. This is only
|
||||
/// for display text; machine-readable output (e.g. an HTML <c>datetime</c>
|
||||
/// attribute) uses <see cref="CultureInfo.InvariantCulture"/> instead.
|
||||
/// </remarks>
|
||||
internal static class Cultures
|
||||
{
|
||||
/// <summary>
|
||||
/// German culture, for the month and weekday names visitors read.
|
||||
/// </summary>
|
||||
public static readonly CultureInfo German = CultureInfo.GetCultureInfo("de-DE");
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Globalization;
|
||||
using Elternbeirat.Contracts;
|
||||
|
||||
namespace Elternbeirat.Web.Shared;
|
||||
@@ -22,11 +21,6 @@ public static class EventFormat
|
||||
/// </summary>
|
||||
private const string ShortDate = "d. MMMM yyyy";
|
||||
|
||||
/// <summary>
|
||||
/// The culture used for month and weekday names.
|
||||
/// </summary>
|
||||
private static readonly CultureInfo German = CultureInfo.GetCultureInfo("de-DE");
|
||||
|
||||
/// <summary>
|
||||
/// Formats the date range of an event.
|
||||
/// </summary>
|
||||
@@ -54,7 +48,7 @@ public static class EventFormat
|
||||
(var start, null, var hasTime)
|
||||
=> Stamp(start, LongDate, hasTime),
|
||||
(var start, { } end, true) when end.Date == start.Date
|
||||
=> $"{start.ToString(LongDate, German)}, {start.ToString("HH:mm", German)}–{end.ToString("HH:mm", German)} Uhr",
|
||||
=> $"{start.ToString(LongDate, Cultures.German)}, {start.ToString("HH:mm", Cultures.German)}–{end.ToString("HH:mm", Cultures.German)} Uhr",
|
||||
(var start, { } end, false) when end.Date == start.Date
|
||||
=> Stamp(start, LongDate, withTime: false),
|
||||
(var start, { } end, var hasTime)
|
||||
@@ -78,6 +72,6 @@ public static class EventFormat
|
||||
/// </returns>
|
||||
private static string Stamp(DateTime value, string dateFormat, bool withTime)
|
||||
=> withTime
|
||||
? value.ToString(dateFormat + ", HH:mm", German) + " Uhr"
|
||||
: value.ToString(dateFormat, German);
|
||||
? value.ToString(dateFormat + ", HH:mm", Cultures.German) + " Uhr"
|
||||
: value.ToString(dateFormat, Cultures.German);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace Elternbeirat.Web.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Marks the current response as HTTP 503 when the content source is down.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Several components handle a <see cref="PocketBase.PocketBaseUnavailableException"/>
|
||||
/// the same way: the site works but PocketBase does not, so the response is a
|
||||
/// 503 and the component renders a "temporarily unavailable" note instead of
|
||||
/// empty content that would read as 200 "there is nothing here". This puts the
|
||||
/// status-setting in one place so those components do not each repeat it.
|
||||
/// </remarks>
|
||||
internal static class SourceUnavailable
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the response status to 503 Service Unavailable, if there is a
|
||||
/// response to set it on.
|
||||
/// </summary>
|
||||
/// <param name="context">
|
||||
/// The current HTTP context, or <see langword="null"/> when the component
|
||||
/// renders outside a request (in which case there is nothing to do).
|
||||
/// </param>
|
||||
public static void SetStatus(HttpContext? context)
|
||||
{
|
||||
if (context is not null)
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user