Browse Source

Dynamically populate LocalAddress based on HTTP request

Support populating the LocalAddress field in the system info
endpoint based on the x-forwarded-host and x-forwarded-proto header.

The x-forwarded-host header must contain both the host and port for
the url to be properly constructed.

Behind network configuration option that is disabled by default.
Fredrik Lindberg 3 years ago
parent
commit
90174f68e2

+ 17 - 5
Emby.Server.Implementations/ApplicationHost.cs

@@ -1073,9 +1073,9 @@ namespace Emby.Server.Implementations
         /// <summary>
         /// Gets the system status.
         /// </summary>
-        /// <param name="source">Where this request originated.</param>
+        /// <param name="request">Where this request originated.</param>
         /// <returns>SystemInfo.</returns>
-        public SystemInfo GetSystemInfo(IPAddress source)
+        public SystemInfo GetSystemInfo(HttpRequest request)
         {
             return new SystemInfo
             {
@@ -1097,7 +1097,7 @@ namespace Emby.Server.Implementations
                 CanLaunchWebBrowser = CanLaunchWebBrowser,
                 TranscodingTempPath = ConfigurationManager.GetTranscodePath(),
                 ServerName = FriendlyName,
-                LocalAddress = GetSmartApiUrl(source),
+                LocalAddress = GetSmartApiUrl(request),
                 SupportsLibraryMonitor = true,
                 EncoderLocation = _mediaEncoder.EncoderLocation,
                 SystemArchitecture = RuntimeInformation.OSArchitecture,
@@ -1110,7 +1110,7 @@ namespace Emby.Server.Implementations
                 .Select(i => new WakeOnLanInfo(i))
                 .ToList();
 
-        public PublicSystemInfo GetPublicSystemInfo(IPAddress address)
+        public PublicSystemInfo GetPublicSystemInfo(HttpRequest request)
         {
             return new PublicSystemInfo
             {
@@ -1119,7 +1119,7 @@ namespace Emby.Server.Implementations
                 Id = SystemId,
                 OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(),
                 ServerName = FriendlyName,
-                LocalAddress = GetSmartApiUrl(address),
+                LocalAddress = GetSmartApiUrl(request),
                 StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted
             };
         }
@@ -1150,6 +1150,18 @@ namespace Emby.Server.Implementations
         /// <inheritdoc/>
         public string GetSmartApiUrl(HttpRequest request, int? port = null)
         {
+            // Return the host in the HTTP request as the API url
+            if (ConfigurationManager.GetNetworkConfiguration().EnablePublishedServerUriByRequest)
+            {
+                int? requestPort = request.Host.Port;
+                if ((requestPort == 80 && string.Equals(request.Scheme, "http", StringComparison.OrdinalIgnoreCase)) || (requestPort == 443 && string.Equals(request.Scheme, "https", StringComparison.OrdinalIgnoreCase)))
+                {
+                    requestPort = -1;
+                }
+
+                return GetLocalApiUrl(request.Host.Host, request.Scheme, requestPort);
+            }
+
             // Published server ends with a /
             if (!string.IsNullOrEmpty(PublishedServerUrl))
             {

+ 2 - 2
Jellyfin.Api/Controllers/SystemController.cs

@@ -66,7 +66,7 @@ namespace Jellyfin.Api.Controllers
         [ProducesResponseType(StatusCodes.Status200OK)]
         public ActionResult<SystemInfo> GetSystemInfo()
         {
-            return _appHost.GetSystemInfo(Request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback);
+            return _appHost.GetSystemInfo(Request);
         }
 
         /// <summary>
@@ -78,7 +78,7 @@ namespace Jellyfin.Api.Controllers
         [ProducesResponseType(StatusCodes.Status200OK)]
         public ActionResult<PublicSystemInfo> GetPublicSystemInfo()
         {
-            return _appHost.GetPublicSystemInfo(Request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback);
+            return _appHost.GetPublicSystemInfo(Request);
         }
 
         /// <summary>

+ 5 - 0
Jellyfin.Networking/Configuration/NetworkConfiguration.cs

@@ -226,5 +226,10 @@ namespace Jellyfin.Networking.Configuration
         /// Gets or sets the known proxies. If the proxy is a network, it's added to the KnownNetworks.
         /// </summary>
         public string[] KnownProxies { get; set; } = Array.Empty<string>();
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the published server uri is based on information in HTTP requests.
+        /// </summary>
+        public bool EnablePublishedServerUriByRequest { get; set; } = false;
     }
 }

+ 2 - 1
Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs

@@ -188,7 +188,8 @@ namespace Jellyfin.Server.Extensions
                     // https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/HttpOverrides/src/ForwardedHeadersMiddleware.cs
                     // Enable debug logging on Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware to help investigate issues.
 
-                    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
+                    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
+
                     if (config.KnownProxies.Length == 0)
                     {
                         options.KnownNetworks.Clear();

+ 3 - 3
MediaBrowser.Controller/IServerApplicationHost.cs

@@ -51,11 +51,11 @@ namespace MediaBrowser.Controller
         /// <summary>
         /// Gets the system info.
         /// </summary>
-        /// <param name="source">The originator of the request.</param>
+        /// <param name="request">The HTTP request.</param>
         /// <returns>SystemInfo.</returns>
-        SystemInfo GetSystemInfo(IPAddress source);
+        SystemInfo GetSystemInfo(HttpRequest request);
 
-        PublicSystemInfo GetPublicSystemInfo(IPAddress address);
+        PublicSystemInfo GetPublicSystemInfo(HttpRequest request);
 
         /// <summary>
         /// Gets a URL specific for the request.