Skip to content

Commit 1dce67a

Browse files
updated subpath handling
1 parent 6cf64d8 commit 1dce67a

1 file changed

Lines changed: 54 additions & 4 deletions

File tree

backend/Api/MoonfinWebController.cs

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Reflection;
2+
using System.Text.RegularExpressions;
23
using Microsoft.AspNetCore.Authorization;
34
using Microsoft.AspNetCore.Http;
45
using Microsoft.AspNetCore.Mvc;
@@ -13,6 +14,9 @@ namespace Moonfin.Server.Api;
1314
public class MoonfinWebController : ControllerBase
1415
{
1516
private readonly Assembly _assembly;
17+
private static readonly Regex BaseHrefRegex = new Regex(
18+
"<base\\s+href=\"[^\"]*\"\\s*/?>",
19+
RegexOptions.IgnoreCase | RegexOptions.Compiled);
1620
private static readonly IReadOnlyDictionary<string, string> ContentTypes =
1721
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
1822
{
@@ -52,8 +56,10 @@ public MoonfinWebController()
5256
[ProducesResponseType(StatusCodes.Status200OK)]
5357
public IActionResult RedirectLegacyPluginJs()
5458
{
55-
const string script =
56-
"(function(){if(window.location.pathname.toLowerCase().indexOf('/moonfin/web/')===-1){window.location.href='/Moonfin/Web/';}})();";
59+
var target = ResolveWebBaseHref();
60+
var script =
61+
"(function(){if(window.location.pathname.toLowerCase().indexOf('/moonfin/web/')===-1){window.location.href='"
62+
+ target + "';}})();";
5763
return Content(script, "application/javascript");
5864
}
5965

@@ -140,6 +146,11 @@ public IActionResult GetWebAsset([FromRoute] string? path)
140146

141147
if (System.IO.File.Exists(fullPath))
142148
{
149+
if (IsIndexHtml(fullPath))
150+
{
151+
return ServeIndexHtml(fullPath);
152+
}
153+
143154
return PhysicalFile(fullPath, GetContentType(fullPath));
144155
}
145156

@@ -148,7 +159,7 @@ public IActionResult GetWebAsset([FromRoute] string? path)
148159
var nestedIndexPath = Path.Combine(fullPath, "index.html");
149160
if (System.IO.File.Exists(nestedIndexPath))
150161
{
151-
return PhysicalFile(nestedIndexPath, "text/html; charset=utf-8");
162+
return ServeIndexHtml(nestedIndexPath);
152163
}
153164
}
154165

@@ -163,7 +174,7 @@ public IActionResult GetWebAsset([FromRoute] string? path)
163174
return NotFound(new { Error = "Moonfin web entrypoint missing", Path = indexPath });
164175
}
165176

166-
return PhysicalFile(indexPath, "text/html; charset=utf-8");
177+
return ServeIndexHtml(indexPath);
167178
}
168179

169180
private static string? NormalizeOptionalText(string? value)
@@ -182,6 +193,45 @@ private string ResolveRuntimeBaseUrl()
182193
return baseUrl.TrimEnd('/');
183194
}
184195

196+
/// <summary>
197+
/// Resolves the absolute path the web app is served from, including any Jellyfin
198+
/// reverse-proxy sub-path prefix (Request.PathBase). Used to rewrite the index.html
199+
/// base href so the app works under both subdomain and sub-path hosting.
200+
/// </summary>
201+
private string ResolveWebBaseHref()
202+
{
203+
var pathBase = Request.PathBase.Value?.TrimEnd('/') ?? string.Empty;
204+
return $"{pathBase}/Moonfin/Web/";
205+
}
206+
207+
private static bool IsIndexHtml(string filePath)
208+
{
209+
return string.Equals(
210+
Path.GetFileName(filePath),
211+
"index.html",
212+
StringComparison.OrdinalIgnoreCase);
213+
}
214+
215+
private IActionResult ServeIndexHtml(string indexPath)
216+
{
217+
var pathBase = Request.PathBase.Value?.TrimEnd('/') ?? string.Empty;
218+
if (pathBase.Length == 0)
219+
{
220+
// No reverse-proxy sub-path: the build-time base href is already correct,
221+
// so serve the file unchanged (identical to standard subdomain/root hosting).
222+
return PhysicalFile(indexPath, "text/html; charset=utf-8");
223+
}
224+
225+
var html = System.IO.File.ReadAllText(indexPath);
226+
html = BaseHrefRegex.Replace(html, _ => $"<base href=\"{pathBase}/Moonfin/Web/\">");
227+
228+
Response.Headers["Cache-Control"] = "no-store, no-cache, must-revalidate";
229+
Response.Headers["Pragma"] = "no-cache";
230+
Response.Headers["Expires"] = "0";
231+
232+
return Content(html, "text/html; charset=utf-8");
233+
}
234+
185235
private static string ResolveDiscoveryProxyUrl(string runtimeBaseUrl)
186236
{
187237
return $"{runtimeBaseUrl}/Moonfin/Discovery/";

0 commit comments

Comments
 (0)