-
Notifications
You must be signed in to change notification settings - Fork 636
Adding basepath to the config #6963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This will allow the aspire app to handle running behind a reverse proxy such as a k8s ingress on a subpath dotnet#4159 dotnet#4528 dotnet#5134
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add test coverage in ValidateDashboardOptions
.
@JamesNK for review |
Tests added |
rerunning the PR checks
The options changes look fine, but this is a one liner in middleware https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.usepathbaseextensions.usepathbase?view=aspnetcore-9.0. You can undo all of the other changes you made. |
@davidfowl , I'm afraid I do not follow. I am using that method in the middleware, but everything else is to handle the options and also the way we are generating the link in the blazor app. The links seem to be string interpolation from the base before |
I see what fowler means now. We don't need to store path base inside
The path base is provided in the dashboard options already. You can use that when writing out the dashboard url. |
There should be a single call to the |
We need to change the blazor client-side path base as well. |
Why? Also UsePathBase should be the first middleware (order matters). We should be able to remove the prefix in UseErrorHandler as well. |
Is blazor loading something from a rooted path? Eg Can it be changed to a relative path? |
I don’t know the right thing to do (haven’t read docs) but there are a lot of docs on this issue. Find out what is best with blazor server in this situation. |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
Im still unclear on the ask. I started with just the one liner, but it doesnt work as expected. we need to handle the url creation helpers in all the places that ive modified. The pipelines keep cycling and im not sure whats not actually working from this code? |
UsePathBase should do most of the heavy lifting. I will take a stab at this and see why that simple one line change doesn’t work. |
Thanks @davidfowl . we really just want to install this as a subpath in a k8s ingress :) |
Any progress? |
Is it possible to use the forwarded header for it, ASP.NET supports the Maybe configure the ForwardedHeadersOptions is more simple to implement |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tested the branch, just looked at code. My knowledge of the things in this PR (running an ASP.NET Core with a base path, running behind a proxy, forwarding headers) is low. An expert should take another look.
I mentioned coming URLs with OrdinalIgnoreCase a number of times. FYI we have StringComparers/StringComparisons with known comparison types. One already might be there for URLs. If not then you could add one.
/// Adds a rference to the dashboard resource so that the required environment variables to allow service discovery to the Aspire dashboard | ||
/// are added to this resource. Also configures a reference relationship to the dashboard resource. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs proof reading
var dashboardUris = builder.ApplicationBuilder.Configuration["ASPNETCORE_URLS"]?.Split(';') | ||
?.Select(u => Uri.TryCreate(u, UriKind.Absolute, out var uri) is { } ? uri : null) | ||
?.Where(u => u is not null) | ||
?.Cast<Uri>() | ||
?.GroupBy(u => u.Scheme) | ||
?? []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var dashboardUris = builder.ApplicationBuilder.Configuration["ASPNETCORE_URLS"]?.Split(';') | |
?.Select(u => Uri.TryCreate(u, UriKind.Absolute, out var uri) is { } ? uri : null) | |
?.Where(u => u is not null) | |
?.Cast<Uri>() | |
?.GroupBy(u => u.Scheme) | |
?? []; | |
var dashboardUris = builder.ApplicationBuilder.Configuration["ASPNETCORE_URLS"]?.Split(';') | |
.Select(u => Uri.TryCreate(u, UriKind.Absolute, out var uri) is { } ? uri : null) | |
.OfType<Uri>() | |
.GroupBy(u => u.Scheme) | |
?? []; |
if (https is not null || http is not null) | ||
{ | ||
var endpoint = https ?? http!; | ||
context.Urls.Add(new() { Url = $"{endpoint.Url}{proxyPath}", DisplayText = "Proxied Dashboard" }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A string concat of URL + path could mean there is no forward slash, or multiple forward slashes in the new URL. Use a better way to combine them?
@@ -26,7 +27,8 @@ | |||
"ASPIRE_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "http://localhost:16032", | |||
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:17031", | |||
"ASPIRE_SHOW_DASHBOARD_RESOURCES": "true", | |||
"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true" | |||
"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true", | |||
"Dashboard__ReverseProxy__ForwardHeaders": "true" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably answered in later code, but how does this env var to the host make its way to the dashboard?
@@ -39,3 +42,22 @@ | |||
<script src="_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.lib.module.js" type="module"></script> | |||
</body> | |||
</html> | |||
|
|||
@code { | |||
private string pathBase = "/"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private string pathBase = "/"; | |
private string _pathBase = "/"; |
@@ -3,7 +3,7 @@ | |||
|
|||
using Aspire.Dashboard.Configuration; | |||
using Aspire.Dashboard.Model; | |||
using Aspire.Dashboard.Utils; | |||
using Aspire.Dashboard.Utils; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using Aspire.Dashboard.Utils; | |
using Aspire.Dashboard.Utils; |
{ | ||
// In development we want to ensure that requests outside of the path base return a 404 to mimic what would | ||
// happen when the dashboard is being served from behind a reverse-proxy at a configured path. Note we still let | ||
// ~/login requests through as that's what VS launches the browser to. In that case we redirect instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need intergration tests of this:
Base path + good path = 200
Base path + bad path = 404
Base path + /login = 302
if (baseRelativePath == targetPagePath) | ||
{ | ||
return true; | ||
} | ||
|
||
var queryIndex = baseRelativePath.IndexOf('?'); | ||
var testPath = queryIndex >= 0 ? baseRelativePath[..queryIndex] : baseRelativePath; | ||
var isMatch = testPath.TrimEnd('/') == targetPagePath; | ||
return isMatch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Path comparisons here should ignore case and culture, e.g. OrdinalIgnoreCase
if (!string.IsNullOrEmpty(dashboardPathBase)) | ||
{ | ||
// Ensure OTLP URLs are rewritten to include the path base. | ||
if (Uri.TryCreate(dashboardOtlpGrpcUrl, UriKind.Absolute, out var otlpGrpcUri) && !otlpGrpcUri.AbsolutePath.StartsWith(dashboardPathBase)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OrdinalIgnoreCase?
uriBuilder.Path = dashboardPathBase + uriBuilder.Path.TrimStart('/'); | ||
dashboardOtlpGrpcUrl = uriBuilder.Uri.ToString(); | ||
} | ||
if (Uri.TryCreate(dashboardOtlpHttpUrl, UriKind.Absolute, out var otlpHttpUri) && !otlpHttpUri.AbsolutePath.StartsWith(dashboardPathBase)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OrdinalIgnoreCase?
?.Select(u => Uri.TryCreate(u, UriKind.Absolute, out var uri) is { } ? uri : null) | ||
?.Where(u => u is not null) | ||
?.Cast<Uri>() | ||
?.GroupBy(u => u.Scheme) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think scheme is always lower case. Maybe ToLowerInvariant()
in the group by in case it isn't and someone does:
ASPNETCORE_URLS=https://localhost:80;HTTPS://LOCALHOST:8080
This is going to require a lot of new tests. For example, does all the existing authentication functionality work properly when running with a base path. |
@JamesNK yep for sure. This is now functionally complete more or less and the next step is to figure out a testing strategy. |
@ewassef do you plan to continue with this PR? |
Are you serious? All the maintainers did their best to discourage contributions, said they would fix it and then let it rot. Most of the people i know have forked this and run it themselves. I would Love to not have to do that, but the style police is stopping everything. So I'm waiting for them to fulfill their commitment ( see thread ) |
@ewassef apologies for confusion. My intent is to complete this PR, it's just a priority and sequencing question right now. No asks on you right now. |
This will allow the aspire app to handle running behind a reverse proxy such as a k8s ingress on a subpath #4159
#4528
#5134
Description
Added a new dashboard base path option, integrated it into the Dashboard Option, validated and replaced all areas that are creating the links
Fixes # (issue)
Checklist
<remarks />
and<code />
elements on your triple slash comments?breaking-change
template):doc-idea
template):Microsoft Reviewers: Open in CodeFlow