Merge pull request #2480 from mark-monteiro/support-injecting-iconfiguration
Support Injecting IConfiguration
This commit is contained in:
commit
0b51de3af5
|
@ -325,8 +325,6 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
private IMediaSourceManager MediaSourceManager { get; set; }
|
private IMediaSourceManager MediaSourceManager { get; set; }
|
||||||
|
|
||||||
private readonly IConfiguration _configuration;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the installation manager.
|
/// Gets the installation manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -364,11 +362,8 @@ namespace Emby.Server.Implementations
|
||||||
IStartupOptions options,
|
IStartupOptions options,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IImageEncoder imageEncoder,
|
IImageEncoder imageEncoder,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager)
|
||||||
IConfiguration configuration)
|
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
|
||||||
|
|
||||||
XmlSerializer = new MyXmlSerializer();
|
XmlSerializer = new MyXmlSerializer();
|
||||||
|
|
||||||
NetworkManager = networkManager;
|
NetworkManager = networkManager;
|
||||||
|
@ -584,7 +579,8 @@ namespace Emby.Server.Implementations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InitAsync(IServiceCollection serviceCollection)
|
/// <inheritdoc/>
|
||||||
|
public async Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig)
|
||||||
{
|
{
|
||||||
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
|
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
|
||||||
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
|
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
|
||||||
|
@ -617,7 +613,7 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
DiscoverTypes();
|
DiscoverTypes();
|
||||||
|
|
||||||
await RegisterResources(serviceCollection).ConfigureAwait(false);
|
await RegisterResources(serviceCollection, startupConfig).ConfigureAwait(false);
|
||||||
|
|
||||||
ContentRoot = ServerConfigurationManager.Configuration.DashboardSourcePath;
|
ContentRoot = ServerConfigurationManager.Configuration.DashboardSourcePath;
|
||||||
if (string.IsNullOrEmpty(ContentRoot))
|
if (string.IsNullOrEmpty(ContentRoot))
|
||||||
|
@ -656,7 +652,7 @@ namespace Emby.Server.Implementations
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers resources that classes will depend on
|
/// Registers resources that classes will depend on
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected async Task RegisterResources(IServiceCollection serviceCollection)
|
protected async Task RegisterResources(IServiceCollection serviceCollection, IConfiguration startupConfig)
|
||||||
{
|
{
|
||||||
serviceCollection.AddMemoryCache();
|
serviceCollection.AddMemoryCache();
|
||||||
|
|
||||||
|
@ -665,8 +661,6 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
|
serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
|
||||||
|
|
||||||
serviceCollection.AddSingleton<IConfiguration>(_configuration);
|
|
||||||
|
|
||||||
serviceCollection.AddSingleton(JsonSerializer);
|
serviceCollection.AddSingleton(JsonSerializer);
|
||||||
|
|
||||||
// TODO: Support for injecting ILogger should be deprecated in favour of ILogger<T> and this removed
|
// TODO: Support for injecting ILogger should be deprecated in favour of ILogger<T> and this removed
|
||||||
|
@ -758,7 +752,7 @@ namespace Emby.Server.Implementations
|
||||||
ProcessFactory,
|
ProcessFactory,
|
||||||
LocalizationManager,
|
LocalizationManager,
|
||||||
() => SubtitleEncoder,
|
() => SubtitleEncoder,
|
||||||
_configuration,
|
startupConfig,
|
||||||
StartupOptions.FFmpegPath);
|
StartupOptions.FFmpegPath);
|
||||||
serviceCollection.AddSingleton(MediaEncoder);
|
serviceCollection.AddSingleton(MediaEncoder);
|
||||||
|
|
||||||
|
@ -780,7 +774,7 @@ namespace Emby.Server.Implementations
|
||||||
this,
|
this,
|
||||||
LoggerFactory.CreateLogger<HttpListenerHost>(),
|
LoggerFactory.CreateLogger<HttpListenerHost>(),
|
||||||
ServerConfigurationManager,
|
ServerConfigurationManager,
|
||||||
_configuration,
|
startupConfig,
|
||||||
NetworkManager,
|
NetworkManager,
|
||||||
JsonSerializer,
|
JsonSerializer,
|
||||||
XmlSerializer,
|
XmlSerializer,
|
||||||
|
|
|
@ -23,23 +23,20 @@ namespace Jellyfin.Server
|
||||||
/// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
/// <param name="imageEncoder">The <see cref="IImageEncoder" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="imageEncoder">The <see cref="IImageEncoder" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
/// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param>
|
/// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param>
|
||||||
/// <param name="configuration">The <see cref="IConfiguration" /> to be used by the <see cref="CoreAppHost" />.</param>
|
|
||||||
public CoreAppHost(
|
public CoreAppHost(
|
||||||
ServerApplicationPaths applicationPaths,
|
ServerApplicationPaths applicationPaths,
|
||||||
ILoggerFactory loggerFactory,
|
ILoggerFactory loggerFactory,
|
||||||
StartupOptions options,
|
StartupOptions options,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IImageEncoder imageEncoder,
|
IImageEncoder imageEncoder,
|
||||||
INetworkManager networkManager,
|
INetworkManager networkManager)
|
||||||
IConfiguration configuration)
|
|
||||||
: base(
|
: base(
|
||||||
applicationPaths,
|
applicationPaths,
|
||||||
loggerFactory,
|
loggerFactory,
|
||||||
options,
|
options,
|
||||||
fileSystem,
|
fileSystem,
|
||||||
imageEncoder,
|
imageEncoder,
|
||||||
networkManager,
|
networkManager)
|
||||||
configuration)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,10 +112,12 @@ namespace Jellyfin.Server
|
||||||
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
|
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
|
||||||
Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
|
Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
|
||||||
|
|
||||||
IConfiguration appConfig = await CreateConfiguration(appPaths).ConfigureAwait(false);
|
// Create an instance of the application configuration to use for application startup
|
||||||
|
await InitLoggingConfigFile(appPaths).ConfigureAwait(false);
|
||||||
CreateLogger(appConfig, appPaths);
|
IConfiguration startupConfig = CreateAppConfiguration(appPaths);
|
||||||
|
|
||||||
|
// Initialize logging framework
|
||||||
|
InitializeLoggingFramework(startupConfig, appPaths);
|
||||||
_logger = _loggerFactory.CreateLogger("Main");
|
_logger = _loggerFactory.CreateLogger("Main");
|
||||||
|
|
||||||
// Log uncaught exceptions to the logging instead of std error
|
// Log uncaught exceptions to the logging instead of std error
|
||||||
|
@ -180,23 +182,22 @@ namespace Jellyfin.Server
|
||||||
options,
|
options,
|
||||||
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
||||||
GetImageEncoder(appPaths),
|
GetImageEncoder(appPaths),
|
||||||
new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()),
|
new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()));
|
||||||
appConfig);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ServiceCollection serviceCollection = new ServiceCollection();
|
ServiceCollection serviceCollection = new ServiceCollection();
|
||||||
await appHost.InitAsync(serviceCollection).ConfigureAwait(false);
|
await appHost.InitAsync(serviceCollection, startupConfig).ConfigureAwait(false);
|
||||||
|
|
||||||
var host = CreateWebHostBuilder(appHost, serviceCollection).Build();
|
var webHost = CreateWebHostBuilder(appHost, serviceCollection, appPaths).Build();
|
||||||
|
|
||||||
// A bit hacky to re-use service provider since ASP.NET doesn't allow a custom service collection.
|
// A bit hacky to re-use service provider since ASP.NET doesn't allow a custom service collection.
|
||||||
appHost.ServiceProvider = host.Services;
|
appHost.ServiceProvider = webHost.Services;
|
||||||
appHost.FindParts();
|
appHost.FindParts();
|
||||||
Migrations.MigrationRunner.Run(appHost, _loggerFactory);
|
Migrations.MigrationRunner.Run(appHost, _loggerFactory);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await host.StartAsync().ConfigureAwait(false);
|
await webHost.StartAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -232,7 +233,7 @@ namespace Jellyfin.Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IWebHostBuilder CreateWebHostBuilder(ApplicationHost appHost, IServiceCollection serviceCollection)
|
private static IWebHostBuilder CreateWebHostBuilder(ApplicationHost appHost, IServiceCollection serviceCollection, IApplicationPaths appPaths)
|
||||||
{
|
{
|
||||||
return new WebHostBuilder()
|
return new WebHostBuilder()
|
||||||
.UseKestrel(options =>
|
.UseKestrel(options =>
|
||||||
|
@ -272,6 +273,7 @@ namespace Jellyfin.Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.ConfigureAppConfiguration(config => config.ConfigureAppConfiguration(appPaths))
|
||||||
.UseSerilog()
|
.UseSerilog()
|
||||||
.UseContentRoot(appHost.ContentRoot)
|
.UseContentRoot(appHost.ContentRoot)
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
|
@ -445,38 +447,51 @@ namespace Jellyfin.Server
|
||||||
return new ServerApplicationPaths(dataDir, logDir, configDir, cacheDir, webDir);
|
return new ServerApplicationPaths(dataDir, logDir, configDir, cacheDir, webDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<IConfiguration> CreateConfiguration(IApplicationPaths appPaths)
|
/// <summary>
|
||||||
|
/// Initialize the logging configuration file using the bundled resource file as a default if it doesn't exist
|
||||||
|
/// already.
|
||||||
|
/// </summary>
|
||||||
|
private static async Task InitLoggingConfigFile(IApplicationPaths appPaths)
|
||||||
{
|
{
|
||||||
const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
|
// Do nothing if the config file already exists
|
||||||
string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, LoggingConfigFileDefault);
|
string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, LoggingConfigFileDefault);
|
||||||
|
if (File.Exists(configPath))
|
||||||
if (!File.Exists(configPath))
|
|
||||||
{
|
{
|
||||||
// For some reason the csproj name is used instead of the assembly name
|
return;
|
||||||
await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath);
|
|
||||||
if (resource == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
"Invalid resource path: '{0}'",
|
|
||||||
ResourcePath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a stream of the resource contents
|
||||||
|
// NOTE: The .csproj name is used instead of the assembly name in the resource path
|
||||||
|
const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
|
||||||
|
await using Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath)
|
||||||
|
?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'");
|
||||||
|
|
||||||
|
// Copy the resource contents to the expected file path for the config file
|
||||||
await using Stream dst = File.Open(configPath, FileMode.CreateNew);
|
await using Stream dst = File.Open(configPath, FileMode.CreateNew);
|
||||||
await resource.CopyToAsync(dst).ConfigureAwait(false);
|
await resource.CopyToAsync(dst).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IConfiguration CreateAppConfiguration(IApplicationPaths appPaths)
|
||||||
|
{
|
||||||
return new ConfigurationBuilder()
|
return new ConfigurationBuilder()
|
||||||
|
.ConfigureAppConfiguration(appPaths)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IConfigurationBuilder ConfigureAppConfiguration(this IConfigurationBuilder config, IApplicationPaths appPaths)
|
||||||
|
{
|
||||||
|
return config
|
||||||
.SetBasePath(appPaths.ConfigurationDirectoryPath)
|
.SetBasePath(appPaths.ConfigurationDirectoryPath)
|
||||||
.AddInMemoryCollection(ConfigurationOptions.Configuration)
|
.AddInMemoryCollection(ConfigurationOptions.Configuration)
|
||||||
.AddJsonFile(LoggingConfigFileDefault, optional: false, reloadOnChange: true)
|
.AddJsonFile(LoggingConfigFileDefault, optional: false, reloadOnChange: true)
|
||||||
.AddJsonFile(LoggingConfigFileSystem, optional: true, reloadOnChange: true)
|
.AddJsonFile(LoggingConfigFileSystem, optional: true, reloadOnChange: true)
|
||||||
.AddEnvironmentVariables("JELLYFIN_")
|
.AddEnvironmentVariables("JELLYFIN_");
|
||||||
.Build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CreateLogger(IConfiguration configuration, IApplicationPaths appPaths)
|
/// <summary>
|
||||||
|
/// Initialize Serilog using configuration and fall back to defaults on failure.
|
||||||
|
/// </summary>
|
||||||
|
private static void InitializeLoggingFramework(IConfiguration configuration, IApplicationPaths appPaths)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Plugins;
|
using MediaBrowser.Common.Plugins;
|
||||||
using MediaBrowser.Model.Updates;
|
using MediaBrowser.Model.Updates;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace MediaBrowser.Common
|
namespace MediaBrowser.Common
|
||||||
|
@ -121,11 +122,12 @@ namespace MediaBrowser.Common
|
||||||
void RemovePlugin(IPlugin plugin);
|
void RemovePlugin(IPlugin plugin);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inits this instance.
|
/// Initializes this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serviceCollection">The service collection.</param>
|
/// <param name="serviceCollection">The service collection.</param>
|
||||||
|
/// <param name="startupConfig">The configuration to use for initialization.</param>
|
||||||
/// <returns>A task.</returns>
|
/// <returns>A task.</returns>
|
||||||
Task InitAsync(IServiceCollection serviceCollection);
|
Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the instance.
|
/// Creates the instance.
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.1" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.1" />
|
||||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user