aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server/Extensions
diff options
context:
space:
mode:
authornyanmisaka <nst799610810@gmail.com>2020-11-08 19:11:54 +0800
committernyanmisaka <nst799610810@gmail.com>2020-11-08 19:11:54 +0800
commit737cb727f9f943f8bb55fca8a5c5023a98aca2d7 (patch)
tree8858a423545a03d0f7dfe5c1d1b0ae1157d62c5e /Jellyfin.Server/Extensions
parent05e78ee78c56364971956507f6239ded61f0af87 (diff)
parent96dcd9c87e2eb4b14004368856949e9fde2db261 (diff)
Merge remote-tracking branch 'upstream/master' into fonts
Diffstat (limited to 'Jellyfin.Server/Extensions')
-rw-r--r--Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs66
-rw-r--r--Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs66
2 files changed, 115 insertions, 17 deletions
diff --git a/Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs b/Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs
index 745567703..c7fbfa4d0 100644
--- a/Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs
+++ b/Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs
@@ -1,5 +1,8 @@
+using System.Collections.Generic;
+using Jellyfin.Server.Middleware;
using MediaBrowser.Controller.Configuration;
using Microsoft.AspNetCore.Builder;
+using Microsoft.OpenApi.Models;
namespace Jellyfin.Server.Extensions
{
@@ -22,6 +25,7 @@ namespace Jellyfin.Server.Extensions
// specifying the Swagger JSON endpoint.
var baseUrl = serverConfigurationManager.Configuration.BaseUrl.Trim('/');
+ var apiDocBaseUrl = serverConfigurationManager.Configuration.BaseUrl;
if (!string.IsNullOrEmpty(baseUrl))
{
baseUrl += '/';
@@ -31,20 +35,76 @@ namespace Jellyfin.Server.Extensions
.UseSwagger(c =>
{
// Custom path requires {documentName}, SwaggerDoc documentName is 'api-docs'
- c.RouteTemplate = $"/{baseUrl}{{documentName}}/openapi.json";
+ c.RouteTemplate = "{documentName}/openapi.json";
+ c.PreSerializeFilters.Add((swagger, httpReq) =>
+ {
+ swagger.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}{apiDocBaseUrl}" } };
+ });
})
.UseSwaggerUI(c =>
{
c.DocumentTitle = "Jellyfin API";
c.SwaggerEndpoint($"/{baseUrl}api-docs/openapi.json", "Jellyfin API");
- c.RoutePrefix = $"{baseUrl}api-docs/swagger";
+ c.InjectStylesheet($"/{baseUrl}api-docs/swagger/custom.css");
+ c.RoutePrefix = "api-docs/swagger";
})
.UseReDoc(c =>
{
c.DocumentTitle = "Jellyfin API";
c.SpecUrl($"/{baseUrl}api-docs/openapi.json");
- c.RoutePrefix = $"{baseUrl}api-docs/redoc";
+ c.InjectStylesheet($"/{baseUrl}api-docs/redoc/custom.css");
+ c.RoutePrefix = "api-docs/redoc";
});
}
+
+ /// <summary>
+ /// Adds IP based access validation to the application pipeline.
+ /// </summary>
+ /// <param name="appBuilder">The application builder.</param>
+ /// <returns>The updated application builder.</returns>
+ public static IApplicationBuilder UseIpBasedAccessValidation(this IApplicationBuilder appBuilder)
+ {
+ return appBuilder.UseMiddleware<IpBasedAccessValidationMiddleware>();
+ }
+
+ /// <summary>
+ /// Adds LAN based access filtering to the application pipeline.
+ /// </summary>
+ /// <param name="appBuilder">The application builder.</param>
+ /// <returns>The updated application builder.</returns>
+ public static IApplicationBuilder UseLanFiltering(this IApplicationBuilder appBuilder)
+ {
+ return appBuilder.UseMiddleware<LanFilteringMiddleware>();
+ }
+
+ /// <summary>
+ /// Adds base url redirection to the application pipeline.
+ /// </summary>
+ /// <param name="appBuilder">The application builder.</param>
+ /// <returns>The updated application builder.</returns>
+ public static IApplicationBuilder UseBaseUrlRedirection(this IApplicationBuilder appBuilder)
+ {
+ return appBuilder.UseMiddleware<BaseUrlRedirectionMiddleware>();
+ }
+
+ /// <summary>
+ /// Adds a custom message during server startup to the application pipeline.
+ /// </summary>
+ /// <param name="appBuilder">The application builder.</param>
+ /// <returns>The updated application builder.</returns>
+ public static IApplicationBuilder UseServerStartupMessage(this IApplicationBuilder appBuilder)
+ {
+ return appBuilder.UseMiddleware<ServerStartupMessageMiddleware>();
+ }
+
+ /// <summary>
+ /// Adds a WebSocket request handler to the application pipeline.
+ /// </summary>
+ /// <param name="appBuilder">The application builder.</param>
+ /// <returns>The updated application builder.</returns>
+ public static IApplicationBuilder UseWebSocketHandler(this IApplicationBuilder appBuilder)
+ {
+ return appBuilder.UseMiddleware<WebSocketHandlerMiddleware>();
+ }
}
}
diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
index 2e2bfea68..cc98955df 100644
--- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
+++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
@@ -2,8 +2,9 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net;
using System.Reflection;
-using Jellyfin.Api;
+using Emby.Server.Implementations;
using Jellyfin.Api.Auth;
using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
using Jellyfin.Api.Auth.DownloadPolicy;
@@ -16,17 +17,22 @@ using Jellyfin.Api.Auth.LocalAccessPolicy;
using Jellyfin.Api.Auth.RequiresElevationPolicy;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Controllers;
+using Jellyfin.Server.Configuration;
+using Jellyfin.Server.Filters;
using Jellyfin.Server.Formatters;
-using Jellyfin.Server.Models;
using MediaBrowser.Common.Json;
using MediaBrowser.Model.Entities;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.OpenApi.Any;
+using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
+using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes;
namespace Jellyfin.Server.Extensions
{
@@ -134,22 +140,30 @@ namespace Jellyfin.Server.Extensions
/// Extension method for adding the jellyfin API to the service collection.
/// </summary>
/// <param name="serviceCollection">The service collection.</param>
- /// <param name="baseUrl">The base url for the API.</param>
+ /// <param name="pluginAssemblies">An IEnumerable containing all plugin assemblies with API controllers.</param>
+ /// <param name="knownProxies">A list of all known proxies to trust for X-Forwarded-For.</param>
/// <returns>The MVC builder.</returns>
- public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl)
+ public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, IEnumerable<Assembly> pluginAssemblies, IReadOnlyList<string> knownProxies)
{
- return serviceCollection
- .AddCors(options =>
- {
- options.AddPolicy(ServerCorsPolicy.DefaultPolicyName, ServerCorsPolicy.DefaultPolicy);
- })
+ IMvcBuilder mvcBuilder = serviceCollection
+ .AddCors()
+ .AddTransient<ICorsPolicyProvider, CorsPolicyProvider>()
.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
+ for (var i = 0; i < knownProxies.Count; i++)
+ {
+ if (IPAddress.TryParse(knownProxies[i], out var address))
+ {
+ options.KnownProxies.Add(address);
+ }
+ }
})
.AddMvc(opts =>
{
- opts.UseGeneralRoutePrefix(baseUrl);
+ // Allow requester to change between camelCase and PascalCase
+ opts.RespectBrowserAcceptHeader = true;
+
opts.OutputFormatters.Insert(0, new CamelCaseJsonProfileFormatter());
opts.OutputFormatters.Insert(0, new PascalCaseJsonProfileFormatter());
@@ -168,6 +182,9 @@ namespace Jellyfin.Server.Extensions
// From JsonDefaults
options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling;
options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented;
+ options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition;
+ options.JsonSerializerOptions.NumberHandling = jsonOptions.NumberHandling;
+
options.JsonSerializerOptions.Converters.Clear();
foreach (var converter in jsonOptions.Converters)
{
@@ -176,8 +193,14 @@ namespace Jellyfin.Server.Extensions
// From JsonDefaults.PascalCase
options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy;
- })
- .AddControllersAsServices();
+ });
+
+ foreach (Assembly pluginAssembly in pluginAssemblies)
+ {
+ mvcBuilder.AddApplicationPart(pluginAssembly);
+ }
+
+ return mvcBuilder.AddControllersAsServices();
}
/// <summary>
@@ -189,12 +212,24 @@ namespace Jellyfin.Server.Extensions
{
return serviceCollection.AddSwaggerGen(c =>
{
- c.SwaggerDoc("api-docs", new OpenApiInfo { Title = "Jellyfin API", Version = "v1" });
+ c.SwaggerDoc("api-docs", new OpenApiInfo
+ {
+ Title = "Jellyfin API",
+ Version = "v1",
+ Extensions = new Dictionary<string, IOpenApiExtension>
+ {
+ {
+ "x-jellyfin-version",
+ new OpenApiString(typeof(ApplicationHost).Assembly.GetName().Version?.ToString())
+ }
+ }
+ });
+
c.AddSecurityDefinition(AuthenticationSchemes.CustomAuthentication, new OpenApiSecurityScheme
{
Type = SecuritySchemeType.ApiKey,
In = ParameterLocation.Header,
- Name = "X-Emby-Token",
+ Name = "X-Emby-Authorization",
Description = "API key header parameter"
});
@@ -238,6 +273,9 @@ namespace Jellyfin.Server.Extensions
// TODO - remove when all types are supported in System.Text.Json
c.AddSwaggerTypeMappings();
+
+ c.OperationFilter<FileResponseFilter>();
+ c.DocumentFilter<WebsocketModelFilter>();
});
}