< Summary - Jellyfin

Information
Class: Jellyfin.Server.Startup
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Startup.cs
Line coverage
100%
Covered lines: 148
Uncovered lines: 0
Coverable lines: 148
Total lines: 233
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.Net;
 3using System.Net.Http;
 4using System.Net.Http.Headers;
 5using System.Net.Mime;
 6using System.Text;
 7using Emby.Server.Implementations.EntryPoints;
 8using Jellyfin.Api.Middleware;
 9using Jellyfin.LiveTv.Extensions;
 10using Jellyfin.LiveTv.Recordings;
 11using Jellyfin.MediaEncoding.Hls.Extensions;
 12using Jellyfin.Networking;
 13using Jellyfin.Networking.HappyEyeballs;
 14using Jellyfin.Server.Extensions;
 15using Jellyfin.Server.HealthChecks;
 16using Jellyfin.Server.Implementations;
 17using Jellyfin.Server.Implementations.Extensions;
 18using Jellyfin.Server.Infrastructure;
 19using MediaBrowser.Common.Net;
 20using MediaBrowser.Controller.Configuration;
 21using MediaBrowser.Controller.Extensions;
 22using MediaBrowser.XbmcMetadata;
 23using Microsoft.AspNetCore.Builder;
 24using Microsoft.AspNetCore.Hosting;
 25using Microsoft.AspNetCore.Mvc;
 26using Microsoft.AspNetCore.Mvc.Infrastructure;
 27using Microsoft.AspNetCore.StaticFiles;
 28using Microsoft.Extensions.Configuration;
 29using Microsoft.Extensions.DependencyInjection;
 30using Microsoft.Extensions.FileProviders;
 31using Microsoft.Extensions.Hosting;
 32using Prometheus;
 33
 34namespace Jellyfin.Server
 35{
 36    /// <summary>
 37    /// Startup configuration for the Kestrel webhost.
 38    /// </summary>
 39    public class Startup
 40    {
 41        private readonly CoreAppHost _serverApplicationHost;
 42        private readonly IServerConfigurationManager _serverConfigurationManager;
 43
 44        /// <summary>
 45        /// Initializes a new instance of the <see cref="Startup" /> class.
 46        /// </summary>
 47        /// <param name="appHost">The server application host.</param>
 48        public Startup(CoreAppHost appHost)
 49        {
 2250            _serverApplicationHost = appHost;
 2251            _serverConfigurationManager = appHost.ConfigurationManager;
 2252        }
 53
 54        /// <summary>
 55        /// Configures the service collection for the webhost.
 56        /// </summary>
 57        /// <param name="services">The service collection.</param>
 58        public void ConfigureServices(IServiceCollection services)
 59        {
 2260            services.AddResponseCompression();
 2261            services.AddHttpContextAccessor();
 2262            services.AddHttpsRedirection(options =>
 2263            {
 2264                options.HttpsPort = _serverApplicationHost.HttpsPort;
 2265            });
 66
 67            // TODO remove once this is fixed upstream https://github.com/dotnet/aspnetcore/issues/34371
 2268            services.AddSingleton<IActionResultExecutor<PhysicalFileResult>, SymlinkFollowingPhysicalFileResultExecutor>
 2269            services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetw
 2270            services.AddJellyfinDbContext();
 2271            services.AddJellyfinApiSwagger();
 72
 73            // configure custom legacy authentication
 2274            services.AddCustomAuthentication();
 75
 2276            services.AddJellyfinApiAuthorization();
 77
 2278            var productHeader = new ProductInfoHeaderValue(
 2279                _serverApplicationHost.Name.Replace(' ', '-'),
 2280                _serverApplicationHost.ApplicationVersionString);
 2281            var acceptJsonHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json, 1.0);
 2282            var acceptXmlHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Xml, 0.9);
 2283            var acceptAnyHeader = new MediaTypeWithQualityHeaderValue("*/*", 0.8);
 2284            Func<IServiceProvider, HttpMessageHandler> eyeballsHttpClientHandlerDelegate = (_) => new SocketsHttpHandler
 2285            {
 2286                AutomaticDecompression = DecompressionMethods.All,
 2287                RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8,
 2288                ConnectCallback = HttpClientExtension.OnConnect
 2289            };
 90
 2291            Func<IServiceProvider, HttpMessageHandler> defaultHttpClientHandlerDelegate = (_) => new SocketsHttpHandler(
 2292            {
 2293                AutomaticDecompression = DecompressionMethods.All,
 2294                RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8
 2295            };
 96
 2297            services.AddHttpClient(NamedClient.Default, c =>
 2298                {
 2299                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 22100                    c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 22101                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 22102                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 22103                })
 22104                .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 105
 22106            services.AddHttpClient(NamedClient.MusicBrainz, c =>
 22107                {
 22108                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 22109                    c.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue($"({_serverApplicationHost.Applicat
 22110                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 22111                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 22112                })
 22113                .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 114
 22115            services.AddHttpClient(NamedClient.DirectIp, c =>
 22116                {
 22117                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 22118                    c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 22119                    c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 22120                    c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 22121                })
 22122                .ConfigurePrimaryHttpMessageHandler(defaultHttpClientHandlerDelegate);
 123
 22124            services.AddHealthChecks()
 22125                .AddCheck<DbContextFactoryHealthCheck<JellyfinDbContext>>(nameof(JellyfinDbContext));
 126
 22127            services.AddHlsPlaylistGenerator();
 22128            services.AddLiveTvServices();
 129
 22130            services.AddHostedService<RecordingsHost>();
 22131            services.AddHostedService<AutoDiscoveryHost>();
 22132            services.AddHostedService<PortForwardingHost>();
 22133            services.AddHostedService<NfoUserDataSaver>();
 22134            services.AddHostedService<LibraryChangedNotifier>();
 22135            services.AddHostedService<UserDataChangeNotifier>();
 22136            services.AddHostedService<RecordingNotifier>();
 22137        }
 138
 139        /// <summary>
 140        /// Configures the app builder for the webhost.
 141        /// </summary>
 142        /// <param name="app">The application builder.</param>
 143        /// <param name="env">The webhost environment.</param>
 144        /// <param name="appConfig">The application config.</param>
 145        public void Configure(
 146            IApplicationBuilder app,
 147            IWebHostEnvironment env,
 148            IConfiguration appConfig)
 149        {
 22150            app.UseBaseUrlRedirection();
 151
 152            // Wrap rest of configuration so everything only listens on BaseUrl.
 22153            var config = _serverConfigurationManager.GetNetworkConfiguration();
 22154            app.Map(config.BaseUrl, mainApp =>
 22155            {
 22156                if (env.IsDevelopment())
 22157                {
 22158                    mainApp.UseDeveloperExceptionPage();
 22159                }
 22160
 22161                mainApp.UseForwardedHeaders();
 22162                mainApp.UseMiddleware<ExceptionMiddleware>();
 22163
 22164                mainApp.UseMiddleware<ResponseTimeMiddleware>();
 22165
 22166                mainApp.UseWebSockets();
 22167
 22168                mainApp.UseResponseCompression();
 22169
 22170                mainApp.UseCors();
 22171
 22172                if (config.RequireHttps && _serverApplicationHost.ListenWithHttps)
 22173                {
 22174                    mainApp.UseHttpsRedirection();
 22175                }
 22176
 22177                // This must be injected before any path related middleware.
 22178                mainApp.UsePathTrim();
 22179
 22180                if (appConfig.HostWebClient())
 22181                {
 22182                    var extensionProvider = new FileExtensionContentTypeProvider();
 22183
 22184                    // subtitles octopus requires .data, .mem files.
 22185                    extensionProvider.Mappings.Add(".data", MediaTypeNames.Application.Octet);
 22186                    extensionProvider.Mappings.Add(".mem", MediaTypeNames.Application.Octet);
 22187                    mainApp.UseDefaultFiles(new DefaultFilesOptions
 22188                    {
 22189                        FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 22190                        RequestPath = "/web"
 22191                    });
 22192                    mainApp.UseStaticFiles(new StaticFileOptions
 22193                    {
 22194                        FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 22195                        RequestPath = "/web",
 22196                        ContentTypeProvider = extensionProvider
 22197                    });
 22198
 22199                    mainApp.UseRobotsRedirection();
 22200                }
 22201
 22202                mainApp.UseStaticFiles();
 22203                mainApp.UseAuthentication();
 22204                mainApp.UseJellyfinApiSwagger(_serverConfigurationManager);
 22205                mainApp.UseQueryStringDecoding();
 22206                mainApp.UseRouting();
 22207                mainApp.UseAuthorization();
 22208
 22209                mainApp.UseLanFiltering();
 22210                mainApp.UseIPBasedAccessValidation();
 22211                mainApp.UseWebSocketHandler();
 22212                mainApp.UseServerStartupMessage();
 22213
 22214                if (_serverConfigurationManager.Configuration.EnableMetrics)
 22215                {
 22216                    // Must be registered after any middleware that could change HTTP response codes or the data will be
 22217                    mainApp.UseHttpMetrics();
 22218                }
 22219
 22220                mainApp.UseEndpoints(endpoints =>
 22221                {
 22222                    endpoints.MapControllers();
 22223                    if (_serverConfigurationManager.Configuration.EnableMetrics)
 22224                    {
 22225                        endpoints.MapMetrics();
 22226                    }
 22227
 22228                    endpoints.MapHealthChecks("/health");
 22229                });
 22230            });
 22231        }
 232    }
 233}