Nice little directory browser :D
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Error page!

+82 -9
+2 -1
Components/Layout/MainLayout.razor
··· 16 16 *@ 17 17 18 18 @inherits LayoutComponentBase 19 + @inject IHttpContextAccessor context 19 20 20 21 <!DOCTYPE html> 21 22 <html lang="en"> ··· 35 36 @* blank placeholder title, overriden (usually) in @Body *@ 36 37 <AppTitle></AppTitle> 37 38 </head> 38 - <body> 39 + <body class="@(context.HttpContext.Response.StatusCode >= 400 ? "from-red-400! to-red-500!" : null)"> 39 40 @Body 40 41 </body> 41 42 </html>
+18 -3
Components/Pages/NotFound.razor
··· 16 16 *@ 17 17 18 18 @page "/not-found" 19 - @layout MainLayout 19 + @inject IHttpContextAccessor context 20 20 21 - <h3>Not Found</h3> 22 - <p>Sorry, the content you are looking for does not exist.</p> 21 + <AppTitle>OOPSIE WOOPSIE!!</AppTitle> 22 + 23 + <div class="n-box text-center gap-2"> 24 + <h1> 25 + <span class="text-6xl">@context.HttpContext.Response.StatusCode</span> 26 + <br /> 27 + <span class="text-4xl"> 28 + @Microsoft.AspNetCore.WebUtilities.ReasonPhrases.GetReasonPhrase( 29 + context.HttpContext.Response.StatusCode 30 + ) 31 + </span> 32 + </h1> 33 + <hr/> 34 + OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The code monkeys at our headquarters are working VEWY HAWD to fix this! 35 + <hr/> 36 + <a href="/" class="clickable p-4">go home......</a> 37 + </div>
+31 -5
Program.cs
··· 17 17 18 18 using System.IO.Compression; 19 19 using System.Text; 20 + using Microsoft.AspNetCore.Diagnostics; 21 + using Microsoft.AspNetCore.Http.Features; 20 22 using Utatane.Components; 21 23 using Microsoft.AspNetCore.ResponseCompression; 22 24 using Microsoft.AspNetCore.Rewrite; ··· 44 46 options.Level = CompressionLevel.SmallestSize; 45 47 }); 46 48 49 + builder.Services.AddHttpContextAccessor(); 50 + 47 51 var app = builder.Build(); 48 52 49 53 // Configure the HTTP request pipeline. 50 54 if (!app.Environment.IsDevelopment()) { 51 55 app.UseExceptionHandler("/Error", createScopeForErrors: true); 52 - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 53 - app.UseHsts(); 54 56 } 55 57 56 58 app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true); 57 - app.UseHttpsRedirection(); 58 59 59 60 app.UseAntiforgery(); 60 61 app.UseResponseCompression(); ··· 95 96 // check paths exist 96 97 app.Use(async (context, next) => { 97 98 if ( 98 - context.Request.Path.StartsWithSegments("/api/files") 99 + // if reexecuting for an error, let someone else handle that 100 + context.Features.Get<IStatusCodeReExecuteFeature>() != null 101 + // let api/ handle that 102 + || context.Request.Path.StartsWithSegments("/api/files") 103 + // let our static file error handler do that 99 104 || context.Request.Path.StartsWithSegments("/.nhnd") 100 105 ) { 101 106 await next(context); ··· 105 110 var resolved = Utils.VerifyPath(context.Request.Path); 106 111 107 112 if (resolved.IsFailed) { 108 - await Results.NotFound().ExecuteAsync(context); 113 + context.Response.StatusCode = StatusCodes.Status404NotFound; 114 + 115 + var original = context.Request.Path; 116 + 117 + var routeFeature = context.Features.Get<IRouteValuesFeature>(); 118 + routeFeature?.RouteValues = new RouteValueDictionary(); 119 + context.SetEndpoint(null); 120 + 121 + await next(context); 122 + 123 + context.Request.Path = original; 109 124 return; 110 125 } 111 126 ··· 136 151 app.UseStaticFiles(new StaticFileOptions { 137 152 RequestPath = "/.nhnd" 138 153 }); 154 + 155 + // if the static handler didn't pick this up, then 404 156 + app.Use(async (context, next) => { 157 + if (context.Request.Path.StartsWithSegments("/.nhnd")) { 158 + context.Response.StatusCode = StatusCodes.Status404NotFound; 159 + return; 160 + } 161 + 162 + await next(context); 163 + }); 164 + 139 165 app.MapRazorComponents<App>(); 140 166 141 167 app.Run();
+31
public/style.css
··· 10 10 Consolas, "Liberation Mono", "Courier New", monospace, 11 11 "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", 12 12 "Noto Color Emoji"; 13 + --color-red-400: oklch(70.4% 0.191 22.216); 14 + --color-red-500: oklch(63.7% 0.237 25.331); 13 15 --color-green-100: oklch(96.2% 0.044 156.743); 14 16 --color-green-200: oklch(92.5% 0.084 155.995); 15 17 --color-green-300: oklch(87.1% 0.15 154.449); ··· 30 32 --color-white: #fff; 31 33 --spacing: 0.25rem; 32 34 --container-6xl: 72rem; 35 + --text-4xl: 2.25rem; 36 + --text-4xl--line-height: calc(2.5 / 2.25); 37 + --text-6xl: 3.75rem; 38 + --text-6xl--line-height: 1; 33 39 --font-weight-bold: 700; 34 40 --radius-sm: 0.25rem; 35 41 --drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1); ··· 247 253 .flex-row { 248 254 flex-direction: row; 249 255 } 256 + .gap-2 { 257 + gap: calc(var(--spacing) * 2); 258 + } 250 259 .border-black { 251 260 border-color: var(--color-black); 252 261 } 262 + .from-red-400\! { 263 + --tw-gradient-from: var(--color-red-400) !important; 264 + --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)) !important; 265 + } 266 + .to-red-500\! { 267 + --tw-gradient-to: var(--color-red-500) !important; 268 + --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)) !important; 269 + } 270 + .p-4 { 271 + padding: calc(var(--spacing) * 4); 272 + } 273 + .text-center { 274 + text-align: center; 275 + } 253 276 .\[vertical-align\:sub\] { 254 277 vertical-align: sub; 255 278 } 256 279 .font-mono { 257 280 font-family: var(--font-mono); 281 + } 282 + .text-4xl { 283 + font-size: var(--text-4xl); 284 + line-height: var(--tw-leading, var(--text-4xl--line-height)); 285 + } 286 + .text-6xl { 287 + font-size: var(--text-6xl); 288 + line-height: var(--tw-leading, var(--text-6xl--line-height)); 258 289 } 259 290 .text-stone-500 { 260 291 color: var(--color-stone-500);