tgstation-server 5.12.1
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 if (applicationBuilder == null)
41 throw new ArgumentNullException(nameof(applicationBuilder));
42
43 applicationBuilder.Use(async (context, next) =>
44 {
45 var logger = GetLogger(context);
46 try
47 {
48 await next();
49 }
50 catch (DbUpdateException e)
51 {
52 if (e.InnerException is OperationCanceledException)
53 {
54 logger.LogTrace(e, "Rethrowing DbUpdateException as OperationCanceledException");
55 throw e.InnerException;
56 }
57
58 logger.LogDebug(e, "Database conflict!");
59 await new ConflictObjectResult(new ErrorMessageResponse(ErrorCode.DatabaseIntegrityConflict)
60 {
61 AdditionalData = String.Format(CultureInfo.InvariantCulture, (e.InnerException ?? e).Message),
62 }).ExecuteResultAsync(new ActionContext
63 {
64 HttpContext = context,
65 });
66 }
67 });
68 }
69
74 public static void UseDisabledClientCache(this IApplicationBuilder applicationBuilder)
75 {
76 if (applicationBuilder == null)
77 throw new ArgumentNullException(nameof(applicationBuilder));
78 applicationBuilder.Use(async (context, next) =>
79 {
80 context.Response.Headers.Add(HeaderNames.CacheControl, new StringValues("no-cache"));
81 await next();
82 });
83 }
84
89 public static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
90 {
91 if (applicationBuilder == null)
92 throw new ArgumentNullException(nameof(applicationBuilder));
93 applicationBuilder.Use(async (context, next) =>
94 {
95 var logger = GetLogger(context);
96 try
97 {
98 await next();
99 }
100 catch (OperationCanceledException ex)
101 {
102 logger.LogDebug(ex, "Request cancelled!");
103 }
104 });
105 }
106
111 public static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
112 {
113 if (applicationBuilder == null)
114 throw new ArgumentNullException(nameof(applicationBuilder));
115
116 applicationBuilder.Use(async (context, next) =>
117 {
118 var logger = GetLogger(context);
119 try
120 {
121 await next();
122 }
123 catch (Exception e)
124 {
125 logger.LogError(e, "Failed request!");
126 await new JsonResult(
127 new ErrorMessageResponse(ErrorCode.InternalServerError)
128 {
129 AdditionalData = e.ToString(),
130 })
131 {
132 StatusCode = (int)HttpStatusCode.InternalServerError,
133 }
134 .ExecuteResultAsync(new ActionContext
135 {
136 HttpContext = context,
137 });
138 }
139 });
140 }
141
147 public static void UseServerBranding(this IApplicationBuilder applicationBuilder, IAssemblyInformationProvider assemblyInformationProvider)
148 {
149 if (applicationBuilder == null)
150 throw new ArgumentNullException(nameof(applicationBuilder));
151 if (assemblyInformationProvider == null)
152 throw new ArgumentNullException(nameof(assemblyInformationProvider));
153
154 applicationBuilder.Use(async (context, next) =>
155 {
156 context.Response.Headers.Add("X-Powered-By", assemblyInformationProvider.VersionPrefix);
157 await next();
158 });
159 }
160
166 public static void UseAdditionalRequestLoggingContext(this IApplicationBuilder applicationBuilder, SwarmConfiguration swarmConfiguration)
167 {
168 if (applicationBuilder == null)
169 throw new ArgumentNullException(nameof(applicationBuilder));
170 if (swarmConfiguration == null)
171 throw new ArgumentNullException(nameof(swarmConfiguration));
172
173 if (LogSwarmIdentifier && swarmConfiguration.Identifier != null)
174 applicationBuilder.Use(async (context, next) =>
175 {
176 using (LogContext.PushProperty(SerilogContextHelper.SwarmIdentifierContextProperty, swarmConfiguration.Identifier))
177 await next();
178 });
179 }
180
186 static ILogger GetLogger(HttpContext httpContext) => httpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(typeof(ApplicationBuilderExtensions));
187 }
188}
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