mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-23 02:27:17 +00:00
Merge pull request #2601 from mark-monteiro/support-running-without-web-content
Support Running Server Without Web Content
This commit is contained in:
@@ -5,7 +5,7 @@ using MediaBrowser.Common.Configuration;
|
||||
namespace Emby.Server.Implementations.AppBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class to hold common application paths used by both the Ui and Server.
|
||||
/// Provides a base class to hold common application paths used by both the UI and Server.
|
||||
/// This can be subclassed to add application-specific paths.
|
||||
/// </summary>
|
||||
public abstract class BaseApplicationPaths : IApplicationPaths
|
||||
@@ -37,10 +37,7 @@ namespace Emby.Server.Implementations.AppBase
|
||||
/// <value>The program data path.</value>
|
||||
public string ProgramDataPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the web UI resources folder.
|
||||
/// </summary>
|
||||
/// <value>The web UI resources path.</value>
|
||||
/// <inheritdoc/>
|
||||
public string WebPath { get; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -235,11 +235,6 @@ namespace Emby.Server.Implementations
|
||||
/// </summary>
|
||||
public int HttpsPort { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content root for the webhost.
|
||||
/// </summary>
|
||||
public string ContentRoot { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server configuration manager.
|
||||
/// </summary>
|
||||
@@ -612,13 +607,7 @@ namespace Emby.Server.Implementations
|
||||
|
||||
DiscoverTypes();
|
||||
|
||||
await RegisterResources(serviceCollection, startupConfig).ConfigureAwait(false);
|
||||
|
||||
ContentRoot = ServerConfigurationManager.Configuration.DashboardSourcePath;
|
||||
if (string.IsNullOrEmpty(ContentRoot))
|
||||
{
|
||||
ContentRoot = ServerConfigurationManager.ApplicationPaths.WebPath;
|
||||
}
|
||||
await RegisterServices(serviceCollection, startupConfig).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task ExecuteWebsocketHandlerAsync(HttpContext context, Func<Task> next)
|
||||
@@ -649,9 +638,9 @@ namespace Emby.Server.Implementations
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers resources that classes will depend on
|
||||
/// Registers services/resources with the service collection that will be available via DI.
|
||||
/// </summary>
|
||||
protected async Task RegisterResources(IServiceCollection serviceCollection, IConfiguration startupConfig)
|
||||
protected async Task RegisterServices(IServiceCollection serviceCollection, IConfiguration startupConfig)
|
||||
{
|
||||
serviceCollection.AddMemoryCache();
|
||||
|
||||
@@ -769,20 +758,8 @@ namespace Emby.Server.Implementations
|
||||
CertificateInfo = GetCertificateInfo(true);
|
||||
Certificate = GetCertificate(CertificateInfo);
|
||||
|
||||
HttpServer = new HttpListenerHost(
|
||||
this,
|
||||
LoggerFactory.CreateLogger<HttpListenerHost>(),
|
||||
ServerConfigurationManager,
|
||||
startupConfig,
|
||||
NetworkManager,
|
||||
JsonSerializer,
|
||||
XmlSerializer,
|
||||
CreateHttpListener())
|
||||
{
|
||||
GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading")
|
||||
};
|
||||
|
||||
serviceCollection.AddSingleton(HttpServer);
|
||||
serviceCollection.AddSingleton<IHttpListener, WebSocketSharpListener>();
|
||||
serviceCollection.AddSingleton<IHttpServer, HttpListenerHost>();
|
||||
|
||||
ImageProcessor = new ImageProcessor(LoggerFactory.CreateLogger<ImageProcessor>(), ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder);
|
||||
serviceCollection.AddSingleton(ImageProcessor);
|
||||
@@ -895,6 +872,14 @@ namespace Emby.Server.Implementations
|
||||
((LibraryManager)LibraryManager).ItemRepository = ItemRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create services registered with the service container that need to be initialized at application startup.
|
||||
/// </summary>
|
||||
public void InitializeServices()
|
||||
{
|
||||
HttpServer = Resolve<IHttpServer>();
|
||||
}
|
||||
|
||||
public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths)
|
||||
{
|
||||
// Distinct these to prevent users from reporting problems that aren't actually problems
|
||||
@@ -1212,8 +1197,6 @@ namespace Emby.Server.Implementations
|
||||
});
|
||||
}
|
||||
|
||||
protected IHttpListener CreateHttpListener() => new WebSocketSharpListener(LoggerFactory.CreateLogger<WebSocketSharpListener>());
|
||||
|
||||
private CertificateInfo GetCertificateInfo(bool generateCertificate)
|
||||
{
|
||||
// Custom cert
|
||||
|
||||
@@ -1,51 +1,48 @@
|
||||
using System;
|
||||
using MediaBrowser.Controller;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Browser
|
||||
{
|
||||
/// <summary>
|
||||
/// Class BrowserLauncher.
|
||||
/// Assists in opening application URLs in an external browser.
|
||||
/// </summary>
|
||||
public static class BrowserLauncher
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens the dashboard page.
|
||||
/// </summary>
|
||||
/// <param name="page">The page.</param>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
private static void OpenDashboardPage(string page, IServerApplicationHost appHost)
|
||||
{
|
||||
var url = appHost.GetLocalApiUrl("localhost") + "/web/" + page;
|
||||
|
||||
OpenUrl(appHost, url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the web client.
|
||||
/// Opens the home page of the web client.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
public static void OpenWebApp(IServerApplicationHost appHost)
|
||||
{
|
||||
OpenDashboardPage("index.html", appHost);
|
||||
TryOpenUrl(appHost, "/web/index.html");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the URL.
|
||||
/// Opens the swagger API page.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The application host instance.</param>
|
||||
/// <param name="appHost">The app host.</param>
|
||||
public static void OpenSwaggerPage(IServerApplicationHost appHost)
|
||||
{
|
||||
TryOpenUrl(appHost, "/swagger/index.html");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified URL in an external browser window. Any exceptions will be logged, but ignored.
|
||||
/// </summary>
|
||||
/// <param name="appHost">The application host.</param>
|
||||
/// <param name="url">The URL.</param>
|
||||
private static void OpenUrl(IServerApplicationHost appHost, string url)
|
||||
private static void TryOpenUrl(IServerApplicationHost appHost, string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
appHost.LaunchUrl(url);
|
||||
string baseUrl = appHost.GetLocalApiUrl("localhost");
|
||||
appHost.LaunchUrl(baseUrl + url);
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
var logger = appHost.Resolve<ILogger>();
|
||||
logger?.LogError(ex, "Failed to open browser window with URL {URL}", url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using Emby.Server.Implementations.HttpServer;
|
||||
using MediaBrowser.Providers.Music;
|
||||
using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
|
||||
|
||||
namespace Emby.Server.Implementations
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class containing the default configuration options for the web server.
|
||||
/// </summary>
|
||||
public static class ConfigurationOptions
|
||||
{
|
||||
public static Dictionary<string, string> Configuration => new Dictionary<string, string>
|
||||
/// <summary>
|
||||
/// Gets a new copy of the default configuration options.
|
||||
/// </summary>
|
||||
public static Dictionary<string, string> DefaultConfiguration => new Dictionary<string, string>
|
||||
{
|
||||
{ "HttpListenerHost:DefaultRedirectPath", "web/index.html" },
|
||||
{ HostWebClientKey, bool.TrueString },
|
||||
{ HttpListenerHost.DefaultRedirectKey, "web/index.html" },
|
||||
{ FfmpegProbeSizeKey, "1G" },
|
||||
{ FfmpegAnalyzeDurationKey, "200M" },
|
||||
{ PlaylistsAllowDuplicatesKey, bool.TrueString }
|
||||
|
||||
@@ -2,7 +2,9 @@ using System.Threading.Tasks;
|
||||
using Emby.Server.Implementations.Browser;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Extensions;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Emby.Server.Implementations.EntryPoints
|
||||
{
|
||||
@@ -11,10 +13,8 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
/// </summary>
|
||||
public sealed class StartupWizard : IServerEntryPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// The app host.
|
||||
/// </summary>
|
||||
private readonly IServerApplicationHost _appHost;
|
||||
private readonly IConfiguration _appConfig;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
|
||||
/// <summary>
|
||||
@@ -22,9 +22,10 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
/// </summary>
|
||||
/// <param name="appHost">The application host.</param>
|
||||
/// <param name="config">The configuration manager.</param>
|
||||
public StartupWizard(IServerApplicationHost appHost, IServerConfigurationManager config)
|
||||
public StartupWizard(IServerApplicationHost appHost, IConfiguration appConfig, IServerConfigurationManager config)
|
||||
{
|
||||
_appHost = appHost;
|
||||
_appConfig = appConfig;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
@@ -36,7 +37,11 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (!_config.Configuration.IsStartupWizardCompleted)
|
||||
if (!_appConfig.HostWebClient())
|
||||
{
|
||||
BrowserLauncher.OpenSwaggerPage(_appHost);
|
||||
}
|
||||
else if (!_config.Configuration.IsStartupWizardCompleted)
|
||||
{
|
||||
BrowserLauncher.OpenWebApp(_appHost);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@@ -29,6 +30,12 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
{
|
||||
public class HttpListenerHost : IHttpServer, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The key for a setting that specifies the default redirect path
|
||||
/// to use for requests where the URL base prefix is invalid or missing.
|
||||
/// </summary>
|
||||
public const string DefaultRedirectKey = "HttpListenerHost:DefaultRedirectPath";
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly INetworkManager _networkManager;
|
||||
@@ -52,12 +59,13 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
INetworkManager networkManager,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IXmlSerializer xmlSerializer,
|
||||
IHttpListener socketListener)
|
||||
IHttpListener socketListener,
|
||||
ILocalizationManager localizationManager)
|
||||
{
|
||||
_appHost = applicationHost;
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_defaultRedirectPath = configuration["HttpListenerHost:DefaultRedirectPath"];
|
||||
_defaultRedirectPath = configuration[DefaultRedirectKey];
|
||||
_baseUrlPrefix = _config.Configuration.BaseUrl;
|
||||
_networkManager = networkManager;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
@@ -69,6 +77,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
|
||||
Instance = this;
|
||||
ResponseFilters = Array.Empty<Action<IRequest, HttpResponse, object>>();
|
||||
GlobalResponse = localizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
|
||||
}
|
||||
|
||||
public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
|
||||
|
||||
Reference in New Issue
Block a user