using System; using System.Threading.Tasks; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; namespace Jellyfin.Api.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.IsNullOrEmpty(localPath) || string.Equals(localPath, baseUrlPrefix, StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, baseUrlPrefix + "/", StringComparison.OrdinalIgnoreCase) || !localPath.StartsWith(baseUrlPrefix, StringComparison.OrdinalIgnoreCase) ) { // Redirect health endpoint if (string.Equals(localPath, "/health", StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, "/health/", StringComparison.OrdinalIgnoreCase)) { _logger.LogDebug("Redirecting /health check"); httpContext.Response.Redirect(baseUrlPrefix + "/health"); return; } // Always redirect back to the default path if the base prefix is invalid or missing _logger.LogDebug("Normalizing an URL at {LocalPath}", localPath); var port = httpContext.Request.Host.Port ?? -1; var uri = new UriBuilder(httpContext.Request.Scheme, httpContext.Request.Host.Host, port, localPath).Uri; var redirectUri = new UriBuilder(httpContext.Request.Scheme, httpContext.Request.Host.Host, port, baseUrlPrefix + "/" + _configuration[DefaultRedirectKey]).Uri; var target = uri.MakeRelativeUri(redirectUri).ToString(); _logger.LogDebug("Redirecting to {Target}", target); httpContext.Response.Redirect(target); return; } await _next(httpContext).ConfigureAwait(false); } }