Files
kawa e190e40b07 Force request host/scheme to App__Domain behind a proxy
The cookie login redirect and other absolute URLs are built from Request.Host;
behind a proxy that doesn't forward the Host header that's the internal IP:port,
so hitting the domain 302'd to the server IP. Rewrite scheme+host to App__Domain
on every request (after UseForwardedHeaders) so all generated URLs stay on the
public domain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 15:54:30 +02:00

37 lines
1.4 KiB
C#

namespace SharepointToolbox.Web.Core.Config;
/// <summary>
/// The app's public domain (e.g. <c>sptb.example.com</c> or <c>https://sptb.example.com</c>),
/// configured via <c>App__Domain</c>. Used to derive the SharePoint-connect redirect URI when
/// <see cref="ClientConnectOptions.RedirectUri"/> isn't set explicitly.
/// </summary>
public class AppDomainOptions
{
public string Domain { get; set; } = string.Empty;
/// <summary>
/// Builds an absolute URL for <paramref name="path"/> rooted at the configured domain, or
/// <c>null</c> when no domain is set. Defaults to <c>https</c> when the domain has no scheme,
/// and tolerates accidental surrounding quotes / trailing slashes (docker-compose's list-form
/// env values can embed literal quotes).
/// </summary>
public string? BuildUrl(string path)
{
var domain = Domain?.Trim().Trim('"', '\'').TrimEnd('/');
if (string.IsNullOrEmpty(domain))
return null;
if (!domain.Contains("://", StringComparison.Ordinal))
domain = "https://" + domain;
return domain + "/" + path.TrimStart('/');
}
/// <summary>
/// The configured domain as an absolute base <see cref="Uri"/> (scheme + host [+ port]), or
/// <c>null</c> when no domain is set or it can't be parsed.
/// </summary>
public Uri? GetBaseUri() =>
BuildUrl("/") is { } url && Uri.TryCreate(url, UriKind.Absolute, out var uri) ? uri : null;
}