mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 13:28:33 +00:00
Web server - Ensure controllers and web modules provided by plugins are removed on disable
This commit is contained in:
parent
43e396bf6d
commit
d73312c4f4
@ -95,35 +95,29 @@ public interface IWebServerService : IArtemisService
|
||||
/// 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>(PluginFeature feature) where T : WebApiController;
|
||||
WebApiControllerRegistration AddController<T>(PluginFeature feature) where T : WebApiController;
|
||||
|
||||
/// <summary>
|
||||
/// Removes an existing Web API controller and restarts the web server
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of Web API controller to remove</typeparam>
|
||||
void RemoveController<T>() where T : WebApiController;
|
||||
void RemoveController(WebApiControllerRegistration registration);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new EmbedIO module and restarts the web server
|
||||
/// </summary>
|
||||
void AddModule(PluginFeature feature, Func<IWebModule> create);
|
||||
WebModuleRegistration AddModule(PluginFeature feature, Func<IWebModule> create);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a EmbedIO module and restarts the web server
|
||||
/// </summary>
|
||||
void RemoveModule(Func<IWebModule> create);
|
||||
void RemoveModule(WebModuleRegistration create);
|
||||
|
||||
/// <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;
|
||||
WebModuleRegistration AddModule<T>(PluginFeature feature) 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.
|
||||
|
||||
@ -3,26 +3,55 @@ using EmbedIO.WebApi;
|
||||
|
||||
namespace Artemis.Core.Services;
|
||||
|
||||
internal class WebApiControllerRegistration<T> : WebApiControllerRegistration where T : WebApiController
|
||||
/// <summary>
|
||||
/// Represents a web API controller registration.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the web API controller.</typeparam>
|
||||
public class WebApiControllerRegistration<T> : WebApiControllerRegistration where T : WebApiController
|
||||
{
|
||||
public WebApiControllerRegistration(PluginFeature feature) : base(feature, typeof(T))
|
||||
internal WebApiControllerRegistration(IWebServerService webServerService, PluginFeature feature) : base(webServerService, feature, typeof(T))
|
||||
{
|
||||
Factory = () => feature.Plugin.Resolve<T>();
|
||||
}
|
||||
|
||||
public Func<T> Factory { get; set; }
|
||||
public override object UntypedFactory => Factory;
|
||||
internal Func<T> Factory { get; set; }
|
||||
internal override object UntypedFactory => Factory;
|
||||
}
|
||||
|
||||
internal abstract class WebApiControllerRegistration
|
||||
/// <summary>
|
||||
/// Represents a web API controller registration.
|
||||
/// </summary>
|
||||
public abstract class WebApiControllerRegistration
|
||||
{
|
||||
protected WebApiControllerRegistration(PluginFeature feature, Type controllerType)
|
||||
private readonly IWebServerService _webServerService;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="WebApiControllerRegistration"/> class.
|
||||
/// </summary>
|
||||
protected internal WebApiControllerRegistration(IWebServerService webServerService, PluginFeature feature, Type controllerType)
|
||||
{
|
||||
_webServerService = webServerService;
|
||||
Feature = feature;
|
||||
ControllerType = controllerType;
|
||||
|
||||
Feature.Disabled += FeatureOnDisabled;
|
||||
}
|
||||
|
||||
public abstract object UntypedFactory { get; }
|
||||
public Type ControllerType { get; set; }
|
||||
private void FeatureOnDisabled(object? sender, EventArgs e)
|
||||
{
|
||||
_webServerService.RemoveController(this);
|
||||
Feature.Disabled -= FeatureOnDisabled;
|
||||
}
|
||||
|
||||
internal abstract object UntypedFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the web API controller.
|
||||
/// </summary>
|
||||
public Type ControllerType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin feature that provided the web API controller.
|
||||
/// </summary>
|
||||
public PluginFeature Feature { get; }
|
||||
}
|
||||
@ -3,25 +3,44 @@ using EmbedIO;
|
||||
|
||||
namespace Artemis.Core.Services;
|
||||
|
||||
internal class WebModuleRegistration
|
||||
/// <summary>
|
||||
/// Represents a registration for a web module.
|
||||
/// </summary>
|
||||
public class WebModuleRegistration
|
||||
{
|
||||
public WebModuleRegistration(PluginFeature feature, Type webModuleType)
|
||||
private readonly IWebServerService _webServerService;
|
||||
|
||||
internal WebModuleRegistration(IWebServerService webServerService, PluginFeature feature, Type webModuleType)
|
||||
{
|
||||
_webServerService = webServerService;
|
||||
Feature = feature ?? throw new ArgumentNullException(nameof(feature));
|
||||
WebModuleType = webModuleType ?? throw new ArgumentNullException(nameof(webModuleType));
|
||||
|
||||
Feature.Disabled += FeatureOnDisabled;
|
||||
}
|
||||
|
||||
public WebModuleRegistration(PluginFeature feature, Func<IWebModule> create)
|
||||
internal WebModuleRegistration(IWebServerService webServerService, PluginFeature feature, Func<IWebModule> create)
|
||||
{
|
||||
_webServerService = webServerService;
|
||||
Feature = feature ?? throw new ArgumentNullException(nameof(feature));
|
||||
Create = create ?? throw new ArgumentNullException(nameof(create));
|
||||
|
||||
Feature.Disabled += FeatureOnDisabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The plugin feature that provided the web module.
|
||||
/// </summary>
|
||||
public PluginFeature Feature { get; }
|
||||
public Type? WebModuleType { get; }
|
||||
public Func<IWebModule>? Create { get; }
|
||||
|
||||
public IWebModule CreateInstance()
|
||||
/// <summary>
|
||||
/// The type of the web module.
|
||||
/// </summary>
|
||||
public Type? WebModuleType { get; }
|
||||
|
||||
internal Func<IWebModule>? Create { get; }
|
||||
|
||||
internal IWebModule CreateInstance()
|
||||
{
|
||||
if (Create != null)
|
||||
return Create();
|
||||
@ -29,4 +48,10 @@ internal class WebModuleRegistration
|
||||
return (IWebModule) Feature.Plugin.Resolve(WebModuleType);
|
||||
throw new ArtemisCoreException("WebModuleRegistration doesn't have a create function nor a web module type :(");
|
||||
}
|
||||
|
||||
private void FeatureOnDisabled(object? sender, EventArgs e)
|
||||
{
|
||||
_webServerService.RemoveModule(this);
|
||||
Feature.Disabled -= FeatureOnDisabled;
|
||||
}
|
||||
}
|
||||
@ -39,9 +39,9 @@ internal class WebServerService : IWebServerService, IDisposable
|
||||
|
||||
PluginsModule = new PluginsModule("/plugins");
|
||||
if (coreService.IsInitialized)
|
||||
StartWebServer();
|
||||
AutoStartWebServer();
|
||||
else
|
||||
coreService.Initialized += (_, _) => StartWebServer();
|
||||
coreService.Initialized += (sender, args) => AutoStartWebServer();
|
||||
}
|
||||
|
||||
public event EventHandler? WebServerStopped;
|
||||
@ -138,7 +138,7 @@ internal class WebServerService : IWebServerService, IDisposable
|
||||
// Add registered controllers to the API module
|
||||
foreach (WebApiControllerRegistration registration in _controllers)
|
||||
apiModule.RegisterController(registration.ControllerType, (Func<WebApiController>) registration.UntypedFactory);
|
||||
|
||||
|
||||
// Listen for state changes.
|
||||
server.StateChanged += (s, e) => _logger.Verbose("WebServer new state - {state}", e.NewState);
|
||||
|
||||
@ -173,6 +173,18 @@ internal class WebServerService : IWebServerService, IDisposable
|
||||
OnWebServerStarted();
|
||||
}
|
||||
}
|
||||
|
||||
private void AutoStartWebServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
StartWebServer();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.Warning(exception, "Failed to initially start webserver");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -237,10 +249,6 @@ internal class WebServerService : IWebServerService, IDisposable
|
||||
return endPoint;
|
||||
}
|
||||
|
||||
private void HandleDataModelRequest<T>(Module<T> module, T value) where T : DataModel, new()
|
||||
{
|
||||
}
|
||||
|
||||
public void RemovePluginEndPoint(PluginEndPoint endPoint)
|
||||
{
|
||||
PluginsModule.RemovePluginEndPoint(endPoint);
|
||||
@ -250,15 +258,20 @@ internal class WebServerService : IWebServerService, IDisposable
|
||||
|
||||
#region Controller management
|
||||
|
||||
public void AddController<T>(PluginFeature feature) where T : WebApiController
|
||||
public WebApiControllerRegistration AddController<T>(PluginFeature feature) where T : WebApiController
|
||||
{
|
||||
_controllers.Add(new WebApiControllerRegistration<T>(feature));
|
||||
if (feature == null) throw new ArgumentNullException(nameof(feature));
|
||||
|
||||
WebApiControllerRegistration<T> registration = new(this, feature);
|
||||
_controllers.Add(registration);
|
||||
StartWebServer();
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
||||
public void RemoveController<T>() where T : WebApiController
|
||||
public void RemoveController(WebApiControllerRegistration registration)
|
||||
{
|
||||
_controllers.RemoveAll(r => r.ControllerType == typeof(T));
|
||||
_controllers.Remove(registration);
|
||||
StartWebServer();
|
||||
}
|
||||
|
||||
@ -266,33 +279,31 @@ internal class WebServerService : IWebServerService, IDisposable
|
||||
|
||||
#region Module management
|
||||
|
||||
public void AddModule(PluginFeature feature, Func<IWebModule> create)
|
||||
public WebModuleRegistration AddModule(PluginFeature feature, Func<IWebModule> create)
|
||||
{
|
||||
if (feature == null) throw new ArgumentNullException(nameof(feature));
|
||||
|
||||
_modules.Add(new WebModuleRegistration(feature, create));
|
||||
WebModuleRegistration registration = new(this, feature, create);
|
||||
_modules.Add(registration);
|
||||
StartWebServer();
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
||||
public void RemoveModule(Func<IWebModule> create)
|
||||
{
|
||||
_modules.RemoveAll(r => r.Create == create);
|
||||
StartWebServer();
|
||||
}
|
||||
|
||||
public void AddModule<T>(PluginFeature feature) where T : IWebModule
|
||||
public WebModuleRegistration 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)));
|
||||
WebModuleRegistration registration = new(this, feature, typeof(T));
|
||||
_modules.Add(registration);
|
||||
StartWebServer();
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
||||
public void RemoveModule<T>() where T : IWebModule
|
||||
public void RemoveModule(WebModuleRegistration registration)
|
||||
{
|
||||
_modules.RemoveAll(r => r.WebModuleType == typeof(T));
|
||||
_modules.Remove(registration);
|
||||
StartWebServer();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user