< Summary - Jellyfin

Information
Class: Jellyfin.Server.Startup
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Startup.cs
Line coverage
99%
Covered lines: 165
Uncovered lines: 1
Coverable lines: 166
Total lines: 259
Line coverage: 99.3%
Branch coverage
50%
Covered branches: 1
Total branches: 2
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 3/26/2026 - 12:14:14 AM Line coverage: 100% (150/150) Total lines: 2355/15/2026 - 12:15:55 AM Line coverage: 99.3% (165/166) Branch coverage: 50% (1/2) Total lines: 259 5/15/2026 - 12:15:55 AM Line coverage: 99.3% (165/166) Branch coverage: 50% (1/2) Total lines: 259

Coverage delta

Coverage delta 1 -1

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
ConfigureServices(...)50%2298.7%
Configure(...)100%11100%

File(s)

/srv/git/jellyfin/Jellyfin.Server/Startup.cs

#LineLine coverage
 1using System;
 2using System.Globalization;
 3using System.IO;
 4using System.Net;
 5using System.Net.Http;
 6using System.Net.Http.Headers;
 7using System.Net.Mime;
 8using System.Text;
 9using Emby.Server.Implementations.EntryPoints;
 10using Emby.Server.Implementations.Localization;
 11using Jellyfin.Api.Middleware;
 12using Jellyfin.Database.Implementations;
 13using Jellyfin.LiveTv.Extensions;
 14using Jellyfin.LiveTv.Recordings;
 15using Jellyfin.MediaEncoding.Hls.Extensions;
 16using Jellyfin.Networking;
 17using Jellyfin.Networking.HappyEyeballs;
 18using Jellyfin.Server.Extensions;
 19using Jellyfin.Server.HealthChecks;
 20using Jellyfin.Server.Implementations.Extensions;
 21using MediaBrowser.Common.Net;
 22using MediaBrowser.Controller.Configuration;
 23using MediaBrowser.Controller.Extensions;
 24using MediaBrowser.XbmcMetadata;
 25using Microsoft.AspNetCore.Builder;
 26using Microsoft.AspNetCore.Hosting;
 27using Microsoft.AspNetCore.Localization;
 28using Microsoft.AspNetCore.StaticFiles;
 29using Microsoft.Extensions.Configuration;
 30using Microsoft.Extensions.DependencyInjection;
 31using Microsoft.Extensions.FileProviders;
 32using Microsoft.Extensions.Hosting;
 33using Microsoft.Extensions.Primitives;
 34using Prometheus;
 35
 36namespace Jellyfin.Server
 37{
 38    /// <summary>
 39    /// Startup configuration for the Kestrel webhost.
 40    /// </summary>
 41    public class Startup
 42    {
 43        private readonly CoreAppHost _serverApplicationHost;
 44        private readonly IConfiguration _configuration;
 45        private readonly IServerConfigurationManager _serverConfigurationManager;
 46
 47        /// <summary>
 48        /// Initializes a new instance of the <see cref="Startup" /> class.
 49        /// </summary>
 50        /// <param name="appHost">The server application host.</param>
 51        /// <param name="configuration">The used Configuration.</param>
 52        public Startup(CoreAppHost appHost, IConfiguration configuration)
 53        {
 2254            _serverApplicationHost = appHost;
 2255            _configuration = configuration;
 2256            _serverConfigurationManager = appHost.ConfigurationManager;
 2257        }
 58
 59        /// <summary>
 60        /// Configures the service collection for the webhost.
 61        /// </summary>
 62        /// <param name="services">The service collection.</param>
 63        public void ConfigureServices(IServiceCollection services)
 64        {
 2265            services.AddResponseCompression();
 2266            services.AddHttpContextAccessor();
 2267            services.AddHttpsRedirection(options =>
 2268            {
 2269                options.HttpsPort = _serverApplicationHost.HttpsPort;
 2270            });
 71
 2272            services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetw
 2273            services.AddJellyfinDbContext(_serverApplicationHost.ConfigurationManager, _configuration);
 2274            services.AddJellyfinApiSwagger();
 75
 76            // configure custom legacy authentication
 2277            services.AddCustomAuthentication();
 78
 2279            services.AddJellyfinApiAuthorization();
 80
 2281            var productHeader = new ProductInfoHeaderValue(
 2282                _serverApplicationHost.Name.Replace(' ', '-'),
 2283                _serverApplicationHost.ApplicationVersionString);
 2284            var acceptJsonHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json, 1.0);
 2285            var acceptXmlHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Xml, 0.9);
 2286            var acceptAnyHeader = new MediaTypeWithQualityHeaderValue("*/*", 0.8);
 2287            Func<IServiceProvider, HttpMessageHandler> eyeballsHttpClientHandlerDelegate = (_) => new SocketsHttpHandler
 2288            {
 2289                AutomaticDecompression = DecompressionMethods.All,
 2290                RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8,
 2291                ConnectCallback = HttpClientExtension.OnConnect
 2292            };
 93
 2294            Func<IServiceProvider, HttpMessageHandler> defaultHttpClientHandlerDelegate = (_) => new SocketsHttpHandler(
 2295            {
 2296                AutomaticDecompression = DecompressionMethods.All,
 2297                RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8
 2298            };
 99
 22100            services.AddHttpClient(NamedClient.Default, c =>
 22101                {
 22102                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 22103                    c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 22104                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 22105                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 22106                })
 22107                .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 108
 22109            services.AddHttpClient(NamedClient.MusicBrainz, c =>
 22110                {
 22111                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 22112                    c.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue($"({_serverApplicationHost.Applicat
 22113                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 22114                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 22115                })
 22116                .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 117
 22118            services.AddHttpClient(NamedClient.DirectIp, c =>
 22119                {
 22120                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 22121                    c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 22122                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 22123                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 22124                })
 22125                .ConfigurePrimaryHttpMessageHandler(defaultHttpClientHandlerDelegate);
 126
 22127            services.AddHealthChecks()
 22128                .AddCheck<DbContextFactoryHealthCheck<JellyfinDbContext>>(nameof(JellyfinDbContext));
 129
 22130            services.AddHlsPlaylistGenerator();
 22131            services.AddLiveTvServices();
 132
 22133            var serverUICulture = _serverConfigurationManager.Configuration.UICulture;
 22134            if (string.IsNullOrEmpty(serverUICulture))
 135            {
 0136                serverUICulture = "en-US";
 137            }
 138
 22139            CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(serverUICulture);
 140
 22141            services.Configure<RequestLocalizationOptions>(options =>
 22142            {
 22143                var supportedUICultures = LocalizationManager.GetSupportedUICultures();
 22144                options.SupportedCultures = supportedUICultures;
 22145                options.SupportedUICultures = supportedUICultures;
 22146                options.DefaultRequestCulture = new RequestCulture(serverUICulture);
 22147                options.ApplyCurrentCultureToResponseHeaders = true;
 22148                options.FallBackToParentCultures = true;
 22149                options.FallBackToParentUICultures = true;
 22150            });
 151
 22152            services.AddHostedService<RecordingsHost>();
 22153            services.AddHostedService<AutoDiscoveryHost>();
 22154            services.AddHostedService<NfoUserDataSaver>();
 22155            services.AddHostedService<LibraryChangedNotifier>();
 22156            services.AddHostedService<UserDataChangeNotifier>();
 22157            services.AddHostedService<RecordingNotifier>();
 22158        }
 159
 160        /// <summary>
 161        /// Configures the app builder for the webhost.
 162        /// </summary>
 163        /// <param name="app">The application builder.</param>
 164        /// <param name="env">The webhost environment.</param>
 165        /// <param name="appConfig">The application config.</param>
 166        public void Configure(
 167            IApplicationBuilder app,
 168            IWebHostEnvironment env,
 169            IConfiguration appConfig)
 170        {
 22171            app.UseBaseUrlRedirection();
 172
 173            // Wrap rest of configuration so everything only listens on BaseUrl.
 22174            var config = _serverConfigurationManager.GetNetworkConfiguration();
 22175            app.Map(config.BaseUrl, mainApp =>
 22176            {
 22177                if (env.IsDevelopment())
 22178                {
 22179                    mainApp.UseDeveloperExceptionPage();
 22180                }
 22181
 22182                mainApp.UseForwardedHeaders();
 22183                mainApp.UseMiddleware<ExceptionMiddleware>();
 22184
 22185                mainApp.UseMiddleware<ResponseTimeMiddleware>();
 22186
 22187                mainApp.UseWebSockets();
 22188
 22189                mainApp.UseResponseCompression();
 22190
 22191                mainApp.UseCors();
 22192
 22193                mainApp.UseRequestLocalization();
 22194
 22195                if (config.RequireHttps && _serverApplicationHost.ListenWithHttps)
 22196                {
 22197                    mainApp.UseHttpsRedirection();
 22198                }
 22199
 22200                if (appConfig.HostWebClient())
 22201                {
 22202                    var extensionProvider = new FileExtensionContentTypeProvider();
 22203
 22204                    // subtitles octopus requires .data, .mem files.
 22205                    extensionProvider.Mappings.Add(".data", MediaTypeNames.Application.Octet);
 22206                    extensionProvider.Mappings.Add(".mem", MediaTypeNames.Application.Octet);
 22207                    mainApp.UseDefaultFiles(new DefaultFilesOptions
 22208                    {
 22209                        FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 22210                        RequestPath = "/web"
 22211                    });
 22212                    mainApp.UseStaticFiles(new StaticFileOptions
 22213                    {
 22214                        FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 22215                        RequestPath = "/web",
 22216                        ContentTypeProvider = extensionProvider,
 22217                        OnPrepareResponse = (context) =>
 22218                        {
 22219                            if (Path.GetFileName(context.File.Name).Equals("index.html", StringComparison.Ordinal))
 22220                            {
 22221                                context.Context.Response.Headers.CacheControl = new StringValues("no-cache");
 22222                            }
 22223                        }
 22224                    });
 22225
 22226                    mainApp.UseRobotsRedirection();
 22227                }
 22228
 22229                mainApp.UseStaticFiles();
 22230                mainApp.UseAuthentication();
 22231                mainApp.UseJellyfinApiSwagger(_serverConfigurationManager);
 22232                mainApp.UseQueryStringDecoding();
 22233                mainApp.UseRouting();
 22234                mainApp.UseAuthorization();
 22235
 22236                mainApp.UseIPBasedAccessValidation();
 22237                mainApp.UseWebSocketHandler();
 22238                mainApp.UseServerStartupMessage();
 22239
 22240                if (_serverConfigurationManager.Configuration.EnableMetrics)
 22241                {
 22242                    // Must be registered after any middleware that could change HTTP response codes or the data will be
 22243                    mainApp.UseHttpMetrics();
 22244                }
 22245
 22246                mainApp.UseEndpoints(endpoints =>
 22247                {
 22248                    endpoints.MapControllers();
 22249                    if (_serverConfigurationManager.Configuration.EnableMetrics)
 22250                    {
 22251                        endpoints.MapMetrics();
 22252                    }
 22253
 22254                    endpoints.MapHealthChecks("/health");
 22255                });
 22256            });
 22257        }
 258    }
 259}