Browse Source

Merge pull request #2769 from mark-monteiro/configurable-repo-url

Make Plugin Repo URL Configurable
Vasily 5 years ago
parent
commit
53db9567d3

+ 2 - 0
Emby.Server.Implementations/ConfigurationOptions.cs

@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using Emby.Server.Implementations.HttpServer;
+using Emby.Server.Implementations.Updates;
 using MediaBrowser.Providers.Music;
 using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
 
@@ -17,6 +18,7 @@ namespace Emby.Server.Implementations
         {
             { HostWebClientKey, bool.TrueString },
             { HttpListenerHost.DefaultRedirectKey, "web/index.html" },
+            { InstallationManager.PluginManifestUrlKey, "https://repo.jellyfin.org/releases/plugin/manifest.json" },
             { FfmpegProbeSizeKey, "1G" },
             { FfmpegAnalyzeDurationKey, "200M" },
             { PlaylistsAllowDuplicatesKey, bool.TrueString }

+ 11 - 6
Emby.Server.Implementations/IStartupOptions.cs

@@ -3,33 +3,38 @@ namespace Emby.Server.Implementations
     public interface IStartupOptions
     {
         /// <summary>
-        /// --ffmpeg
+        /// Gets the value of the --ffmpeg command line option.
         /// </summary>
         string FFmpegPath { get; }
 
         /// <summary>
-        /// --service
+        /// Gets the value of the --service command line option.
         /// </summary>
         bool IsService { get; }
 
         /// <summary>
-        /// --noautorunwebapp
+        /// Gets the value of the --noautorunwebapp command line option.
         /// </summary>
         bool NoAutoRunWebApp { get; }
 
         /// <summary>
-        /// --package-name
+        /// Gets the value of the --package-name command line option.
         /// </summary>
         string PackageName { get; }
 
         /// <summary>
-        /// --restartpath
+        /// Gets the value of the --restartpath command line option.
         /// </summary>
         string RestartPath { get; }
 
         /// <summary>
-        /// --restartargs
+        /// Gets the value of the --restartargs command line option.
         /// </summary>
         string RestartArgs { get; }
+
+        /// <summary>
+        /// Gets the value of the --plugin-manifest-url command line option.
+        /// </summary>
+        string PluginManifestUrl { get; }
     }
 }

+ 47 - 12
Emby.Server.Implementations/Updates/InstallationManager.cs

@@ -3,8 +3,10 @@ using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Net;
 using System.Net.Http;
 using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
 using System.Security.Cryptography;
 using System.Threading;
 using System.Threading.Tasks;
@@ -18,6 +20,7 @@ using MediaBrowser.Model.Events;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Updates;
+using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Logging;
 
 namespace Emby.Server.Implementations.Updates
@@ -27,6 +30,11 @@ namespace Emby.Server.Implementations.Updates
     /// </summary>
     public class InstallationManager : IInstallationManager
     {
+        /// <summary>
+        /// The key for a setting that specifies a URL for the plugin repository JSON manifest.
+        /// </summary>
+        public const string PluginManifestUrlKey = "InstallationManager:PluginManifestUrl";
+
         /// <summary>
         /// The _logger.
         /// </summary>
@@ -44,6 +52,7 @@ namespace Emby.Server.Implementations.Updates
         private readonly IApplicationHost _applicationHost;
 
         private readonly IZipClient _zipClient;
+        private readonly IConfiguration _appConfig;
 
         private readonly object _currentInstallationsLock = new object();
 
@@ -65,7 +74,8 @@ namespace Emby.Server.Implementations.Updates
             IJsonSerializer jsonSerializer,
             IServerConfigurationManager config,
             IFileSystem fileSystem,
-            IZipClient zipClient)
+            IZipClient zipClient,
+            IConfiguration appConfig)
         {
             if (logger == null)
             {
@@ -83,6 +93,7 @@ namespace Emby.Server.Implementations.Updates
             _config = config;
             _fileSystem = fileSystem;
             _zipClient = zipClient;
+            _appConfig = appConfig;
         }
 
         /// <inheritdoc />
@@ -112,19 +123,43 @@ namespace Emby.Server.Implementations.Updates
         /// <inheritdoc />
         public async Task<IReadOnlyList<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken = default)
         {
-            using (var response = await _httpClient.SendAsync(
-                new HttpRequestOptions
+            var manifestUrl = _appConfig.GetValue<string>(PluginManifestUrlKey);
+
+            try
+            {
+                using (var response = await _httpClient.SendAsync(
+                    new HttpRequestOptions
+                    {
+                        Url = manifestUrl,
+                        CancellationToken = cancellationToken,
+                        CacheMode = CacheMode.Unconditional,
+                        CacheLength = TimeSpan.FromMinutes(3)
+                    },
+                    HttpMethod.Get).ConfigureAwait(false))
+                using (Stream stream = response.Content)
                 {
-                    Url = "https://repo.jellyfin.org/releases/plugin/manifest.json",
-                    CancellationToken = cancellationToken,
-                    CacheMode = CacheMode.Unconditional,
-                    CacheLength = TimeSpan.FromMinutes(3)
-                },
-                HttpMethod.Get).ConfigureAwait(false))
-            using (Stream stream = response.Content)
+                    try
+                    {
+                        return await _jsonSerializer.DeserializeFromStreamAsync<IReadOnlyList<PackageInfo>>(stream).ConfigureAwait(false);
+                    }
+                    catch (SerializationException ex)
+                    {
+                        const string LogTemplate =
+                            "Failed to deserialize the plugin manifest retrieved from {PluginManifestUrl}. If you " +
+                            "have specified a custom plugin repository manifest URL with --plugin-manifest-url or " +
+                            PluginManifestUrlKey + ", please ensure that it is correct.";
+                        _logger.LogError(ex, LogTemplate, manifestUrl);
+                        throw;
+                    }
+                }
+            }
+            catch (UriFormatException ex)
             {
-                return await _jsonSerializer.DeserializeFromStreamAsync<IReadOnlyList<PackageInfo>>(
-                    stream).ConfigureAwait(false);
+                const string LogTemplate =
+                    "The URL configured for the plugin repository manifest URL is not valid: {PluginManifestUrl}. " +
+                    "Please check the URL configured by --plugin-manifest-url or " + PluginManifestUrlKey;
+                _logger.LogError(ex, LogTemplate, manifestUrl);
+                throw;
             }
         }
 

+ 10 - 1
Jellyfin.Server/StartupOptions.cs

@@ -1,7 +1,7 @@
 using System.Collections.Generic;
-using System.Globalization;
 using CommandLine;
 using Emby.Server.Implementations;
+using Emby.Server.Implementations.Updates;
 using MediaBrowser.Controller.Extensions;
 
 namespace Jellyfin.Server
@@ -76,6 +76,10 @@ namespace Jellyfin.Server
         [Option("restartargs", Required = false, HelpText = "Arguments for restart script.")]
         public string? RestartArgs { get; set; }
 
+        /// <inheritdoc />
+        [Option("plugin-manifest-url", Required = false, HelpText = "A custom URL for the plugin repository JSON manifest")]
+        public string? PluginManifestUrl { get; set; }
+
         /// <summary>
         /// Gets the command line options as a dictionary that can be used in the .NET configuration system.
         /// </summary>
@@ -84,6 +88,11 @@ namespace Jellyfin.Server
         {
             var config = new Dictionary<string, string>();
 
+            if (PluginManifestUrl != null)
+            {
+                config.Add(InstallationManager.PluginManifestUrlKey, PluginManifestUrl);
+            }
+
             if (NoWebClient)
             {
                 config.Add(ConfigurationExtensions.HostWebClientKey, bool.FalseString);