question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Blazor Server behind reverse-proxy is case sensitive when app base path is changed

See original GitHub issue

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I’m trying to host a Blazor Server behind Azure Front Door and noticed issues around case sensitivity for the app base path. Basically I set the base path for ANC using app.UsePathBase("/foo") in Program.cs and then have a routing rule matching /foo/* and /foo/ in Azure Front Door which will forward to the Blazor server app (hosted on Azure App Services).

Every thing works fine when I navigate to https://example.com/foo/. But when I navigate to https://example.com/FoO/ Blazor will fail to initialize the circuit, and in developer tools I can see the following logs. No exceptions or anything on the server though.

[2022-01-12T18:49:30.095Z] Error: The circuit failed to initialize. blazor.server.js:1:115531
[2022-01-12T18:49:30.096Z] Information: Connection disconnected. blazor.server.js:1:36859
Uncaught (in promise) Error: Invocation canceled due to the underlying connection being closed.

After adjusting log level on the server side I saw the following log which caught my eye:

Received hub invocation: InvocationMessage { 
   InvocationId: "0",
   Target: "StartCircuit",
   Arguments: [
      https://example.com/foo/,
      https://example.com/FoO/,
      [{"type":"server","sequence":0,"descriptor":"..."},{"type":"server","sequence":1,"descriptor":"..."}],
   ], StreamIds: [  ]
}.

I think that the case mismatch in baseUri (https://example.com/foo/) and uri (https://example.com/FoO/) is because Azure Front Door will forward according to the matching rules (which are case-insensitive). So because the matching rule is /foo the forwarded path will be /foo. The uri I believe is just location.href in Blazor JS side.

After following the code I noticed that the case mismatch above will lead to an exception in NavigationManager.

The URI 'https://example.com/FoO/' is not contained by the base URI 'https://example/foo/'.

https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Components/Server/src/ComponentHub.cs#L133 https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Components/Server/src/Circuits/CircuitFactory.cs#L63 https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Components/Components/src/NavigationManager.cs#L161 https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Components/Components/src/NavigationManager.cs#L82 https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Components/Components/src/NavigationManager.cs#L305

The case mismatch will NOT happen if i navigate directly to the Azure App Service. StartCircuit is invoked with arguments https://example.com/FoO/, https://example.com/FoO/, [....]

Expected Behavior

Path should be case-insensitive when hosted behind a reverse-proxy.

Steps To Reproduce

EDIT: Added local repro code using YARP. See https://github.com/bjorkstromm/aspnetcore-blazor-repro-issue-39469

  1. Create new Blazor Server App
  2. Add Azure SignalR (needed when using behind Azure Front Door) a) Install NuGet package Microsoft.Azure.SignalR b) Add builder.Services.AddSignalR().AddAzureSignalR(); to Program.cs
  1. Adjust base path a) app.UsePathBase("/foo"); to Program.cs
  2. Publish to Azure App Service
  3. Create Azure Front Door and configure a) Add backend pool, point to Azure App Service b) Add routing rule with match patterns /foo/ and /foo/* which forwards to backend pool created in previous step.

If above steps are not enough, I could either try creating a minimal repro with Bicep templates, or if possible try to reproduce everything locally using YARP instead of Azure Front Door. Let me know if you need more info.

The root cause however is simple to reproduce (NavigationManager throwing exception):

var foo = new FooNavigatioManager();
foo.Init("https://example.com/foo/", "https://example.com/FoO/");

class FooNavigatioManager : NavigationManager
{
    public void Init(string baseUri, string uri) => Initialize(baseUri, uri);
}

Exceptions (if any)

The URI 'https://example.com/FoO/' is not contained by the base URI 'https://example/foo/'.

But it’s actually swallowed here: https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Components/Server/src/ComponentHub.cs#L158

.NET Version

6.0.100

Anything else?

Related https://github.com/dotnet/aspnetcore/issues/23107 https://github.com/dotnet/aspnetcore/issues/6818

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
msftbot[bot]commented, Jan 13, 2022

We’ve moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

0reactions
bjorkstrommcommented, Oct 28, 2022

E.g. if AFD is configured to match pattern /foo-bar/* on a route, and incoming HTTP request has /Foo-Bar/BaZ, then AFD will match route, and forward /foo-bar/BaZ to backend. This somehow messes up Blazor Server, since client side script sees path /Foo-Bar while server-side got request on /foo-bar.

This isn’t a problem when using YARP, since it will NOT change casing when forwarding request.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Blazor server side behind reverse proxy 404
I have a blazor server-side app hosted on IIS behind a reverse proxy (using ARR). I have tried everything I can think of,...
Read more >
Secure a hosted ASP.NET Core Blazor WebAssembly app ...
This article explains how to create a hosted Blazor WebAssembly solution that uses Duende Identity Server to authenticate users and API ...
Read more >
How to fix Blazor WASM base path problems - elmah.io Blog
This post will show you how to fix a common problem when setting the application base path with Blazor WebAssembly.
Read more >
Blazor Server using Web API for data access gets no ...
With Blazor server both your website and DB should be behind the firewall. No need for another layer of abstraction and additional out...
Read more >
Dealing with Application Base URLs and Razor link ...
In the case of DasBlog, we have a configuration setting so that the app knows where it LOOKS like it is, from the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found