| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 | 
							- using System;
 
- using System.Net;
 
- using System.Net.Http;
 
- using System.Net.Http.Headers;
 
- using System.Net.Mime;
 
- using System.Text;
 
- using Emby.Server.Implementations.EntryPoints;
 
- using Jellyfin.Api.Middleware;
 
- using Jellyfin.Database.Implementations;
 
- using Jellyfin.LiveTv.Extensions;
 
- using Jellyfin.LiveTv.Recordings;
 
- using Jellyfin.MediaEncoding.Hls.Extensions;
 
- using Jellyfin.Networking;
 
- using Jellyfin.Networking.HappyEyeballs;
 
- using Jellyfin.Server.Extensions;
 
- using Jellyfin.Server.HealthChecks;
 
- using Jellyfin.Server.Implementations.Extensions;
 
- using Jellyfin.Server.Infrastructure;
 
- using MediaBrowser.Common.Net;
 
- using MediaBrowser.Controller.Configuration;
 
- using MediaBrowser.Controller.Extensions;
 
- using MediaBrowser.XbmcMetadata;
 
- using Microsoft.AspNetCore.Builder;
 
- using Microsoft.AspNetCore.Hosting;
 
- using Microsoft.AspNetCore.Mvc;
 
- using Microsoft.AspNetCore.Mvc.Infrastructure;
 
- using Microsoft.AspNetCore.StaticFiles;
 
- using Microsoft.Extensions.Configuration;
 
- using Microsoft.Extensions.DependencyInjection;
 
- using Microsoft.Extensions.FileProviders;
 
- using Microsoft.Extensions.Hosting;
 
- using Prometheus;
 
- namespace Jellyfin.Server
 
- {
 
-     /// <summary>
 
-     /// Startup configuration for the Kestrel webhost.
 
-     /// </summary>
 
-     public class Startup
 
-     {
 
-         private readonly CoreAppHost _serverApplicationHost;
 
-         private readonly IConfiguration _configuration;
 
-         private readonly IServerConfigurationManager _serverConfigurationManager;
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="Startup" /> class.
 
-         /// </summary>
 
-         /// <param name="appHost">The server application host.</param>
 
-         /// <param name="configuration">The used Configuration.</param>
 
-         public Startup(CoreAppHost appHost, IConfiguration configuration)
 
-         {
 
-             _serverApplicationHost = appHost;
 
-             _configuration = configuration;
 
-             _serverConfigurationManager = appHost.ConfigurationManager;
 
-         }
 
-         /// <summary>
 
-         /// Configures the service collection for the webhost.
 
-         /// </summary>
 
-         /// <param name="services">The service collection.</param>
 
-         public void ConfigureServices(IServiceCollection services)
 
-         {
 
-             services.AddResponseCompression();
 
-             services.AddHttpContextAccessor();
 
-             services.AddHttpsRedirection(options =>
 
-             {
 
-                 options.HttpsPort = _serverApplicationHost.HttpsPort;
 
-             });
 
-             // TODO remove once this is fixed upstream https://github.com/dotnet/aspnetcore/issues/34371
 
-             services.AddSingleton<IActionResultExecutor<PhysicalFileResult>, SymlinkFollowingPhysicalFileResultExecutor>();
 
-             services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration());
 
-             services.AddJellyfinDbContext(_serverApplicationHost.ConfigurationManager, _configuration);
 
-             services.AddJellyfinApiSwagger();
 
-             // configure custom legacy authentication
 
-             services.AddCustomAuthentication();
 
-             services.AddJellyfinApiAuthorization();
 
-             var productHeader = new ProductInfoHeaderValue(
 
-                 _serverApplicationHost.Name.Replace(' ', '-'),
 
-                 _serverApplicationHost.ApplicationVersionString);
 
-             var acceptJsonHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json, 1.0);
 
-             var acceptXmlHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Xml, 0.9);
 
-             var acceptAnyHeader = new MediaTypeWithQualityHeaderValue("*/*", 0.8);
 
-             Func<IServiceProvider, HttpMessageHandler> eyeballsHttpClientHandlerDelegate = (_) => new SocketsHttpHandler()
 
-             {
 
-                 AutomaticDecompression = DecompressionMethods.All,
 
-                 RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8,
 
-                 ConnectCallback = HttpClientExtension.OnConnect
 
-             };
 
-             Func<IServiceProvider, HttpMessageHandler> defaultHttpClientHandlerDelegate = (_) => new SocketsHttpHandler()
 
-             {
 
-                 AutomaticDecompression = DecompressionMethods.All,
 
-                 RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8
 
-             };
 
-             services.AddHttpClient(NamedClient.Default, c =>
 
-                 {
 
-                     c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 
-                     c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 
-                     c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 
-                     c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 
-                 })
 
-                 .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 
-             services.AddHttpClient(NamedClient.MusicBrainz, c =>
 
-                 {
 
-                     c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 
-                     c.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue($"({_serverApplicationHost.ApplicationUserAgentAddress})"));
 
-                     c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 
-                     c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 
-                 })
 
-                 .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate);
 
-             services.AddHttpClient(NamedClient.DirectIp, c =>
 
-                 {
 
-                     c.DefaultRequestHeaders.UserAgent.Add(productHeader);
 
-                     c.DefaultRequestHeaders.Accept.Add(acceptJsonHeader);
 
-                     c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
 
-                     c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
 
-                 })
 
-                 .ConfigurePrimaryHttpMessageHandler(defaultHttpClientHandlerDelegate);
 
-             services.AddHealthChecks()
 
-                 .AddCheck<DbContextFactoryHealthCheck<JellyfinDbContext>>(nameof(JellyfinDbContext));
 
-             services.AddHlsPlaylistGenerator();
 
-             services.AddLiveTvServices();
 
-             services.AddHostedService<RecordingsHost>();
 
-             services.AddHostedService<AutoDiscoveryHost>();
 
-             services.AddHostedService<NfoUserDataSaver>();
 
-             services.AddHostedService<LibraryChangedNotifier>();
 
-             services.AddHostedService<UserDataChangeNotifier>();
 
-             services.AddHostedService<RecordingNotifier>();
 
-         }
 
-         /// <summary>
 
-         /// Configures the app builder for the webhost.
 
-         /// </summary>
 
-         /// <param name="app">The application builder.</param>
 
-         /// <param name="env">The webhost environment.</param>
 
-         /// <param name="appConfig">The application config.</param>
 
-         public void Configure(
 
-             IApplicationBuilder app,
 
-             IWebHostEnvironment env,
 
-             IConfiguration appConfig)
 
-         {
 
-             app.UseBaseUrlRedirection();
 
-             // Wrap rest of configuration so everything only listens on BaseUrl.
 
-             var config = _serverConfigurationManager.GetNetworkConfiguration();
 
-             app.Map(config.BaseUrl, mainApp =>
 
-             {
 
-                 if (env.IsDevelopment())
 
-                 {
 
-                     mainApp.UseDeveloperExceptionPage();
 
-                 }
 
-                 mainApp.UseForwardedHeaders();
 
-                 mainApp.UseMiddleware<ExceptionMiddleware>();
 
-                 mainApp.UseMiddleware<ResponseTimeMiddleware>();
 
-                 mainApp.UseWebSockets();
 
-                 mainApp.UseResponseCompression();
 
-                 mainApp.UseCors();
 
-                 if (config.RequireHttps && _serverApplicationHost.ListenWithHttps)
 
-                 {
 
-                     mainApp.UseHttpsRedirection();
 
-                 }
 
-                 // This must be injected before any path related middleware.
 
-                 mainApp.UsePathTrim();
 
-                 if (appConfig.HostWebClient())
 
-                 {
 
-                     var extensionProvider = new FileExtensionContentTypeProvider();
 
-                     // subtitles octopus requires .data, .mem files.
 
-                     extensionProvider.Mappings.Add(".data", MediaTypeNames.Application.Octet);
 
-                     extensionProvider.Mappings.Add(".mem", MediaTypeNames.Application.Octet);
 
-                     mainApp.UseDefaultFiles(new DefaultFilesOptions
 
-                     {
 
-                         FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 
-                         RequestPath = "/web"
 
-                     });
 
-                     mainApp.UseStaticFiles(new StaticFileOptions
 
-                     {
 
-                         FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
 
-                         RequestPath = "/web",
 
-                         ContentTypeProvider = extensionProvider
 
-                     });
 
-                     mainApp.UseRobotsRedirection();
 
-                 }
 
-                 mainApp.UseStaticFiles();
 
-                 mainApp.UseAuthentication();
 
-                 mainApp.UseJellyfinApiSwagger(_serverConfigurationManager);
 
-                 mainApp.UseQueryStringDecoding();
 
-                 mainApp.UseRouting();
 
-                 mainApp.UseAuthorization();
 
-                 mainApp.UseLanFiltering();
 
-                 mainApp.UseIPBasedAccessValidation();
 
-                 mainApp.UseWebSocketHandler();
 
-                 mainApp.UseServerStartupMessage();
 
-                 if (_serverConfigurationManager.Configuration.EnableMetrics)
 
-                 {
 
-                     // Must be registered after any middleware that could change HTTP response codes or the data will be bad
 
-                     mainApp.UseHttpMetrics();
 
-                 }
 
-                 mainApp.UseEndpoints(endpoints =>
 
-                 {
 
-                     endpoints.MapControllers();
 
-                     if (_serverConfigurationManager.Configuration.EnableMetrics)
 
-                     {
 
-                         endpoints.MapMetrics();
 
-                     }
 
-                     endpoints.MapHealthChecks("/health");
 
-                 });
 
-             });
 
-         }
 
-     }
 
- }
 
 
  |