feat: add real http status pages
@ -1,34 +0,0 @@
|
|||||||
@page "/error/{code:int?}"
|
|
||||||
@model OliverBooth.Pages.ErrorModel
|
|
||||||
@{
|
|
||||||
Layout = "_MinimalLayout";
|
|
||||||
ViewData["Title"] = "Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h2 class="text-danger">
|
|
||||||
@switch (Model.HttpStatusCode)
|
|
||||||
{
|
|
||||||
case 403:
|
|
||||||
<span>403 Forbidden</span>
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 404:
|
|
||||||
<span>404 Page not found</span>
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 500:
|
|
||||||
<span>Internal server error</span>
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
<span>Something went wrong</span>
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
@if (Model.ShowRequestId)
|
|
||||||
{
|
|
||||||
<p>
|
|
||||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
|
||||||
</p>
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace OliverBooth.Pages;
|
|
||||||
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
||||||
[IgnoreAntiforgeryToken]
|
|
||||||
public class ErrorModel : PageModel
|
|
||||||
{
|
|
||||||
public string? RequestId { get; set; }
|
|
||||||
|
|
||||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
|
||||||
|
|
||||||
public int HttpStatusCode { get; private set; }
|
|
||||||
|
|
||||||
public IActionResult OnGet(int? code = null)
|
|
||||||
{
|
|
||||||
HttpStatusCode = code ?? HttpContext.Response.StatusCode;
|
|
||||||
if (HttpStatusCode == 200)
|
|
||||||
{
|
|
||||||
return RedirectToPage("/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
17
OliverBooth/Pages/Error/BadRequest.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@page "/error/400"
|
||||||
|
<article>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">400 Bad Request</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">Received invalid request message. Check your request and try again.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="align-self-stretch">
|
||||||
|
<img class="img-fluid" src="~/img/error/400-bad-request.png">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
15
OliverBooth/Pages/Error/Forbidden.cshtml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@page "/error/403"
|
||||||
|
<article>
|
||||||
|
<div class="text-center d-flex flex-column align-items-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">403 Forbidden</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<img class="img-fluid" src="~/img/error/403-forbidden.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">Access to the requested page is forbidden.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
17
OliverBooth/Pages/Error/GatewayTimeout.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@page "/error/504"
|
||||||
|
<article>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="align-self-stretch">
|
||||||
|
<img class="img-fluid" src="~/img/error/504-gateway-timeout.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">504 Gateway Timeout</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">The server is slacking. Give it more coffee.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
17
OliverBooth/Pages/Error/Gone.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@page "/error/400"
|
||||||
|
<article>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">410 Gone</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">The requested page has mysteriously disappeared.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="align-self-stretch">
|
||||||
|
<img class="img-fluid" src="~/img/error/410-gone.png">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
17
OliverBooth/Pages/Error/ImATeapot.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@page "/error/418"
|
||||||
|
<article>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="align-self-stretch">
|
||||||
|
<img class="img-fluid" src="~/img/error/418-im-a-teapot.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">418 I'm A Teapot</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">No coffee available. I am only capable of brewing tea.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
17
OliverBooth/Pages/Error/InternalServerError.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@page "/error/500"
|
||||||
|
<article>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="align-self-stretch">
|
||||||
|
<img class="img-fluid" src="~/img/error/500-internal-server-error.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">500 Internal Server Error</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">This is my fault, not yours.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
17
OliverBooth/Pages/Error/NotFound.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@page "/error/404"
|
||||||
|
<article>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="align-self-stretch">
|
||||||
|
<img class="img-fluid" src="~/img/error/404-not-found.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">404 Not Found</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">The requested page could not be found.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
17
OliverBooth/Pages/Error/ServiceUnavailable.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@page "/error/503"
|
||||||
|
<article>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">503 Service Unavailable</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">The server is currently unable to process your request. Please try again later.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="align-self-stretch">
|
||||||
|
<img class="img-fluid" src="~/img/error/503-service-unavailable.png">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
17
OliverBooth/Pages/Error/TooManyRequests.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@page "/error/429"
|
||||||
|
<article>
|
||||||
|
<div class="d-flex align-items-center justify-content-center">
|
||||||
|
<div class="d-flex flex-column align-items-center justify-content-center">
|
||||||
|
<div class="p-2">
|
||||||
|
<h1 class="text-center">429 Too Many Requests</h1>
|
||||||
|
</div>
|
||||||
|
<div class="p-2">
|
||||||
|
<p class="text-center">You are being rate limited.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="align-self-stretch">
|
||||||
|
<img class="img-fluid" src="~/img/error/429-too-many-requests.png">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
@ -81,9 +81,78 @@ if (builder.Environment.IsProduction())
|
|||||||
|
|
||||||
WebApplication app = builder.Build();
|
WebApplication app = builder.Build();
|
||||||
|
|
||||||
|
app.Use(async (ctx, next) =>
|
||||||
|
{
|
||||||
|
await next();
|
||||||
|
|
||||||
|
if (ctx.Response.HasStarted)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? originalPath = ctx.Request.Path.Value;
|
||||||
|
ctx.Items["originalPath"] = originalPath;
|
||||||
|
|
||||||
|
bool matchedErrorPage = false;
|
||||||
|
|
||||||
|
switch (ctx.Response.StatusCode)
|
||||||
|
{
|
||||||
|
case 400:
|
||||||
|
ctx.Request.Path = "/error/401";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 403:
|
||||||
|
ctx.Request.Path = "/error/403";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 404:
|
||||||
|
ctx.Request.Path = "/error/404";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 410:
|
||||||
|
ctx.Request.Path = "/error/410";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 418:
|
||||||
|
ctx.Request.Path = "/error/418";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 429:
|
||||||
|
ctx.Request.Path = "/error/429";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 500:
|
||||||
|
ctx.Request.Path = "/error/500";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 503:
|
||||||
|
ctx.Request.Path = "/error/503";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 504:
|
||||||
|
ctx.Request.Path = "/error/504";
|
||||||
|
matchedErrorPage = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchedErrorPage)
|
||||||
|
{
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app.UseStatusCodePagesWithReExecute("/error/{0}");
|
||||||
|
|
||||||
if (!app.Environment.IsDevelopment())
|
if (!app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseExceptionHandler("/Error");
|
app.UseExceptionHandler("/error/500");
|
||||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
}
|
}
|
||||||
|
BIN
src/img/error/400-bad-request.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
src/img/error/403-forbidden.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
src/img/error/404-not-found.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
src/img/error/410-gone.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
src/img/error/418-im-a-teapot.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
src/img/error/429-too-many-requests.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
src/img/error/500-internal-server-error.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/img/error/503-service-unavailable.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/img/error/504-gateway-timeout.png
Normal file
After Width: | Height: | Size: 27 KiB |