< 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 2/13/2026 - 12:11:21 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        {
 2154            _serverApplicationHost = appHost;
 2155            _configuration = configuration;
 2156            _serverConfigurationManager = appHost.ConfigurationManager;
 2157        }
 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        {
 2165            services.AddResponseCompression();
 2166            services.AddHttpContextAccessor();
 2167            services.AddHttpsRedirection(options =>
 2168            {
 2169                options.HttpsPort = _serverApplicationHost.HttpsPort;
 2170            });
 71
 2172            services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetw
 2173            services.AddJellyfinDbContext(_serverApplicationHost.ConfigurationManager, _configuration);
 2174            services.AddJellyfinApiSwagger();
 75
 76            // configure custom legacy authentication
 2177            services.AddCustomAuthentication();
 78
 2179            services.AddJellyfinApiAuthorization();
 80
 2181            var productHeader = new ProductInfoHeaderValue(
 2182                _serverApplicationHost.Name.Replace(' ', '-'),
 2183                _serverApplicationHost.ApplicationVersionString);
 2184            var acceptJsonHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json, 1.0);
 2185            var acceptXmlHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Xml, 0.9);
 2186            var acceptAnyHeader = new MediaTypeWithQualityHeaderValue("*/*", 0.8);
 2187            Func<IServiceProvider, HttpMessageHandler> eyeballsHttpClientHandlerDelegate = (_) => new SocketsHttpHandler
 2188            {
 2189                AutomaticDecompression = DecompressionMethods.All,
 2190                RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8,
 2191                ConnectCallback = HttpClientExtension.OnConnect
 2192            };
 93
 2194            Func<IServiceProvider, HttpMessageHandler> defaultHttpClientHandlerDelegate = (_) => new SocketsHttpHandler(
 2195            {
 2196                AutomaticDecompression = DecompressionMethods.All,
 2197                RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8
 2198            };
 99
 21100            services.AddHttpClient(NamedClient.Default, c =>
 21101                {
 21102                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 21103                    c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 21104                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 21105                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 21106                })
 21107                .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 108
 21109            services.AddHttpClient(NamedClient.MusicBrainz, c =>
 21110                {
 21111                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 21112                    c.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue($"({_serverApplicationHost.Applicat
 21113                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 21114                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 21115                })
 21116                .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 117
 21118            services.AddHttpClient(NamedClient.DirectIp, c =>
 21119                {
 21120                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 21121                    c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 21122                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 21123                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 21124                })
 21125                .ConfigurePrimaryHttpMessageHandler(defaultHttpClientHandlerDelegate);
 126
 21127            services.AddHealthChecks()
 21128                .AddCheck<DbContextFactoryHealthCheck<JellyfinDbContext>>(nameof(JellyfinDbContext));
 129
 21130            services.AddHlsPlaylistGenerator();
 21131            services.AddLiveTvServices();
 132
 21133            var serverUICulture = _serverConfigurationManager.Configuration.UICulture;
 21134            if (string.IsNullOrEmpty(serverUICulture))
 135            {
 0136                serverUICulture = "en-US";
 137            }
 138
 21139            CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(serverUICulture);
 140
 21141            services.Configure<RequestLocalizationOptions>(options =>
 21142            {
 21143                var supportedUICultures = LocalizationManager.GetSupportedUICultures();
 21144                options.SupportedCultures = supportedUICultures;
 21145                options.SupportedUICultures = supportedUICultures;
 21146                options.DefaultRequestCulture = new RequestCulture(serverUICulture);
 21147                options.ApplyCurrentCultureToResponseHeaders = true;
 21148                options.FallBackToParentCultures = true;
 21149                options.FallBackToParentUICultures = true;
 21150            });
 151
 21152            services.AddHostedService<RecordingsHost>();
 21153            services.AddHostedService<AutoDiscoveryHost>();
 21154            services.AddHostedService<NfoUserDataSaver>();
 21155            services.AddHostedService<LibraryChangedNotifier>();
 21156            services.AddHostedService<UserDataChangeNotifier>();
 21157            services.AddHostedService<RecordingNotifier>();
 21158        }
 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        {
 21171            app.UseBaseUrlRedirection();
 172
 173            // Wrap rest of configuration so everything only listens on BaseUrl.
 21174            var config = _serverConfigurationManager.GetNetworkConfiguration();
 21175            app.Map(config.BaseUrl, mainApp =>
 21176            {
 21177                if (env.IsDevelopment())
 21178                {
 21179                    mainApp.UseDeveloperExceptionPage();
 21180                }
 21181
 21182                mainApp.UseForwardedHeaders();
 21183                mainApp.UseMiddleware<ExceptionMiddleware>();
 21184
 21185                mainApp.UseMiddleware<ResponseTimeMiddleware>();
 21186
 21187                mainApp.UseWebSockets();
 21188
 21189                mainApp.UseResponseCompression();
 21190
 21191                mainApp.UseCors();
 21192
 21193                mainApp.UseRequestLocalization();
 21194
 21195                if (config.RequireHttps && _serverApplicationHost.ListenWithHttps)
 21196                {
 21197                    mainApp.UseHttpsRedirection();
 21198                }
 21199
 21200                if (appConfig.HostWebClient())
 21201                {
 21202                    var extensionProvider = new FileExtensionContentTypeProvider();
 21203
 21204                    // subtitles octopus requires .data, .mem files.
 21205                    extensionProvider.Mappings.Add(".data", MediaTypeNames.Application.Octet);
 21206                    extensionProvider.Mappings.Add(".mem", MediaTypeNames.Application.Octet);
 21207                    mainApp.UseDefaultFiles(new DefaultFilesOptions
 21208                    {
 21209                        FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 21210                        RequestPath = "/web"
 21211                    });
 21212                    mainApp.UseStaticFiles(new StaticFileOptions
 21213                    {
 21214                        FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 21215                        RequestPath = "/web",
 21216                        ContentTypeProvider = extensionProvider,
 21217                        OnPrepareResponse = (context) =>
 21218                        {
 21219                            if (Path.GetFileName(context.File.Name).Equals("index.html", StringComparison.Ordinal))
 21220                            {
 21221                                context.Context.Response.Headers.CacheControl = new StringValues("no-cache");
 21222                            }
 21223                        }
 21224                    });
 21225
 21226                    mainApp.UseRobotsRedirection();
 21227                }
 21228
 21229                mainApp.UseStaticFiles();
 21230                mainApp.UseAuthentication();
 21231                mainApp.UseJellyfinApiSwagger(_serverConfigurationManager);
 21232                mainApp.UseQueryStringDecoding();
 21233                mainApp.UseRouting();
 21234                mainApp.UseAuthorization();
 21235
 21236                mainApp.UseIPBasedAccessValidation();
 21237                mainApp.UseWebSocketHandler();
 21238                mainApp.UseServerStartupMessage();
 21239
 21240                if (_serverConfigurationManager.Configuration.EnableMetrics)
 21241                {
 21242                    // Must be registered after any middleware that could change HTTP response codes or the data will be
 21243                    mainApp.UseHttpMetrics();
 21244                }
 21245
 21246                mainApp.UseEndpoints(endpoints =>
 21247                {
 21248                    endpoints.MapControllers();
 21249                    if (_serverConfigurationManager.Configuration.EnableMetrics)
 21250                    {
 21251                        endpoints.MapMetrics();
 21252                    }
 21253
 21254                    endpoints.MapHealthChecks("/health");
 21255                });
 21256            });
 21257        }
 258    }
 259}