Blazor Server + YARP - Static Files (CSS/JS) 404 & Circuit Failed to Initialize
Hello community,
I am currently implementing YARP (Yet Another Reverse Proxy) in my Blazor Server application to proxy multiple existing projects. However, I am encountering the following issues:
- Static files (CSS, JS, etc.) are not loading (404 errors)
- The browser console shows multiple Failed to load resource: the server responded with a status of 404 errors for CSS and JS files.
- Blazor Circuit Initialization Failure
- After the WebSocket connection is established, I get the following error:
[Error] The circuit failed to initialize. Connection disconnected.
### Project Setup & Code Snippets Program.cs Configuration
builder.Services.AddReverseProxy();
builder.Services.AddSingleton<IProxyConfigProvider, DynamicProxyConfigProvider>();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAntiforgery();
app.UseAuthentication();
app.UseAuthorization();
app.MapReverseProxy();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
app.Run();
DynamicProxyConfigProvider.cs (Route & Cluster Configuration)
routes.Add(new RouteConfig
{
RouteId = routeId,
ClusterId = clusterId,
Match = new RouteMatch { Path = $"{proxiedUrl}/{{**catch-all}}" },
Transforms = new List<Dictionary<string, string>>
{
new Dictionary<string, string> { { "PathRemovePrefix", proxiedUrl } }
}
});
clusters.Add(new ClusterConfig
{
ClusterId = clusterId,
Destinations = new Dictionary<string, DestinationConfig>
{
{ "destination", new DestinationConfig { Address = item.Url } }
}
});
Index Page (Navigation to Proxy URL)
string sanitizedTitle = Uri.EscapeDataString(item.Title.Trim().Replace(" ", "-").ToLower());
string proxiedUrl = $"/system/{sanitizedTitle}-{item.Id}";
Navigation.NavigateTo(proxiedUrl, true);
Steps to Reproduce:
- Set up a Blazor Server application with YARP.
- Proxy an external Blazor app via YARP.
- Open the browser and check the console (F12).
- Observe the 404 errors for static files.
- Attempt to initialize a Blazor session and note the circuit failure.
What I Have Tried: -Ensured Static Files Exist in wwwroot. -Added UseStaticFiles() before UseRouting(). -Checked _content/ Paths for Blazor resources. -Enabled WebSockets in YARP. -Modified appsettings.json to match YARP paths.
Expected Behavior: -Static files should load correctly. -Blazor Circuit should initialize without failure.
Environment:
- .NET Version: net9.0
- YARP Version: 2.3.0
- Blazor Server Framework Version: net9.0
- Hosting Environment: Localhost (https://localhost:7287)
- Browser: Edge
### Questions:
- How do I ensure YARP properly serves static files?
- How can I debug Blazor Circuit Initialization Failure through YARP?
here is the result of all the logs.
dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-24'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-24' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-23'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-23' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-22'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-22' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-21'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-21' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-20'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-20' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-19'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-19' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-18'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-18' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-17'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-17' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-16'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-16' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[24] Destination 'destination' has been added. dbug: Yarp.ReverseProxy.Forwarder.ForwarderHttpClientFactory[45] New client created for cluster 'cluster-15'. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[21] Cluster 'cluster-15' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-24' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-23' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-22' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-21' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-20' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-19' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-18' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-17' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-16' has been added. dbug: Yarp.ReverseProxy.Management.ProxyConfigManager[27] Route 'system-15' has been added. dbug: Microsoft.Extensions.Hosting.Internal.Host[1] Hosting starting info: Microsoft.Hosting.Lifetime[14] Now listening on: https://localhost:7287 info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5059 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: C:\DEVOPS\Service Portal Application (ADPIA)\SPA.Web dbug: Microsoft.Extensions.Hosting.Internal.Host[2] Hosting started dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint '/ (/)' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint '/ (/)' dbug: Microsoft.WebTools.BrowserLink.Net.BrowserLinkMiddleware[1] Response markup is scheduled to include Browser Link script injection. info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint '/ (/)' dbug: Microsoft.WebTools.BrowserLink.Net.BrowserLinkMiddleware[2] Response markup was updated to include Browser Link script injection. dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/_framework/blazor.web.js' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint 'Blazor web static files' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint 'Blazor web static files' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'Blazor web static files' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/_blazor/negotiate' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint '(null)' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/_blazor' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint '(null)' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1] Request successfully matched the route with name '(null)' and template '/' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/system/why-not-space-16' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1005] Endpoint 'system-16' with route pattern '/system/why-not-space-16/{**catch-all}' is valid for the request path '/system/why-not-space-16' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint 'system-16' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint 'system-16' info: Yarp.ReverseProxy.Forwarder.HttpForwarder[9] Proxying to http://whynot.adpia-itsolutions.com/ HTTP/2 RequestVersionOrLower info: Yarp.ReverseProxy.Forwarder.HttpForwarder[56] Received HTTP/1.1 response 200. dbug: Microsoft.WebTools.BrowserLink.Net.BrowserLinkMiddleware[1] Response markup is scheduled to include Browser Link script injection. info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'system-16' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/_blazor/disconnect' dbug: Microsoft.WebTools.BrowserLink.Net.BrowserLinkMiddleware[2] Response markup was updated to include Browser Link script injection. dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint '(null)' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1000] No candidates found for the request path '/css/print.css' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1000] No candidates found for the request path '/css/app.css' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[2] Request did not match any endpoints dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1000] No candidates found for the request path '/_content/Syncfusion.Blazor.Themes/bootstrap5.css' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[2] Request did not match any endpoints dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1000] No candidates found for the request path '/CLA.Web.styles.css' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/_framework/blazor.web.js' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint 'Blazor web static files' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint 'Blazor web static files' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[2] Request did not match any endpoints dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[2] Request did not match any endpoints info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'Blazor web static files' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1000] No candidates found for the request path '/_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1000] No candidates found for the request path '/js/rfidListener.js' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[2] Request did not match any endpoints dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[2] Request did not match any endpoints info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/_blazor/negotiate' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint '(null)' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001] 1 candidate(s) found for the request path '/_blazor' dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1] Request matched endpoint '(null)' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] Executing endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint' info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] Executed endpoint 'Microsoft.AspNetCore.Routing.RouteEndpoint'
Was this ever resolved or have you found a work around? I too am having this issue.