mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-05-24 02:02:29 -04:00
Allow for dynamic cors response
This commit is contained in:
parent
0424d09b8d
commit
3c0484cc97
@ -135,13 +135,17 @@ namespace Jellyfin.Server.Extensions
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection">The service collection.</param>
|
||||
/// <param name="baseUrl">The base url for the API.</param>
|
||||
/// <param name="corsHosts">The configured cors hosts.</param>
|
||||
/// <returns>The MVC builder.</returns>
|
||||
public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl)
|
||||
public static IMvcBuilder AddJellyfinApi(
|
||||
this IServiceCollection serviceCollection,
|
||||
string baseUrl,
|
||||
string[] corsHosts)
|
||||
{
|
||||
return serviceCollection
|
||||
.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(ServerCorsPolicy.DefaultPolicyName, ServerCorsPolicy.DefaultPolicy);
|
||||
options.AddPolicy(ServerCorsPolicy.DefaultPolicyName, new ServerCorsPolicy(corsHosts).Policy);
|
||||
})
|
||||
.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
|
68
Jellyfin.Server/Middleware/DynamicCorsMiddleware.cs
Normal file
68
Jellyfin.Server/Middleware/DynamicCorsMiddleware.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Jellyfin.Server.Middleware
|
||||
{
|
||||
/// <summary>
|
||||
/// Dynamic cors middleware.
|
||||
/// </summary>
|
||||
public class DynamicCorsMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly ILogger<DynamicCorsMiddleware> _logger;
|
||||
private readonly CorsMiddleware _corsMiddleware;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DynamicCorsMiddleware"/> class.
|
||||
/// </summary>
|
||||
/// <param name="next">Next request delegate.</param>
|
||||
/// <param name="corsService">Instance of the <see cref="ICorsService"/> interface.</param>
|
||||
/// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
|
||||
/// <param name="policyName">The cors policy name.</param>
|
||||
public DynamicCorsMiddleware(
|
||||
RequestDelegate next,
|
||||
ICorsService corsService,
|
||||
ILoggerFactory loggerFactory,
|
||||
string policyName)
|
||||
{
|
||||
_corsMiddleware = new CorsMiddleware(next, corsService, loggerFactory, policyName);
|
||||
_next = next;
|
||||
_logger = loggerFactory.CreateLogger<DynamicCorsMiddleware>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoke request.
|
||||
/// </summary>
|
||||
/// <param name="context">Request context.</param>
|
||||
/// <param name="corsPolicyProvider">Instance of the <see cref="ICorsPolicyProvider"/> interface.</param>
|
||||
/// <returns>Task.</returns>
|
||||
///
|
||||
public async Task Invoke(HttpContext context, ICorsPolicyProvider corsPolicyProvider)
|
||||
{
|
||||
// Only execute if is preflight request.
|
||||
if (string.Equals(context.Request.Method, CorsConstants.PreflightHttpMethod, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Invoke original cors middleware.
|
||||
await _corsMiddleware.Invoke(context, corsPolicyProvider).ConfigureAwait(false);
|
||||
if (context.Response.Headers.TryGetValue(HeaderNames.AccessControlAllowOrigin, out var headerValue)
|
||||
&& string.Equals(headerValue, "*", StringComparison.Ordinal))
|
||||
{
|
||||
context.Response.Headers[HeaderNames.AccessControlAllowOrigin] = context.Request.Host.Value;
|
||||
_logger.LogDebug("Overwriting CORS response header: {HeaderName}: {HeaderValue}", HeaderNames.AccessControlAllowOrigin, context.Request.Host.Value);
|
||||
|
||||
if (!context.Response.Headers.ContainsKey(HeaderNames.AccessControlAllowCredentials))
|
||||
{
|
||||
context.Response.Headers[HeaderNames.AccessControlAllowCredentials] = "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the next delegate/middleware in the pipeline
|
||||
await this._next(context).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +1,47 @@
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||
|
||||
namespace Jellyfin.Server.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Server Cors Policy.
|
||||
/// </summary>
|
||||
public static class ServerCorsPolicy
|
||||
public class ServerCorsPolicy
|
||||
{
|
||||
/// <summary>
|
||||
/// Default policy name.
|
||||
/// </summary>
|
||||
public const string DefaultPolicyName = "DefaultCorsPolicy";
|
||||
public const string DefaultPolicyName = nameof(ServerCorsPolicy);
|
||||
|
||||
/// <summary>
|
||||
/// Default Policy. Allow Everything.
|
||||
/// Initializes a new instance of the <see cref="ServerCorsPolicy"/> class.
|
||||
/// </summary>
|
||||
public static readonly CorsPolicy DefaultPolicy = new CorsPolicy
|
||||
/// <param name="corsHosts">The configured cors hosts.</param>
|
||||
public ServerCorsPolicy(string[] corsHosts)
|
||||
{
|
||||
// Allow any origin
|
||||
Origins = { "*" },
|
||||
var builder = new CorsPolicyBuilder()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
|
||||
// Allow any method
|
||||
Methods = { "*" },
|
||||
// No hosts configured or only default configured.
|
||||
if (corsHosts.Length == 0
|
||||
|| (corsHosts.Length == 1
|
||||
&& string.Equals(corsHosts[0], "*", StringComparison.Ordinal)))
|
||||
{
|
||||
builder.AllowAnyOrigin();
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.WithOrigins(corsHosts)
|
||||
.AllowCredentials();
|
||||
}
|
||||
|
||||
// Allow any header
|
||||
Headers = { "*" }
|
||||
};
|
||||
Policy = builder.Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cors policy.
|
||||
/// </summary>
|
||||
public CorsPolicy Policy { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,9 @@ namespace Jellyfin.Server
|
||||
{
|
||||
services.AddResponseCompression();
|
||||
services.AddHttpContextAccessor();
|
||||
services.AddJellyfinApi(_serverConfigurationManager.Configuration.BaseUrl.TrimStart('/'));
|
||||
services.AddJellyfinApi(
|
||||
_serverConfigurationManager.Configuration.BaseUrl.TrimStart('/'),
|
||||
_serverConfigurationManager.Configuration.CorsHosts);
|
||||
|
||||
services.AddJellyfinApiSwagger();
|
||||
|
||||
@ -78,11 +80,11 @@ namespace Jellyfin.Server
|
||||
app.UseAuthentication();
|
||||
app.UseJellyfinApiSwagger(_serverConfigurationManager);
|
||||
app.UseRouting();
|
||||
app.UseCors(ServerCorsPolicy.DefaultPolicyName);
|
||||
app.UseMiddleware<DynamicCorsMiddleware>(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
|
||||
// Must be registered after any middleware that could change HTTP response codes or the data will be bad
|
||||
app.UseHttpMetrics();
|
||||
}
|
||||
|
||||
|
@ -264,6 +264,11 @@ namespace MediaBrowser.Model.Configuration
|
||||
/// </summary>
|
||||
public long SlowResponseThresholdMs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cors hosts.
|
||||
/// </summary>
|
||||
public string[] CorsHosts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
||||
/// </summary>
|
||||
@ -372,6 +377,7 @@ namespace MediaBrowser.Model.Configuration
|
||||
|
||||
EnableSlowResponseWarning = true;
|
||||
SlowResponseThresholdMs = 500;
|
||||
CorsHosts = new[] { "*" };
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user