mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-29 16:11:05 +01:00
Remove developer exception page in production
- Replace it with an ErrorMessage payload - Adjust the client to account for this
This commit is contained in:
@@ -112,7 +112,11 @@ namespace Tgstation.Server.Client
|
||||
throw new MethodNotSupportedException();
|
||||
case HttpStatusCode.InternalServerError:
|
||||
// response json is html
|
||||
throw new ServerErrorException(json);
|
||||
throw new ServerErrorException(errorMessage ?? new ErrorMessage
|
||||
{
|
||||
Message = "An internal server error occurred!",
|
||||
SeverApiVersion = null
|
||||
}, response.StatusCode);
|
||||
case (HttpStatusCode)429:
|
||||
// rate limited
|
||||
response.Headers.TryGetValues("Retry-After", out var values);
|
||||
|
||||
@@ -9,27 +9,18 @@ namespace Tgstation.Server.Client
|
||||
/// </summary>
|
||||
public sealed class ServerErrorException : ClientException
|
||||
{
|
||||
/// <summary>
|
||||
/// The raw HTML of the error
|
||||
/// </summary>
|
||||
public string Html { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct an <see cref="ServerErrorException"/>
|
||||
/// </summary>
|
||||
public ServerErrorException() { }
|
||||
|
||||
/// <summary>
|
||||
/// Construct an <see cref="ServerErrorException"/> with <paramref name="html"/>
|
||||
/// Construct an <see cref="ServerErrorException"/> with a given <paramref name="errorMessage"/>
|
||||
/// </summary>
|
||||
/// <param name="html">The raw HTML response of the <see cref="ServerErrorException"/></param>
|
||||
public ServerErrorException(string html) : base(new ErrorMessage
|
||||
/// <param name="errorMessage">The <see cref="ErrorMessage"/> for the <see cref="ClientException"/></param>
|
||||
/// <param name="statusCode">The <see cref="HttpStatusCode"/> for the <see cref="ClientException"/></param>
|
||||
public ServerErrorException(ErrorMessage errorMessage, HttpStatusCode statusCode) : base(errorMessage, statusCode)
|
||||
{
|
||||
Message = "An internal server error occurred!",
|
||||
SeverApiVersion = null
|
||||
}, HttpStatusCode.InternalServerError)
|
||||
{
|
||||
Html = html;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -351,9 +351,12 @@ namespace Tgstation.Server.Host.Core
|
||||
ChangeToken.OnChange(configuration.GetReloadToken, () => serverControl.Restart());
|
||||
|
||||
// setup the HTTP request pipeline
|
||||
// Final point where we wrap exceptions in a 500 (ErrorMessage) response
|
||||
applicationBuilder.UseServerErrorHandling();
|
||||
|
||||
// should anything after this throw an exception, catch it and display a detailed html page
|
||||
applicationBuilder.UseDeveloperExceptionPage(); // it is not worth it to limit this, you should only ever get it if you're an authorized user
|
||||
if(hostingEnvironment.IsDevelopment())
|
||||
applicationBuilder.UseDeveloperExceptionPage(); // it is not worth it to limit this, you should only ever get it if you're an authorized user
|
||||
|
||||
// suppress OperationCancelledExceptions, they are just aborted HTTP requests
|
||||
applicationBuilder.UseCancelledRequestSuppression();
|
||||
|
||||
@@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Core
|
||||
@@ -69,5 +70,39 @@ namespace Tgstation.Server.Host.Core
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suppress all in flight exceptions with error 500.
|
||||
/// </summary>
|
||||
/// <param name="applicationBuilder">The <see cref="IApplicationBuilder"/> to configure</param>
|
||||
public static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
|
||||
{
|
||||
if (applicationBuilder == null)
|
||||
throw new ArgumentNullException(nameof(applicationBuilder));
|
||||
applicationBuilder.Use(async (context, next) =>
|
||||
{
|
||||
var logger = GetLogger(context);
|
||||
try
|
||||
{
|
||||
await next().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError("Failed request: {0}", e);
|
||||
await new ObjectResult(
|
||||
new ErrorMessage
|
||||
{
|
||||
Message = $"A unhandled exception has occurred: {e}"
|
||||
})
|
||||
{
|
||||
StatusCode = (int)HttpStatusCode.InternalServerError
|
||||
}
|
||||
.ExecuteResultAsync(new ActionContext
|
||||
{
|
||||
HttpContext = context
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user