Control panel is now hosted at /app

- Fixed browser detection redirect
- Used managed routing to redirect all requests to index.html if there is no matching static file
This commit is contained in:
Jordan Brown
2020-10-12 12:22:24 -04:00
parent 8bdfc57192
commit c8495f4dec
5 changed files with 72 additions and 6 deletions
@@ -1,5 +1,7 @@
{
"private": true,
"_comment1": "This sets PUBLIC_URL during the build",
"homepage": "/app/",
"dependencies": {
"react-dom": "^16.13.1",
"tgstation-server-control-panel": "0.4.0"
@@ -7,7 +9,7 @@
"optionalDependencies": {
"fsevents": "1.2.9"
},
"_comment": "fsevent@1.2.9 is locked in to prevent broken builds on windows for v1.2.11",
"_comment2": "fsevent@1.2.9 is locked in to prevent broken builds on windows for v1.2.11",
"scripts": {
"msbuild": "npm run clean && react-scripts build && cp-cli node_modules/tgstation-server-control-panel/build/public/ build/ && rimraf ../wwwroot && move-cli build ../wwwroot",
"clean": "rimraf build"
@@ -5,6 +5,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<base href="%PUBLIC_URL%/">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
@@ -0,0 +1,54 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using System;
using System.Net.Mime;
using Tgstation.Server.Host.Core;
namespace Tgstation.Server.Host.Controllers
{
/// <summary>
/// Controller for the web control panel.
/// </summary>
[Route(Application.ControlPanelRoute)]
public class ControlPanelController : Controller
{
/// <summary>
/// The <see cref="IWebHostEnvironment"/> for the <see cref="ControlPanelController"/>.
/// </summary>
readonly IWebHostEnvironment hostEnvironment;
/// <summary>
/// Initializes a new instance of the <see cref="ControlPanelController"/> <see langword="class"/>.
/// </summary>
/// <param name="hostEnvironment">The value of <see cref="hostEnvironment"/>.</param>
public ControlPanelController(IWebHostEnvironment hostEnvironment)
{
this.hostEnvironment = hostEnvironment ?? throw new ArgumentNullException(nameof(hostEnvironment));
}
/// <summary>
/// Handle a GET request to the control panel route. Route to static files if they exist, otherwise index.html.
/// </summary>
/// <param name="appRoute">The value of the route.</param>
/// <returns>The <see cref="VirtualFileResult"/> to use.</returns>
[Route("{**appRoute}")]
[HttpGet]
public VirtualFileResult Get([FromRoute] string appRoute)
{
var fileInfo = hostEnvironment.WebRootFileProvider.GetFileInfo(appRoute);
if (fileInfo.Exists)
{
var contentTypeProvider = new FileExtensionContentTypeProvider();
if (!contentTypeProvider.TryGetContentType(fileInfo.Name, out var contentType))
{
contentType = "application/octet-stream";
}
return File(appRoute, contentType);
}
return File("index.html", MediaTypeNames.Text.Html);
}
}
}
@@ -7,7 +7,6 @@ using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using System;
using System.Linq;
using System.Net.Mime;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
@@ -100,7 +99,7 @@ namespace Tgstation.Server.Host.Controllers
authenticationContextFactory,
logger,
(browserResolver ?? throw new ArgumentNullException(nameof(browserResolver))).Browser.Type != BrowserType.Generic
&& (controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions))).Enable)
&& !(controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions))).Enable)
{
this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
@@ -140,8 +139,8 @@ namespace Tgstation.Server.Host.Controllers
// if we are using a browser and the control panel, soft redirect to the app page
if (controlPanelConfiguration.Enable && browserResolver.Browser.Type != BrowserType.Generic)
{
Logger.LogDebug("Unauthorized browser request (User-Agent: \"{0}\"), loading control panel...", browserResolver.UserAgent);
return File("~/index.html", MediaTypeNames.Text.Html);
Logger.LogDebug("Unauthorized browser request (User-Agent: \"{0}\"), redirecting to control panel...", browserResolver.UserAgent);
return Redirect(Application.ControlPanelRoute);
}
return ApiHeaders == null ? HeadersIssue() : Unauthorized();
+11 -1
View File
@@ -47,6 +47,11 @@ namespace Tgstation.Server.Host.Core
#pragma warning disable CA1506
sealed class Application : SetupApplication
{
/// <summary>
/// Route to the web control panel.
/// </summary>
public const string ControlPanelRoute = "/app";
/// <summary>
/// The <see cref="IWebHostEnvironment"/> for the <see cref="Application"/>.
/// </summary>
@@ -428,7 +433,12 @@ namespace Tgstation.Server.Host.Core
if (controlPanelConfiguration.Enable)
{
logger.LogWarning("Web control panel enabled. This is a highly WIP feature!");
applicationBuilder.UseStaticFiles();
applicationBuilder.UseFileServer(new FileServerOptions
{
RequestPath = ControlPanelRoute,
EnableDefaultFiles = true,
EnableDirectoryBrowsing = false
});
}
else
logger.LogDebug("Web control panel disabled!");