using System; using System.Threading.Tasks; using Jellyfin.Networking.Configuration; using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using ConfigurationExtensions = MediaBrowser.Controller.Extensions.ConfigurationExtensions; namespace Jellyfin.Server.Middleware { /// /// Redirect requests without baseurl prefix to the baseurl prefixed URL. /// public class BaseUrlRedirectionMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; private readonly IConfiguration _configuration; /// /// Initializes a new instance of the class. /// /// The next delegate in the pipeline. /// The logger. /// The application configuration. public BaseUrlRedirectionMiddleware( RequestDelegate next, ILogger logger, IConfiguration configuration) { _next = next; _logger = logger; _configuration = configuration; } /// /// Executes the middleware action. /// /// The current HTTP context. /// The server configuration manager. /// The async task. public async Task Invoke(HttpContext httpContext, IServerConfigurationManager serverConfigurationManager) { var localPath = httpContext.Request.Path.ToString(); var baseUrlPrefix = serverConfigurationManager.GetNetworkConfiguration().BaseUrl; if (string.Equals(localPath, baseUrlPrefix + "/", StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, baseUrlPrefix, StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase) || string.IsNullOrEmpty(localPath) || !localPath.StartsWith(baseUrlPrefix, StringComparison.OrdinalIgnoreCase)) { // Always redirect back to the default path if the base prefix is invalid or missing _logger.LogDebug("Normalizing an URL at {LocalPath}", localPath); httpContext.Response.Redirect(baseUrlPrefix + "/" + _configuration[ConfigurationExtensions.DefaultRedirectKey]); return; } await _next(httpContext).ConfigureAwait(false); } } }