tgstation-server 5.12.7
The /tg/station 13 server suite
Loading...
Searching...
No Matches
ApplicationBuilderExtensions.cs
Go to the documentation of this file.
1using System;
2using System.Globalization;
3using System.Net;
4
5using Microsoft.AspNetCore.Builder;
6using Microsoft.AspNetCore.Http;
7using Microsoft.AspNetCore.Mvc;
8using Microsoft.EntityFrameworkCore;
9using Microsoft.Extensions.DependencyInjection;
10using Microsoft.Extensions.Logging;
11using Microsoft.Extensions.Primitives;
12using Microsoft.Net.Http.Headers;
13
14using Serilog.Context;
15
21
23{
28 {
32 internal static bool LogSwarmIdentifier { get; set; }
33
38 public static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
39 {
40 ArgumentNullException.ThrowIfNull(applicationBuilder);
41
42 applicationBuilder.Use(async (context, next) =>
43 {
44 var logger = GetLogger(context);
45 try
46 {
47 await next();
48 }
49 catch (DbUpdateException e)
50 {
51 if (e.InnerException is OperationCanceledException)
52 {
53 logger.LogTrace(e, "Rethrowing DbUpdateException as OperationCanceledException");
54 throw e.InnerException;
55 }
56
57 logger.LogDebug(e, "Database conflict!");
58 await new ConflictObjectResult(new ErrorMessageResponse(ErrorCode.DatabaseIntegrityConflict)
59 {
60 AdditionalData = String.Format(CultureInfo.InvariantCulture, (e.InnerException ?? e).Message),
61 }).ExecuteResultAsync(new ActionContext
62 {
63 HttpContext = context,
64 });
65 }
66 });
67 }
68
73 public static void UseDisabledClientCache(this IApplicationBuilder applicationBuilder)
74 {
75 ArgumentNullException.ThrowIfNull(applicationBuilder);
76 applicationBuilder.Use(async (context, next) =>
77 {
78 context.Response.Headers.Add(HeaderNames.CacheControl, new StringValues("no-cache"));
79 await next();
80 });
81 }
82
87 public static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
88 {
89 ArgumentNullException.ThrowIfNull(applicationBuilder);
90 applicationBuilder.Use(async (context, next) =>
91 {
92 var logger = GetLogger(context);
93 try
94 {
95 await next();
96 }
97 catch (OperationCanceledException ex)
98 {
99 logger.LogDebug(ex, "Request cancelled!");
100 }
101 });
102 }
103
108 public static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
109 {
110 ArgumentNullException.ThrowIfNull(applicationBuilder);
111
112 applicationBuilder.Use(async (context, next) =>
113 {
114 var logger = GetLogger(context);
115 try
116 {
117 await next();
118 }
119 catch (Exception e)
120 {
121 logger.LogError(e, "Failed request!");
122 await new JsonResult(
123 new ErrorMessageResponse(ErrorCode.InternalServerError)
124 {
125 AdditionalData = e.ToString(),
126 })
127 {
128 StatusCode = (int)HttpStatusCode.InternalServerError,
129 }
130 .ExecuteResultAsync(new ActionContext
131 {
132 HttpContext = context,
133 });
134 }
135 });
136 }
137
143 public static void UseServerBranding(this IApplicationBuilder applicationBuilder, IAssemblyInformationProvider assemblyInformationProvider)
144 {
145 ArgumentNullException.ThrowIfNull(applicationBuilder);
146 ArgumentNullException.ThrowIfNull(assemblyInformationProvider);
147
148 applicationBuilder.Use(async (context, next) =>
149 {
150 context.Response.Headers.Add("X-Powered-By", assemblyInformationProvider.VersionPrefix);
151 await next();
152 });
153 }
154
160 public static void UseAdditionalRequestLoggingContext(this IApplicationBuilder applicationBuilder, SwarmConfiguration swarmConfiguration)
161 {
162 ArgumentNullException.ThrowIfNull(applicationBuilder);
163 ArgumentNullException.ThrowIfNull(swarmConfiguration);
164
165 if (LogSwarmIdentifier && swarmConfiguration.Identifier != null)
166 applicationBuilder.Use(async (context, next) =>
167 {
168 using (LogContext.PushProperty(SerilogContextHelper.SwarmIdentifierContextProperty, swarmConfiguration.Identifier))
169 await next();
170 });
171 }
172
178 static ILogger GetLogger(HttpContext httpContext) => httpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(typeof(ApplicationBuilderExtensions));
179 }
180}
string? Identifier
The server's identifier.
Definition: SwarmServer.cs:21
Represents an error message returned by the server.
Configuration for the server swarm system.
static void UseServerBranding(this IApplicationBuilder applicationBuilder, IAssemblyInformationProvider assemblyInformationProvider)
Add the X-Powered-By response header.
static void UseDisabledClientCache(this IApplicationBuilder applicationBuilder)
Suppress any client side caching of API calls.
static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
Suppress all in flight Exceptions for the request with error 500.
static ILogger GetLogger(HttpContext httpContext)
Gets a ILogger from a given httpContext .
static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
Return a ConflictObjectResult for DbUpdateExceptions.
static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
Suppress global::System.Threading.Tasks.TaskCanceledException warnings when a user aborts a request.
static void UseAdditionalRequestLoggingContext(this IApplicationBuilder applicationBuilder, SwarmConfiguration swarmConfiguration)
Adds additional global LogContext to the request pipeline.
Helpers for manipulating the Serilog.Context.LogContext.
const string SwarmIdentifierContextProperty
The Serilog.Context.LogContext property name for Api.Models.Internal.SwarmServer.Identifiers.
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
Definition: ErrorCode.cs:11