2023-01-15 11:46:30 -05:00
using System ;
2025-04-19 22:08:24 +03:00
using System.Collections.Generic ;
2023-01-15 11:46:30 -05:00
using System.IO ;
using System.Net ;
2025-04-19 22:08:24 +03:00
using System.Security.Cryptography.X509Certificates ;
2023-01-15 11:46:30 -05:00
using Jellyfin.Server.Helpers ;
using MediaBrowser.Common.Configuration ;
using MediaBrowser.Controller.Extensions ;
2025-04-19 22:08:24 +03:00
using MediaBrowser.Model.Net ;
2023-01-15 11:46:30 -05:00
using Microsoft.AspNetCore.Hosting ;
2025-04-19 22:08:24 +03:00
using Microsoft.AspNetCore.Server.Kestrel.Core ;
2023-01-15 11:46:30 -05:00
using Microsoft.Extensions.Configuration ;
using Microsoft.Extensions.Hosting ;
using Microsoft.Extensions.Logging ;
namespace Jellyfin.Server.Extensions ;
/// <summary>
/// Extensions for configuring the web host builder.
/// </summary>
public static class WebHostBuilderExtensions
{
/// <summary>
/// Configure the web host builder.
/// </summary>
/// <param name="builder">The builder to configure.</param>
/// <param name="appHost">The application host.</param>
/// <param name="startupConfig">The application configuration.</param>
/// <param name="appPaths">The application paths.</param>
/// <param name="logger">The logger.</param>
/// <returns>The configured web host builder.</returns>
public static IWebHostBuilder ConfigureWebHostBuilder (
this IWebHostBuilder builder ,
CoreAppHost appHost ,
IConfiguration startupConfig ,
IApplicationPaths appPaths ,
ILogger logger )
{
return builder
. UseKestrel ( ( builderContext , options ) = >
{
2025-04-19 22:08:24 +03:00
SetupJellyfinWebServer (
appHost . NetManager . GetAllBindInterfaces ( false ) ,
appHost . HttpPort ,
appHost . ListenWithHttps ? appHost . HttpsPort : null ,
appHost . Certificate ,
startupConfig ,
appPaths ,
logger ,
builderContext ,
options ) ;
} )
. UseStartup ( context = > new Startup ( appHost , context . Configuration ) ) ;
}
2023-01-15 11:46:30 -05:00
2025-04-19 22:08:24 +03:00
/// <summary>
/// Configures a Kestrel type webServer to bind to the specific arguments.
/// </summary>
/// <param name="addresses">The IP addresses that should be listend to.</param>
/// <param name="httpPort">The http port.</param>
/// <param name="httpsPort">If set the https port. If set you must also set the certificate.</param>
/// <param name="certificate">The certificate used for https port.</param>
/// <param name="startupConfig">The startup config.</param>
/// <param name="appPaths">The app paths.</param>
/// <param name="logger">A logger.</param>
/// <param name="builderContext">The kestrel build pipeline context.</param>
/// <param name="options">The kestrel server options.</param>
/// <exception cref="InvalidOperationException">Will be thrown when a https port is set but no or an invalid certificate is provided.</exception>
public static void SetupJellyfinWebServer (
IReadOnlyList < IPData > addresses ,
int httpPort ,
int? httpsPort ,
X509Certificate2 ? certificate ,
IConfiguration startupConfig ,
IApplicationPaths appPaths ,
ILogger logger ,
WebHostBuilderContext builderContext ,
KestrelServerOptions options )
{
bool flagged = false ;
foreach ( var netAdd in addresses )
{
var address = netAdd . Address ;
logger . LogInformation ( "Kestrel is listening on {Address}" , address . Equals ( IPAddress . IPv6Any ) ? "all interfaces" : address ) ;
options . Listen ( netAdd . Address , httpPort ) ;
if ( httpsPort . HasValue )
{
if ( builderContext . HostingEnvironment . IsDevelopment ( ) )
2023-01-15 11:46:30 -05:00
{
2025-04-19 22:08:24 +03:00
try
2023-01-15 11:46:30 -05:00
{
options . Listen (
2024-05-17 13:51:48 -04:00
address ,
2025-04-19 22:08:24 +03:00
httpsPort . Value ,
listenOptions = > listenOptions . UseHttps ( ) ) ;
2023-01-15 11:46:30 -05:00
}
2025-04-19 22:08:24 +03:00
catch ( InvalidOperationException )
2023-01-15 11:46:30 -05:00
{
2025-04-19 22:08:24 +03:00
if ( ! flagged )
2023-01-15 11:46:30 -05:00
{
2025-04-19 22:08:24 +03:00
logger . LogWarning ( "Failed to listen to HTTPS using the ASP.NET Core HTTPS development certificate. Please ensure it has been installed and set as trusted" ) ;
flagged = true ;
2023-01-15 11:46:30 -05:00
}
}
}
2025-04-19 22:08:24 +03:00
else
2023-01-15 11:46:30 -05:00
{
2025-04-19 22:08:24 +03:00
if ( certificate is null )
2023-01-15 11:46:30 -05:00
{
2025-04-19 22:08:24 +03:00
throw new InvalidOperationException ( "Cannot run jellyfin with https without setting a valid certificate." ) ;
2023-01-15 11:46:30 -05:00
}
2025-04-19 22:08:24 +03:00
options . Listen (
address ,
httpsPort . Value ,
listenOptions = > listenOptions . UseHttps ( certificate ) ) ;
2023-01-15 11:46:30 -05:00
}
2025-04-19 22:08:24 +03:00
}
}
// Bind to unix socket (only on unix systems)
if ( startupConfig . UseUnixSocket ( ) & & Environment . OSVersion . Platform = = PlatformID . Unix )
{
var socketPath = StartupHelpers . GetUnixSocketPath ( startupConfig , appPaths ) ;
// Workaround for https://github.com/aspnet/AspNetCore/issues/14134
if ( File . Exists ( socketPath ) )
{
File . Delete ( socketPath ) ;
}
options . ListenUnixSocket ( socketPath ) ;
logger . LogInformation ( "Kestrel listening to unix socket {SocketPath}" , socketPath ) ;
}
2023-01-15 11:46:30 -05:00
}
}