tgstation-server 6.12.0
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;
11
12using Serilog.Context;
13
20
22{
27 {
31 internal static bool LogSwarmIdentifier { get; set; }
32
37 public static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
38 {
39 ArgumentNullException.ThrowIfNull(applicationBuilder);
40
41 applicationBuilder.Use(async (context, next) =>
42 {
43 var logger = GetLogger(context);
44 try
45 {
46 await next();
47 }
48 catch (DbUpdateException e)
49 {
50 if (e.InnerException is OperationCanceledException)
51 {
52 logger.LogTrace(e, "Rethrowing DbUpdateException as OperationCanceledException");
53 throw e.InnerException;
54 }
55
56 logger.LogDebug(e, "Database conflict!");
57 await new ConflictObjectResult(new ErrorMessageResponse(ErrorCode.DatabaseIntegrityConflict)
58 {
59 AdditionalData = String.Format(CultureInfo.InvariantCulture, (e.InnerException ?? e).Message),
60 }).ExecuteResultAsync(new ActionContext
61 {
62 HttpContext = context,
63 });
64 }
65 });
66 }
67
72 public static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
73 {
74 ArgumentNullException.ThrowIfNull(applicationBuilder);
75 applicationBuilder.Use(async (context, next) =>
76 {
77 var logger = GetLogger(context);
78 try
79 {
80 await next();
81 }
82 catch (OperationCanceledException ex)
83 {
84 logger.LogDebug(ex, "Request cancelled!");
85 }
86 });
87 }
88
93 public static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
94 {
95 ArgumentNullException.ThrowIfNull(applicationBuilder);
96
97 applicationBuilder.Use(async (context, next) =>
98 {
99 var logger = GetLogger(context);
100 try
101 {
102 await next();
103 }
104 catch (Exception e)
105 {
106 logger.LogError(e, "Failed request!");
107 await new JsonResult(
108 new ErrorMessageResponse(ErrorCode.InternalServerError)
109 {
110 AdditionalData = e.ToString(),
111 })
112 {
113 StatusCode = (int)HttpStatusCode.InternalServerError,
114 }
115 .ExecuteResultAsync(new ActionContext
116 {
117 HttpContext = context,
118 });
119 }
120 });
121 }
122
127 public static void UseApiCompatibility(this IApplicationBuilder applicationBuilder)
128 {
129 ArgumentNullException.ThrowIfNull(applicationBuilder);
130
131 applicationBuilder.Use(async (context, next) =>
132 {
133 var apiHeadersProvider = context.RequestServices.GetRequiredService<IApiHeadersProvider>();
134 if (apiHeadersProvider.ApiHeaders?.Compatible(
135 Version.Parse(
137 {
138 await new BadRequestObjectResult(
139 new ErrorMessageResponse(ErrorCode.ApiMismatch))
140 .ExecuteResultAsync(new ActionContext
141 {
142 HttpContext = context,
143 });
144 return;
145 }
146
147 await next();
148 });
149 }
150
156 public static void UseServerBranding(this IApplicationBuilder applicationBuilder, IAssemblyInformationProvider assemblyInformationProvider)
157 {
158 ArgumentNullException.ThrowIfNull(applicationBuilder);
159 ArgumentNullException.ThrowIfNull(assemblyInformationProvider);
160
161 applicationBuilder.Use((context, next) =>
162 {
163 context.Response.Headers.Add("X-Powered-By", assemblyInformationProvider.VersionPrefix);
164 return next();
165 });
166 }
167
173 public static void UseDisabledNginxProxyBuffering(this IApplicationBuilder applicationBuilder)
174 {
175 ArgumentNullException.ThrowIfNull(applicationBuilder);
176
177 // https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-buffering
178 applicationBuilder.Use((context, next) =>
179 {
180 context.Response.Headers.Add("X-Accel-Buffering", "no");
181 return next();
182 });
183 }
184
190 public static void UseAdditionalRequestLoggingContext(this IApplicationBuilder applicationBuilder, SwarmConfiguration swarmConfiguration)
191 {
192 ArgumentNullException.ThrowIfNull(applicationBuilder);
193 ArgumentNullException.ThrowIfNull(swarmConfiguration);
194
195 if (LogSwarmIdentifier && swarmConfiguration.Identifier != null)
196 applicationBuilder.Use(async (context, next) =>
197 {
198 using (LogContext.PushProperty(SerilogContextHelper.SwarmIdentifierContextProperty, swarmConfiguration.Identifier))
199 await next();
200 });
201 }
202
208 static ILogger GetLogger(HttpContext httpContext) => httpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(typeof(ApplicationBuilderExtensions));
209 }
210}
string? Identifier
The server's identifier.
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 UseDisabledNginxProxyBuffering(this IApplicationBuilder applicationBuilder)
Add the X-Accel-Buffering response header.
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.
static void UseApiCompatibility(this IApplicationBuilder applicationBuilder)
Check that the API version is the current major version if it's present in the headers.
Attribute for bringing in the master versions list from MSBuild that aren't embedded into assemblies ...
string RawGraphQLVersion
The Version string of the TGS GraphQL API.
static MasterVersionsAttribute Instance
Return the Assembly's instance of the MasterVersionsAttribute.
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:12