This repository has been archived by the owner on Jul 17, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
Adjusting absolute URLs in services
Christian Weiss edited this page Feb 20, 2016
·
1 revision
The gateway doesn't rewrite absolute URLs which are returned by the target service. Your services therefore must adjust them according to the sent proxy headers.
Typical examples for absolute URLs in APIs are API descriptions like Swagger.
If you use "Swashbuckle" (Swagger for ASP.NET) you can overwrite the base url
by setting c.RootUrl(req => GetRootUrl(req));
with the following implementation:
private static string GetRootUrl(HttpRequestMessage request)
{
string scheme = null;
string host = null;
// Is there a "Forwarded" header?
string forwarded = GetHeaderValue(request, "Forwarded");
if (forwarded != null)
{
string[] parts = forwarded.Replace(" ", "").Split(';');
foreach (var part in parts)
{
if (part != null && part.StartsWith("host=", StringComparison.OrdinalIgnoreCase))
{
host = part.Substring("host=".Length);
if (host == string.Empty) host = null;
}
if (part != null && part.StartsWith("proto=", StringComparison.OrdinalIgnoreCase))
{
scheme = part.Substring("proto=".Length);
if (scheme == string.Empty) scheme = null;
}
}
}
// Fallback to non-standard "X-Forwarded-Host"/"Port"
string xForwardedHost = GetHeaderValue(request, "X-Forwarded-Host");
if (host == null && xForwardedHost != null)
{
host = xForwardedHost;
// in case there was no port in the host
string xForwardedPort = GetHeaderValue(request, "X-Forwarded-Port");
if (host.IndexOf(':') < 0 && xForwardedPort != null)
{
host += ":" + xForwardedPort;
}
}
// take the current URI if there was no header
scheme = scheme ?? GetHeaderValue(request, "X-Forwarded-Proto") ?? request.RequestUri.Scheme;
host = host ?? (request.RequestUri.Host + ":" + request.RequestUri.Port.ToString());
// relative path (Swashbuckle doesn't allow a trailing '/')
string path = GetHeaderValue(request, "X-Forwarded-PathBase") ?? request.GetRequestContext().VirtualPathRoot.ToString();
path = "/" + path.TrimStart('/');
path = path.TrimEnd('/');
return $"{scheme}://{host}{path}";
}
private static string GetHeaderValue(HttpRequestMessage request, string headerName)
{
IEnumerable<string> list;
return request.Headers.TryGetValues(headerName, out list) ? list.FirstOrDefault() : null;
}