< Summary - Jellyfin

Information
Class: Jellyfin.Server.Startup
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Startup.cs
Line coverage
100%
Covered lines: 154
Uncovered lines: 0
Coverable lines: 154
Total lines: 243
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

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

File(s)

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

#LineLine coverage
 1using System;
 2using System.IO;
 3using System.Net;
 4using System.Net.Http;
 5using System.Net.Http.Headers;
 6using System.Net.Mime;
 7using System.Text;
 8using Emby.Server.Implementations.EntryPoints;
 9using Jellyfin.Api.Middleware;
 10using Jellyfin.Database.Implementations;
 11using Jellyfin.LiveTv.Extensions;
 12using Jellyfin.LiveTv.Recordings;
 13using Jellyfin.MediaEncoding.Hls.Extensions;
 14using Jellyfin.Networking;
 15using Jellyfin.Networking.HappyEyeballs;
 16using Jellyfin.Server.Extensions;
 17using Jellyfin.Server.HealthChecks;
 18using Jellyfin.Server.Implementations.Extensions;
 19using Jellyfin.Server.Infrastructure;
 20using MediaBrowser.Common.Net;
 21using MediaBrowser.Controller.Configuration;
 22using MediaBrowser.Controller.Extensions;
 23using MediaBrowser.XbmcMetadata;
 24using Microsoft.AspNetCore.Builder;
 25using Microsoft.AspNetCore.Hosting;
 26using Microsoft.AspNetCore.Mvc;
 27using Microsoft.AspNetCore.Mvc.Infrastructure;
 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
 72            // TODO remove once this is fixed upstream https://github.com/dotnet/aspnetcore/issues/34371
 2173            services.AddSingleton<IActionResultExecutor<PhysicalFileResult>, SymlinkFollowingPhysicalFileResultExecutor>
 2174            services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetw
 2175            services.AddJellyfinDbContext(_serverApplicationHost.ConfigurationManager, _configuration);
 2176            services.AddJellyfinApiSwagger();
 77
 78            // configure custom legacy authentication
 2179            services.AddCustomAuthentication();
 80
 2181            services.AddJellyfinApiAuthorization();
 82
 2183            var productHeader = new ProductInfoHeaderValue(
 2184                _serverApplicationHost.Name.Replace(' ', '-'),
 2185                _serverApplicationHost.ApplicationVersionString);
 2186            var acceptJsonHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json, 1.0);
 2187            var acceptXmlHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Xml, 0.9);
 2188            var acceptAnyHeader = new MediaTypeWithQualityHeaderValue("*/*", 0.8);
 2189            Func<IServiceProvider, HttpMessageHandler> eyeballsHttpClientHandlerDelegate = (_) => new SocketsHttpHandler
 2190            {
 2191                AutomaticDecompression = DecompressionMethods.All,
 2192                RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8,
 2193                ConnectCallback = HttpClientExtension.OnConnect
 2194            };
 95
 2196            Func<IServiceProvider, HttpMessageHandler> defaultHttpClientHandlerDelegate = (_) => new SocketsHttpHandler(
 2197            {
 2198                AutomaticDecompression = DecompressionMethods.All,
 2199                RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8
 21100            };
 101
 21102            services.AddHttpClient(NamedClient.Default, c =>
 21103                {
 21104                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 21105                    c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 21106                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 21107                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 21108                })
 21109                .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 110
 21111            services.AddHttpClient(NamedClient.MusicBrainz, c =>
 21112                {
 21113                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 21114                    c.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue($"({_serverApplicationHost.Applicat
 21115                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 21116                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 21117                })
 21118                .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 119
 21120            services.AddHttpClient(NamedClient.DirectIp, c =>
 21121                {
 21122                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 21123                    c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 21124                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 21125                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 21126                })
 21127                .ConfigurePrimaryHttpMessageHandler(defaultHttpClientHandlerDelegate);
 128
 21129            services.AddHealthChecks()
 21130                .AddCheck<DbContextFactoryHealthCheck<JellyfinDbContext>>(nameof(JellyfinDbContext));
 131
 21132            services.AddHlsPlaylistGenerator();
 21133            services.AddLiveTvServices();
 134
 21135            services.AddHostedService<RecordingsHost>();
 21136            services.AddHostedService<AutoDiscoveryHost>();
 21137            services.AddHostedService<NfoUserDataSaver>();
 21138            services.AddHostedService<LibraryChangedNotifier>();
 21139            services.AddHostedService<UserDataChangeNotifier>();
 21140            services.AddHostedService<RecordingNotifier>();
 21141        }
 142
 143        /// <summary>
 144        /// Configures the app builder for the webhost.
 145        /// </summary>
 146        /// <param name="app">The application builder.</param>
 147        /// <param name="env">The webhost environment.</param>
 148        /// <param name="appConfig">The application config.</param>
 149        public void Configure(
 150            IApplicationBuilder app,
 151            IWebHostEnvironment env,
 152            IConfiguration appConfig)
 153        {
 21154            app.UseBaseUrlRedirection();
 155
 156            // Wrap rest of configuration so everything only listens on BaseUrl.
 21157            var config = _serverConfigurationManager.GetNetworkConfiguration();
 21158            app.Map(config.BaseUrl, mainApp =>
 21159            {
 21160                if (env.IsDevelopment())
 21161                {
 21162                    mainApp.UseDeveloperExceptionPage();
 21163                }
 21164
 21165                mainApp.UseForwardedHeaders();
 21166                mainApp.UseMiddleware<ExceptionMiddleware>();
 21167
 21168                mainApp.UseMiddleware<ResponseTimeMiddleware>();
 21169
 21170                mainApp.UseWebSockets();
 21171
 21172                mainApp.UseResponseCompression();
 21173
 21174                mainApp.UseCors();
 21175
 21176                if (config.RequireHttps && _serverApplicationHost.ListenWithHttps)
 21177                {
 21178                    mainApp.UseHttpsRedirection();
 21179                }
 21180
 21181                // This must be injected before any path related middleware.
 21182                mainApp.UsePathTrim();
 21183
 21184                if (appConfig.HostWebClient())
 21185                {
 21186                    var extensionProvider = new FileExtensionContentTypeProvider();
 21187
 21188                    // subtitles octopus requires .data, .mem files.
 21189                    extensionProvider.Mappings.Add(".data", MediaTypeNames.Application.Octet);
 21190                    extensionProvider.Mappings.Add(".mem", MediaTypeNames.Application.Octet);
 21191                    mainApp.UseDefaultFiles(new DefaultFilesOptions
 21192                    {
 21193                        FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 21194                        RequestPath = "/web"
 21195                    });
 21196                    mainApp.UseStaticFiles(new StaticFileOptions
 21197                    {
 21198                        FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 21199                        RequestPath = "/web",
 21200                        ContentTypeProvider = extensionProvider,
 21201                        OnPrepareResponse = (context) =>
 21202                        {
 21203                            if (Path.GetFileName(context.File.Name).Equals("index.html", StringComparison.Ordinal))
 21204                            {
 21205                                context.Context.Response.Headers.CacheControl = new StringValues("no-cache");
 21206                            }
 21207                        }
 21208                    });
 21209
 21210                    mainApp.UseRobotsRedirection();
 21211                }
 21212
 21213                mainApp.UseStaticFiles();
 21214                mainApp.UseAuthentication();
 21215                mainApp.UseJellyfinApiSwagger(_serverConfigurationManager);
 21216                mainApp.UseQueryStringDecoding();
 21217                mainApp.UseRouting();
 21218                mainApp.UseAuthorization();
 21219
 21220                mainApp.UseIPBasedAccessValidation();
 21221                mainApp.UseWebSocketHandler();
 21222                mainApp.UseServerStartupMessage();
 21223
 21224                if (_serverConfigurationManager.Configuration.EnableMetrics)
 21225                {
 21226                    // Must be registered after any middleware that could change HTTP response codes or the data will be
 21227                    mainApp.UseHttpMetrics();
 21228                }
 21229
 21230                mainApp.UseEndpoints(endpoints =>
 21231                {
 21232                    endpoints.MapControllers();
 21233                    if (_serverConfigurationManager.Configuration.EnableMetrics)
 21234                    {
 21235                        endpoints.MapMetrics();
 21236                    }
 21237
 21238                    endpoints.MapHealthChecks("/health");
 21239                });
 21240            });
 21241        }
 242    }
 243}