-
Notifications
You must be signed in to change notification settings - Fork 10k
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
Blazor forms should render target URL in action attribute as root-relative (absolute path), not fully qualified #51380
Comments
It seems the workaround is: -<EditForm action="@Navigation.Uri" ...>
+<EditForm action="@Navigation.ToBaseRelativePath(Navigation.Uri)" ...> I'm not sure how you can expect anything other than an absolute URL for
But why would one specify the |
I did forget that I did use Lines 50 to 56 in faf594a
In this case, the Lines 88 to 89 in faf594a
|
I've done it in my app just to workaround this issue 😄. If I let Blazor render the |
Just hit an issue with the workaround 😞 If you use a base relative URL when you're already on the site root ( |
OK this extension method seems to resolve the issue with the original workaround. Note this could likely be implemented more efficiently directly in namespace Microsoft.AspNetCore.Components;
public static class NavigationManagerExtensions
{
public static string ToAbsolutePath(this NavigationManager navigationManager, string uri)
{
if (uri.StartsWith(navigationManager.BaseUri, StringComparison.Ordinal))
{
// The absolute URI must be of the form "{baseUri}something" (where baseUri ends with a slash),
// and from that we return "something". If baseUri includes a path, we return that path too.
return new Uri(uri).AbsolutePath;
}
var message = $"The URI '{uri}' is not contained by the base URI '{navigationManager.BaseUri}'.";
throw new ArgumentException(message);
}
} |
This is unfortunate - we specifically discussed this exact issue in the PR for #51130, so it seems there was a misunderstanding. I definitely agree this should work by default. Returning a root-relative URL will make this work naturally in a much wider range of cases. PR: #51403 CaveatReturning a root-relative URL is still not sufficient if a reverse proxy modifies the path in any way, e.g., mapping A completely general fix is impossible because URL rewriting could be an arbitrary function and needn't even be invertible. Even for the basic case where an ingress adds a path prefix, we can't invert it by default because we don't know that has happened. Given a request to But despite this, MVC and Razor Pages have been getting along fine for years with this limitation, so presumably in practice it's not a problem. Alternative client-side solutionThe obvious alternative for Blazor is to handle this on the client, since the case that prompted all this is when we're doing enhanced nav. We could make it work with all possible URL transformations trivially in a single line of code, and would no longer have to force emitting an However on further consideration I don't think a client-side fix is what we want, because it would still run into trouble if a certain form is not enhanced but some other enhanced nav is still pending in the background. For example, the user clicks "back" which updates the URL instantly and begins an async enhanced page load, but before it completes they could submit a non-enhanced form without any Overall proposalI agree with @DamianEdwards's proposal above: we emit a root-relative URL, despite the caveat. The fact that MVC and Razor Pages already do this is good evidence that it's sufficient in practice. In the rare case where it's not sufficient, the developer will have to emit PR: #51403 |
# Fix form actions for apps deployed behind reverse proxy Makes forms work for apps deployed behind a reverse proxy. ## Description Apps deployed behind a reverse proxy (e.g., container apps) should not try to emit absolute URLs by default because the scheme/hostname/port may differ from what is reachable from the outside world. The fix is to emit root-relative URLs. Fixes #51380 ## Customer Impact Without this fix, apps deployed behind a reverse proxy (e.g., in ACA) would not support form posts. ## Regression? - [ ] Yes - [x] No No because this only affects SSR forms, which is a new feature in .NET 8. ## Risk - [ ] High - [ ] Medium - [x] Low Low because this is only a change to how we generate the URL for a form's `action` attribute. Previously we used an absolute URL, but now we use a root-relative one. There is no other runtime change. Everything else in this PR is extra tests and updating existing tests. ## Verification - [x] Manual (required) - [x] Automated ## Packaging changes reviewed? - [ ] Yes - [ ] No - [x] N/A
The change recently made to always render the current fully qualified request URL as the value for any
form
element rendered in a Razor component, causes issues when the app is deployed behind any kind of reverse proxy/ingress controller, which is extremely common for any hosting PaaS, including Azure App Service for Linux/Containers, and Azure Container Apps.In these environments, the value of
HttpRequest.Scheme
,HttpRequest.Host
, etc. will not reflect the values the browser client sees unless the forwarded headers middleware is added and properly configured. Doing so is a fairly complex task and tied strongly to the specific destination the app is deployed to.Instead of using the fully qualified URL, MVC and Razor Pages renders the
action
attribute with just the root-relative (absolute) path, i.e. /shopping/cart instead of http://contoso.com/shopping/cart, so that the scheme and host from the client's point of view, do not need to be known (it does this usingIUrlHelper
). Note that this must still take into consideration the current value ofHttpRequest.PathBase
if set. This makes it far simpler to have the application work correctly without need to configured forwarded headers.We should update Blazor's form rendering logic to match what MVC and Razor Pages does, except that Blazor should always render a value (MVC skips it if it's for the current controller/action/page).
@javiercn @SteveSandersonMS
The text was updated successfully, but these errors were encountered: