From 6933d9997d7b780fff3b076a5a9fd5f567743d23 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Mon, 8 May 2023 00:03:14 -0700 Subject: [PATCH] Forward SignalR requests through the web app --- src/Web/WebMVC/AppSettings.cs | 1 - src/Web/WebMVC/Extensions/Extensions.cs | 25 +++++++++++++++++ src/Web/WebMVC/Program.cs | 2 ++ src/Web/WebMVC/Views/Shared/_Layout.cshtml | 32 ++++++---------------- src/Web/WebMVC/WebMVC.csproj | 1 + 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/Web/WebMVC/AppSettings.cs b/src/Web/WebMVC/AppSettings.cs index 8879abf2e..b1a8b6851 100644 --- a/src/Web/WebMVC/AppSettings.cs +++ b/src/Web/WebMVC/AppSettings.cs @@ -3,6 +3,5 @@ public class AppSettings { public string PurchaseUrl { get; set; } - public string SignalrHubUrl { get; set; } public bool UseCustomizationData { get; set; } } diff --git a/src/Web/WebMVC/Extensions/Extensions.cs b/src/Web/WebMVC/Extensions/Extensions.cs index 4118f167a..8c8a6843c 100644 --- a/src/Web/WebMVC/Extensions/Extensions.cs +++ b/src/Web/WebMVC/Extensions/Extensions.cs @@ -1,5 +1,7 @@ // Fix samesite issue when running eShop from docker-compose locally as by default http protocol is being used // Refer to https://github.com/dotnet-architecture/eShopOnContainers/issues/1391 +using Yarp.ReverseProxy.Forwarder; + internal static class Extensions { public static void AddHealthChecks(this IServiceCollection services, IConfiguration configuration) @@ -82,4 +84,27 @@ internal static class Extensions options.Scope.Add("webhooks"); }); } + + public static IEndpointConventionBuilder MapForwardSignalR(this WebApplication app) + { + // Forward the SignalR traffic to the bff + var destination = app.Configuration.GetRequiredValue("PurchaseUrl"); + var authTransformer = new BffAuthTransfomer(); + var requestConfig = new ForwarderRequestConfig(); + + return app.MapForwarder("/hub/notificationhub/{**any}", destination, requestConfig, authTransformer); + } + + private sealed class BffAuthTransfomer : HttpTransformer + { + public override async ValueTask TransformRequestAsync(HttpContext httpContext, HttpRequestMessage proxyRequest, string destinationPrefix, CancellationToken cancellationToken) + { + // Set the access token as a bearer token for the outgoing request + var accessToken = await httpContext.GetTokenAsync("access_token"); + + proxyRequest.Headers.Authorization = new("Bearer", accessToken); + + await base.TransformRequestAsync(httpContext, proxyRequest, destinationPrefix, cancellationToken); + } + } } diff --git a/src/Web/WebMVC/Program.cs b/src/Web/WebMVC/Program.cs index 71748a750..aa55b2cb7 100644 --- a/src/Web/WebMVC/Program.cs +++ b/src/Web/WebMVC/Program.cs @@ -2,6 +2,7 @@ builder.AddServiceDefaults(); +builder.Services.AddHttpForwarder(); builder.Services.AddControllersWithViews(); builder.Services.AddHealthChecks(builder.Configuration); @@ -28,6 +29,7 @@ app.UseAuthorization(); app.MapControllerRoute("default", "{controller=Catalog}/{action=Index}/{id?}"); app.MapControllerRoute("defaultError", "{controller=Error}/{action=Error}"); app.MapControllers(); +app.MapForwardSignalR(); WebContextSeed.Seed(app, app.Environment); diff --git a/src/Web/WebMVC/Views/Shared/_Layout.cshtml b/src/Web/WebMVC/Views/Shared/_Layout.cshtml index 9a634b78a..6cb3f43fb 100644 --- a/src/Web/WebMVC/Views/Shared/_Layout.cshtml +++ b/src/Web/WebMVC/Views/Shared/_Layout.cshtml @@ -86,35 +86,23 @@ @RenderSection("scripts", required: false) - - @using Microsoft.AspNetCore.Authentication; - @using Microsoft.Extensions.Options - @inject IOptions settings -