mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Webserver - Removed '/api/' part from URLs
Webserver - Added the ability to register custom EmbedIO modules Webserver - Ensure custom controllers/modules are always cleaned up on plugin feature disable
This commit is contained in:
parent
e32b181d9f
commit
ed704a165c
@ -55,7 +55,8 @@ namespace Artemis.Core.Services
|
||||
DataModelJsonPluginEndPoint<T> AddDataModelJsonEndPoint<T>(Module<T> module, string endPointName) where T : DataModel;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new endpoint that directly maps received JSON to the data model of the provided <paramref name="profileModule" />.
|
||||
/// Adds a new endpoint that directly maps received JSON to the data model of the provided
|
||||
/// <paramref name="profileModule" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data model type of the module</typeparam>
|
||||
/// <param name="profileModule">The module whose datamodel to apply the received JSON to</param>
|
||||
@ -64,7 +65,8 @@ namespace Artemis.Core.Services
|
||||
DataModelJsonPluginEndPoint<T> AddDataModelJsonEndPoint<T>(ProfileModule<T> profileModule, string endPointName) where T : DataModel;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new endpoint that directly maps received JSON to the data model of the provided <paramref name="dataModelExpansion" />.
|
||||
/// Adds a new endpoint that directly maps received JSON to the data model of the provided
|
||||
/// <paramref name="dataModelExpansion" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data model type of the module</typeparam>
|
||||
/// <param name="dataModelExpansion">The data model expansion whose datamodel to apply the received JSON to</param>
|
||||
@ -114,7 +116,7 @@ namespace Artemis.Core.Services
|
||||
/// Adds a new Web API controller and restarts the web server
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of Web API controller to remove</typeparam>
|
||||
void AddController<T>() where T : WebApiController;
|
||||
void AddController<T>(PluginFeature feature) where T : WebApiController;
|
||||
|
||||
/// <summary>
|
||||
/// Removes an existing Web API controller and restarts the web server
|
||||
@ -122,6 +124,18 @@ namespace Artemis.Core.Services
|
||||
/// <typeparam name="T">The type of Web API controller to remove</typeparam>
|
||||
void RemoveController<T>() where T : WebApiController;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new EmbedIO module and restarts the web server
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of module to add</typeparam>
|
||||
void AddModule<T>(PluginFeature feature) where T : IWebModule;
|
||||
|
||||
/// <summary>
|
||||
/// Removes a EmbedIO module and restarts the web server
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of module to remove</typeparam>
|
||||
void RemoveModule<T>() where T : IWebModule;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the web server has been created and is about to start. This is the ideal place to add your own modules.
|
||||
/// </summary>
|
||||
|
||||
@ -48,13 +48,13 @@ namespace Artemis.Core.Services
|
||||
protected override async Task OnRequestAsync(IHttpContext context)
|
||||
{
|
||||
if (context.Route.SubPath == null)
|
||||
throw HttpException.NotFound();
|
||||
return;
|
||||
|
||||
// Split the sub path
|
||||
string[] pathParts = context.Route.SubPath.Substring(1).Split('/');
|
||||
// Expect a plugin ID and an endpoint
|
||||
if (pathParts == null || pathParts.Length != 2)
|
||||
throw HttpException.BadRequest("Path must contain a plugin ID and endpoint and nothing else.");
|
||||
if (pathParts.Length != 2)
|
||||
return;
|
||||
|
||||
// Find a matching plugin
|
||||
if (!_pluginEndPoints.TryGetValue(pathParts[0], out Dictionary<string, PluginEndPoint>? endPoints))
|
||||
@ -78,7 +78,7 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsFinalHandler => true;
|
||||
public override bool IsFinalHandler => false;
|
||||
|
||||
internal string? ServerUrl { get; set; }
|
||||
|
||||
|
||||
@ -6,9 +6,9 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
internal class WebApiControllerRegistration<T> : WebApiControllerRegistration where T : WebApiController
|
||||
{
|
||||
public WebApiControllerRegistration(IKernel kernel) : base(typeof(T))
|
||||
public WebApiControllerRegistration(PluginFeature feature) : base(feature, typeof(T))
|
||||
{
|
||||
Factory = () => kernel.Get<T>();
|
||||
Factory = () => feature.Plugin.Kernel!.Get<T>();
|
||||
}
|
||||
|
||||
public Func<T> Factory { get; set; }
|
||||
@ -17,12 +17,14 @@ namespace Artemis.Core.Services
|
||||
|
||||
internal abstract class WebApiControllerRegistration
|
||||
{
|
||||
protected WebApiControllerRegistration(Type controllerType)
|
||||
protected WebApiControllerRegistration(PluginFeature feature, Type controllerType)
|
||||
{
|
||||
Feature = feature;
|
||||
ControllerType = controllerType;
|
||||
}
|
||||
|
||||
public abstract object UntypedFactory { get; }
|
||||
public Type ControllerType { get; set; }
|
||||
public PluginFeature Feature { get; }
|
||||
}
|
||||
}
|
||||
20
src/Artemis.Core/Services/WebServer/WebModuleRegistration.cs
Normal file
20
src/Artemis.Core/Services/WebServer/WebModuleRegistration.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using EmbedIO;
|
||||
using Ninject;
|
||||
|
||||
namespace Artemis.Core.Services
|
||||
{
|
||||
internal class WebModuleRegistration
|
||||
{
|
||||
public PluginFeature Feature { get; }
|
||||
public Type WebModuleType { get; }
|
||||
|
||||
public WebModuleRegistration(PluginFeature feature, Type webModuleType)
|
||||
{
|
||||
Feature = feature;
|
||||
WebModuleType = webModuleType;
|
||||
}
|
||||
|
||||
public IWebModule CreateInstance() => (IWebModule) Feature.Plugin.Kernel!.Get(WebModuleType);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core.DataModelExpansions;
|
||||
@ -8,7 +9,6 @@ using Artemis.Core.Modules;
|
||||
using EmbedIO;
|
||||
using EmbedIO.WebApi;
|
||||
using Newtonsoft.Json;
|
||||
using Ninject;
|
||||
using Serilog;
|
||||
|
||||
namespace Artemis.Core.Services
|
||||
@ -16,18 +16,19 @@ namespace Artemis.Core.Services
|
||||
internal class WebServerService : IWebServerService, IDisposable
|
||||
{
|
||||
private readonly List<WebApiControllerRegistration> _controllers;
|
||||
private readonly IKernel _kernel;
|
||||
private readonly List<WebModuleRegistration> _modules;
|
||||
private readonly ILogger _logger;
|
||||
private readonly PluginSetting<int> _webServerPortSetting;
|
||||
|
||||
public WebServerService(IKernel kernel, ILogger logger, ISettingsService settingsService)
|
||||
public WebServerService(ILogger logger, ISettingsService settingsService, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
_kernel = kernel;
|
||||
_logger = logger;
|
||||
_controllers = new List<WebApiControllerRegistration>();
|
||||
_modules = new List<WebModuleRegistration>();
|
||||
|
||||
_webServerPortSetting = settingsService.GetSetting("WebServer.Port", 9696);
|
||||
_webServerPortSetting.SettingChanged += WebServerPortSettingOnSettingChanged;
|
||||
pluginManagementService.PluginFeatureDisabled += PluginManagementServiceOnPluginFeatureDisabled;
|
||||
|
||||
PluginsModule = new PluginsModule("/plugins");
|
||||
StartWebServer();
|
||||
@ -43,12 +44,18 @@ namespace Artemis.Core.Services
|
||||
Server?.Dispose();
|
||||
Server = null;
|
||||
|
||||
WebApiModule apiModule = new("/api/", JsonNetSerializer);
|
||||
WebApiModule apiModule = new("/", JsonNetSerializer);
|
||||
PluginsModule.ServerUrl = $"http://localhost:{_webServerPortSetting.Value}/";
|
||||
WebServer server = new WebServer(o => o.WithUrlPrefix($"http://*:{_webServerPortSetting.Value}/").WithMode(HttpListenerMode.EmbedIO))
|
||||
.WithLocalSessionManager()
|
||||
.WithModule(PluginsModule);
|
||||
|
||||
// Add registered modules
|
||||
foreach (var webModule in _modules)
|
||||
server = server.WithModule(webModule.CreateInstance());
|
||||
|
||||
server = server
|
||||
.WithModule(apiModule)
|
||||
.WithModule(PluginsModule)
|
||||
.HandleHttpException((context, exception) => HandleHttpExceptionJson(context, exception))
|
||||
.HandleUnhandledException(JsonExceptionHandlerCallback);
|
||||
|
||||
@ -166,9 +173,9 @@ namespace Artemis.Core.Services
|
||||
|
||||
#region Controller management
|
||||
|
||||
public void AddController<T>() where T : WebApiController
|
||||
public void AddController<T>(PluginFeature feature) where T : WebApiController
|
||||
{
|
||||
_controllers.Add(new WebApiControllerRegistration<T>(_kernel));
|
||||
_controllers.Add(new WebApiControllerRegistration<T>(feature));
|
||||
StartWebServer();
|
||||
}
|
||||
|
||||
@ -180,6 +187,26 @@ namespace Artemis.Core.Services
|
||||
|
||||
#endregion
|
||||
|
||||
#region Module management
|
||||
|
||||
public void AddModule<T>(PluginFeature feature) where T : IWebModule
|
||||
{
|
||||
if (feature == null) throw new ArgumentNullException(nameof(feature));
|
||||
if (_modules.Any(r => r.WebModuleType == typeof(T)))
|
||||
return;
|
||||
|
||||
_modules.Add(new WebModuleRegistration(feature, typeof(T)));
|
||||
StartWebServer();
|
||||
}
|
||||
|
||||
public void RemoveModule<T>() where T : IWebModule
|
||||
{
|
||||
_modules.RemoveAll(r => r.WebModuleType == typeof(T));
|
||||
StartWebServer();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Handlers
|
||||
|
||||
private async Task JsonExceptionHandlerCallback(IHttpContext context, Exception exception)
|
||||
@ -235,6 +262,25 @@ namespace Artemis.Core.Services
|
||||
StartWebServer();
|
||||
}
|
||||
|
||||
private void PluginManagementServiceOnPluginFeatureDisabled(object? sender, PluginFeatureEventArgs e)
|
||||
{
|
||||
bool mustRestart = false;
|
||||
if (_controllers.Any(c => c.Feature == e.PluginFeature))
|
||||
{
|
||||
mustRestart = true;
|
||||
_controllers.RemoveAll(c => c.Feature == e.PluginFeature);
|
||||
}
|
||||
|
||||
if (_modules.Any(m => m.Feature == e.PluginFeature))
|
||||
{
|
||||
mustRestart = true;
|
||||
_modules.RemoveAll(m => m.Feature == e.PluginFeature);
|
||||
}
|
||||
|
||||
if (mustRestart)
|
||||
StartWebServer();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
@ -64,7 +64,7 @@ namespace Artemis.UI
|
||||
|
||||
string url = await File.ReadAllTextAsync(Path.Combine(Constants.DataFolder, "webserver.txt"));
|
||||
using HttpClient client = new();
|
||||
await client.PostAsync(url + "api/remote/bring-to-foreground", null!);
|
||||
await client.PostAsync(url + "remote/bring-to-foreground", null!);
|
||||
}
|
||||
|
||||
private void UtilitiesOnRestartRequested(object sender, RestartEventArgs e)
|
||||
|
||||
@ -106,7 +106,7 @@ namespace Artemis.UI.Services
|
||||
|
||||
public void RegisterControllers()
|
||||
{
|
||||
_webServerService.AddController<RemoteController>();
|
||||
_webServerService.AddController<RemoteController>(Constants.CorePlugin.Features.First().Instance!);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user