aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server/Startup.cs
blob: cbc1c040cb1221a92857c9aeb114a702c1745233 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
using System;
using System.ComponentModel;
using System.Net.Http.Headers;
using Jellyfin.Api.TypeConverters;
using Jellyfin.Server.Extensions;
using Jellyfin.Server.Middleware;
using Jellyfin.Server.Models;
using MediaBrowser.Common;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
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 IApplicationHost _applicationHost;

        /// <summary>
        /// Initializes a new instance of the <see cref="Startup" /> class.
        /// </summary>
        /// <param name="serverConfigurationManager">The server configuration manager.</param>
        /// <param name="applicationHost">The application host.</param>
        public Startup(IServerConfigurationManager serverConfigurationManager, IApplicationHost applicationHost)
        {
            _serverConfigurationManager = serverConfigurationManager;
            _applicationHost = applicationHost;
        }

        /// <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.AddJellyfinApi(_serverConfigurationManager.Configuration.BaseUrl.TrimStart('/'), _applicationHost.GetApiPluginAssemblies());

            services.AddJellyfinApiSwagger();

            // configure custom legacy authentication
            services.AddCustomAuthentication();

            services.AddJellyfinApiAuthorization();

            var productHeader = new ProductInfoHeaderValue(_applicationHost.Name.Replace(' ', '-'), _applicationHost.ApplicationVersionString);
            services
                .AddHttpClient(NamedClient.Default, c =>
                {
                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
                })
                .ConfigurePrimaryHttpMessageHandler(x => new DefaultHttpClientHandler());

            services.AddHttpClient(NamedClient.MusicBrainz, c =>
                {
                    c.DefaultRequestHeaders.UserAgent.Add(productHeader);
                    c.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue($"({_applicationHost.ApplicationUserAgentAddress})"));
                })
                .ConfigurePrimaryHttpMessageHandler(x => new DefaultHttpClientHandler());
        }

        /// <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="serverApplicationHost">The server application host.</param>
        public void Configure(
            IApplicationBuilder app,
            IWebHostEnvironment env,
            IServerApplicationHost serverApplicationHost)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMiddleware<ExceptionMiddleware>();

            app.UseMiddleware<ResponseTimeMiddleware>();

            app.UseWebSockets();

            app.UseResponseCompression();

            // TODO app.UseMiddleware<WebSocketMiddleware>();

            app.UseAuthentication();
            app.UseJellyfinApiSwagger(_serverConfigurationManager);
            app.UseRouting();
            app.UseCors(ServerCorsPolicy.DefaultPolicyName);
            app.UseAuthorization();
            if (_serverConfigurationManager.Configuration.EnableMetrics)
            {
                // Must be registered after any middleware that could chagne HTTP response codes or the data will be bad
                app.UseHttpMetrics();
            }

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                if (_serverConfigurationManager.Configuration.EnableMetrics)
                {
                    endpoints.MapMetrics(_serverConfigurationManager.Configuration.BaseUrl.TrimStart('/') + "/metrics");
                }
            });

            app.Use(serverApplicationHost.ExecuteHttpHandlerAsync);

            // Add type descriptor for legacy datetime parsing.
            TypeDescriptor.AddAttributes(typeof(DateTime?), new TypeConverterAttribute(typeof(DateTimeTypeConverter)));
        }
    }
}