mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +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
|
/// Adds a new Web API controller and restarts the web server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of Web API controller to remove</typeparam>
|
/// <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>
|
/// <summary>
|
||||||
/// Removes an existing Web API controller and restarts the web server
|
/// Removes an existing Web API controller and restarts the web server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of Web API controller to remove</typeparam>
|
/// <typeparam name="T">The type of Web API controller to remove</typeparam>
|
||||||
void RemoveController<T>() where T : WebApiController;
|
void RemoveController(WebApiControllerRegistration registration);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a new EmbedIO module and restarts the web server
|
/// Adds a new EmbedIO module and restarts the web server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void AddModule(PluginFeature feature, Func<IWebModule> create);
|
WebModuleRegistration AddModule(PluginFeature feature, Func<IWebModule> create);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a EmbedIO module and restarts the web server
|
/// Removes a EmbedIO module and restarts the web server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void RemoveModule(Func<IWebModule> create);
|
void RemoveModule(WebModuleRegistration create);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a new EmbedIO module and restarts the web server
|
/// Adds a new EmbedIO module and restarts the web server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of module to add</typeparam>
|
/// <typeparam name="T">The type of module to add</typeparam>
|
||||||
void AddModule<T>(PluginFeature feature) where T : IWebModule;
|
WebModuleRegistration 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>
|
/// <summary>
|
||||||
/// Occurs when the web server has been created and is about to start. This is the ideal place to add your own modules.
|
/// 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;
|
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>();
|
Factory = () => feature.Plugin.Resolve<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<T> Factory { get; set; }
|
internal Func<T> Factory { get; set; }
|
||||||
public override object UntypedFactory => Factory;
|
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;
|
Feature = feature;
|
||||||
ControllerType = controllerType;
|
ControllerType = controllerType;
|
||||||
|
|
||||||
|
Feature.Disabled += FeatureOnDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract object UntypedFactory { get; }
|
private void FeatureOnDisabled(object? sender, EventArgs e)
|
||||||
public Type ControllerType { get; set; }
|
{
|
||||||
|
_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; }
|
public PluginFeature Feature { get; }
|
||||||
}
|
}
|
||||||
@ -3,25 +3,44 @@ using EmbedIO;
|
|||||||
|
|
||||||
namespace Artemis.Core.Services;
|
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));
|
Feature = feature ?? throw new ArgumentNullException(nameof(feature));
|
||||||
WebModuleType = webModuleType ?? throw new ArgumentNullException(nameof(webModuleType));
|
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));
|
Feature = feature ?? throw new ArgumentNullException(nameof(feature));
|
||||||
Create = create ?? throw new ArgumentNullException(nameof(create));
|
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 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)
|
if (Create != null)
|
||||||
return Create();
|
return Create();
|
||||||
@ -29,4 +48,10 @@ internal class WebModuleRegistration
|
|||||||
return (IWebModule) Feature.Plugin.Resolve(WebModuleType);
|
return (IWebModule) Feature.Plugin.Resolve(WebModuleType);
|
||||||
throw new ArtemisCoreException("WebModuleRegistration doesn't have a create function nor a web module type :(");
|
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");
|
PluginsModule = new PluginsModule("/plugins");
|
||||||
if (coreService.IsInitialized)
|
if (coreService.IsInitialized)
|
||||||
StartWebServer();
|
AutoStartWebServer();
|
||||||
else
|
else
|
||||||
coreService.Initialized += (_, _) => StartWebServer();
|
coreService.Initialized += (sender, args) => AutoStartWebServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler? WebServerStopped;
|
public event EventHandler? WebServerStopped;
|
||||||
@ -138,7 +138,7 @@ internal class WebServerService : IWebServerService, IDisposable
|
|||||||
// Add registered controllers to the API module
|
// Add registered controllers to the API module
|
||||||
foreach (WebApiControllerRegistration registration in _controllers)
|
foreach (WebApiControllerRegistration registration in _controllers)
|
||||||
apiModule.RegisterController(registration.ControllerType, (Func<WebApiController>) registration.UntypedFactory);
|
apiModule.RegisterController(registration.ControllerType, (Func<WebApiController>) registration.UntypedFactory);
|
||||||
|
|
||||||
// Listen for state changes.
|
// Listen for state changes.
|
||||||
server.StateChanged += (s, e) => _logger.Verbose("WebServer new state - {state}", e.NewState);
|
server.StateChanged += (s, e) => _logger.Verbose("WebServer new state - {state}", e.NewState);
|
||||||
|
|
||||||
@ -173,6 +173,18 @@ internal class WebServerService : IWebServerService, IDisposable
|
|||||||
OnWebServerStarted();
|
OnWebServerStarted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AutoStartWebServer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StartWebServer();
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
_logger.Warning(exception, "Failed to initially start webserver");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -237,10 +249,6 @@ internal class WebServerService : IWebServerService, IDisposable
|
|||||||
return endPoint;
|
return endPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleDataModelRequest<T>(Module<T> module, T value) where T : DataModel, new()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemovePluginEndPoint(PluginEndPoint endPoint)
|
public void RemovePluginEndPoint(PluginEndPoint endPoint)
|
||||||
{
|
{
|
||||||
PluginsModule.RemovePluginEndPoint(endPoint);
|
PluginsModule.RemovePluginEndPoint(endPoint);
|
||||||
@ -250,15 +258,20 @@ internal class WebServerService : IWebServerService, IDisposable
|
|||||||
|
|
||||||
#region Controller management
|
#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();
|
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();
|
StartWebServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,33 +279,31 @@ internal class WebServerService : IWebServerService, IDisposable
|
|||||||
|
|
||||||
#region Module management
|
#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));
|
if (feature == null) throw new ArgumentNullException(nameof(feature));
|
||||||
|
|
||||||
_modules.Add(new WebModuleRegistration(feature, create));
|
WebModuleRegistration registration = new(this, feature, create);
|
||||||
|
_modules.Add(registration);
|
||||||
StartWebServer();
|
StartWebServer();
|
||||||
|
|
||||||
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveModule(Func<IWebModule> create)
|
public WebModuleRegistration AddModule<T>(PluginFeature feature) where T : IWebModule
|
||||||
{
|
|
||||||
_modules.RemoveAll(r => r.Create == create);
|
|
||||||
StartWebServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddModule<T>(PluginFeature feature) where T : IWebModule
|
|
||||||
{
|
{
|
||||||
if (feature == null) throw new ArgumentNullException(nameof(feature));
|
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();
|
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();
|
StartWebServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user