aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server/Startup.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Server/Startup.cs')
-rw-r--r--Jellyfin.Server/Startup.cs197
1 files changed, 197 insertions, 0 deletions
diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs
new file mode 100644
index 000000000..8085c2630
--- /dev/null
+++ b/Jellyfin.Server/Startup.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Net.Mime;
+using System.Text;
+using Jellyfin.Networking.Configuration;
+using Jellyfin.Server.Extensions;
+using Jellyfin.Server.Implementations;
+using Jellyfin.Server.Infrastructure;
+using Jellyfin.Server.Middleware;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Extensions;
+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 IServerConfigurationManager _serverConfigurationManager;
+ private readonly IServerApplicationHost _serverApplicationHost;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Startup" /> class.
+ /// </summary>
+ /// <param name="serverConfigurationManager">The server configuration manager.</param>
+ /// <param name="serverApplicationHost">The server application host.</param>
+ public Startup(
+ IServerConfigurationManager serverConfigurationManager,
+ IServerApplicationHost serverApplicationHost)
+ {
+ _serverConfigurationManager = serverConfigurationManager;
+ _serverApplicationHost = serverApplicationHost;
+ }
+
+ /// <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.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> 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(defaultHttpClientHandlerDelegate);
+
+ 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(defaultHttpClientHandlerDelegate);
+
+ services.AddHealthChecks()
+ .AddDbContextCheck<JellyfinDb>();
+ }
+
+ /// <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();
+ mainApp.UseStaticFiles();
+ 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.UseStaticFiles(new StaticFileOptions
+ {
+ FileProvider = new PhysicalFileProvider(_serverConfigurationManager.ApplicationPaths.WebPath),
+ RequestPath = "/web",
+ ContentTypeProvider = extensionProvider
+ });
+
+ mainApp.UseRobotsRedirection();
+ }
+
+ 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("/metrics");
+ }
+
+ endpoints.MapHealthChecks("/health");
+ });
+ });
+ }
+ }
+}