diff --git a/bff/src/Bff.Yarp/RouteBuilderExtensions.cs b/bff/src/Bff.Yarp/RouteBuilderExtensions.cs index c94ed0fae..297ed1022 100644 --- a/bff/src/Bff.Yarp/RouteBuilderExtensions.cs +++ b/bff/src/Bff.Yarp/RouteBuilderExtensions.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; +using Yarp.ReverseProxy.Forwarder; using Yarp.ReverseProxy.Transforms.Builder; namespace Duende.Bff.Yarp; @@ -18,19 +19,31 @@ public static class RouteBuilderExtensions /// /// Adds a remote BFF API endpoint /// - /// - /// - /// - /// - /// + /// The endpoint route builder to add the endpoint to. + /// The local path pattern for the BFF API endpoint. + /// The remote API address to which requests will be forwarded. + /// + /// Optional. An action to configure YARP transforms for this proxy request. + /// If not provided, a default transform builder is used. + /// + /// + /// Optional. Additional configuration for the forwarded request, such as timeouts or activity propagation. + /// If not specified, the default yarp configuration is used. + /// + /// An for further configuration of the endpoint. public static IEndpointConventionBuilder MapRemoteBffApiEndpoint( this IEndpointRouteBuilder endpoints, PathString localPath, Uri apiAddress, - Action? yarpTransformBuilder = null) + Action? yarpTransformBuilder = null, + ForwarderRequestConfig? requestConfig = null + ) { endpoints.CheckLicense(); + // See if a default request config is registered in DI, otherwise use an empty one + requestConfig ??= endpoints.ServiceProvider.GetService() ?? ForwarderRequestConfig.Empty; + // Configure the yarp transform pipeline. Either use the one provided or the default yarpTransformBuilder ??= context => { @@ -45,7 +58,8 @@ public static class RouteBuilderExtensions // Try to resolve the ITransformBuilder from DI. If it is not registered, // throw a clearer exception. Otherwise, the call below fails with a less clear exception. - var _ = endpoints.ServiceProvider.GetService() ?? throw new InvalidOperationException("No ITransformBuilder has been registered. Have you called BffBuilder.AddRemoteApis()"); + _ = endpoints.ServiceProvider.GetService() + ?? throw new InvalidOperationException("No ITransformBuilder has been registered. Have you called BffBuilder.AddRemoteApis()"); return endpoints.MapForwarder( pattern: localPath.Add("/{**catch-all}").Value!, @@ -53,7 +67,8 @@ public static class RouteBuilderExtensions configureTransform: context => { yarpTransformBuilder(context); - }) + }, + requestConfig: requestConfig) .WithMetadata(new BffRemoteApiEndpointMetadata()); } diff --git a/bff/test/Bff.Tests/BffFrontendIndexTests.cs b/bff/test/Bff.Tests/BffFrontendIndexTests.cs index a7e651c66..7bdda44d0 100644 --- a/bff/test/Bff.Tests/BffFrontendIndexTests.cs +++ b/bff/test/Bff.Tests/BffFrontendIndexTests.cs @@ -52,7 +52,7 @@ public class BffFrontendIndexTests : BffTestBase await Bff.BrowserClient.Login() .CheckResponseContent(Cdn.IndexHtml); - var result = await Bff.BrowserClient.CallBffHostApi(The.SubPath); + var result = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); } [Fact] public async Task Given_index_can_call_local_api() diff --git a/bff/test/Bff.Tests/BffRemoteApiTests.cs b/bff/test/Bff.Tests/BffRemoteApiTests.cs index 5722e3c0b..ce2851304 100644 --- a/bff/test/Bff.Tests/BffRemoteApiTests.cs +++ b/bff/test/Bff.Tests/BffRemoteApiTests.cs @@ -38,7 +38,7 @@ public class BffRemoteApiTests : BffTestBase await Bff.BrowserClient.Login(); - ApiCallDetails result = await Bff.BrowserClient.CallBffHostApi(The.SubPath); + ApiCallDetails result = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); result.Sub.ShouldBe(The.Sub); } @@ -60,7 +60,7 @@ public class BffRemoteApiTests : BffTestBase }) ); - ApiCallDetails result = await Bff.BrowserClient.CallBffHostApi(The.SubPath); + ApiCallDetails result = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); result.Sub.ShouldBeNull(); if (requiredTokenType == RequiredTokenType.UserOrClient || requiredTokenType == RequiredTokenType.Client) @@ -90,7 +90,7 @@ public class BffRemoteApiTests : BffTestBase }) ); - await Bff.BrowserClient.CallBffHostApi(The.SubPath, + await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath, expectedStatusCode: HttpStatusCode.Unauthorized); diff --git a/bff/test/Bff.Tests/Endpoints/DPoPTestsWithManualAuthentication.cs b/bff/test/Bff.Tests/Endpoints/DPoPTestsWithManualAuthentication.cs index bb8aa37db..7c321ab8b 100644 --- a/bff/test/Bff.Tests/Endpoints/DPoPTestsWithManualAuthentication.cs +++ b/bff/test/Bff.Tests/Endpoints/DPoPTestsWithManualAuthentication.cs @@ -62,7 +62,7 @@ public class DPoPTestsWithManualAuthentication : BffTestBase, IAsyncLifetime { ApiCallDetails callToApi = await Bff.BrowserClient.CallBffHostApi( - url: Bff.Url(The.SubPath) + url: Bff.Url(The.PathAndSubPath) ); callToApi.RequestHeaders["DPoP"].First().ShouldNotBeNullOrEmpty(); diff --git a/bff/test/Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs index c5c5d9bcc..a2eb3d035 100644 --- a/bff/test/Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs @@ -45,7 +45,7 @@ public class DpopRemoteEndpointTests : BffTestBase, IAsyncLifetime { ApiCallDetails callToApi = await Bff.BrowserClient.CallBffHostApi( - url: Bff.Url(The.SubPath) + url: Bff.Url(The.PathAndSubPath) ); callToApi.RequestHeaders["DPoP"].First().ShouldNotBeNullOrEmpty(); diff --git a/bff/test/Bff.Tests/Endpoints/RemoteEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/RemoteEndpointTests.cs index b0dbd0c0c..251cfeadc 100644 --- a/bff/test/Bff.Tests/Endpoints/RemoteEndpointTests.cs +++ b/bff/test/Bff.Tests/Endpoints/RemoteEndpointTests.cs @@ -3,7 +3,6 @@ using System.Net; using System.Security.Claims; -using System.Text.Json; using Duende.Bff.AccessTokenManagement; using Duende.Bff.Configuration; using Duende.Bff.DynamicFrontends; @@ -16,6 +15,7 @@ using Duende.IdentityServer.Services; using Microsoft.AspNetCore.Authentication; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Xunit.Abstractions; +using Yarp.ReverseProxy.Forwarder; using Yarp.ReverseProxy.Transforms; using Yarp.ReverseProxy.Transforms.Builder; using Resource = Duende.Bff.AccessTokenManagement.Resource; @@ -611,57 +611,146 @@ public class RemoteEndpointTests : BffTestBase } [Theory, MemberData(nameof(AllSetups))] - public async Task endpoint_can_be_configured_with_custom_transform(BffSetupType setup) + public async Task MapRemoteBffApiEndpoint_can_override_default_transform(BffSetupType setup) { Bff.OnConfigureEndpoints += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path), - c => + app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path), c => + { + DefaultBffYarpTransformerBuilders.DirectProxyWithAccessToken(The.Path, c); + c.AddRequestHeader("custom", "with value"); + // Add a transform that adds the catchall route value to a header + c.AddRequestTransform(async context => { - c.CopyRequestHeaders = true; - DefaultBffYarpTransformerBuilders.DirectProxyWithAccessToken(The.Path, c); - }) - .WithAccessToken(RequiredTokenType.UserOrClient) - .SkipAntiforgery(); + // One of our customers asked how to access the catch-all route value in subsequent transforms + if (context.HttpContext.Request.RouteValues.TryGetValue("catch-all", out var value) && value is string s) + { + context.ProxyRequest.Headers.Add("catch-all", "/" + s); + } + await Task.CompletedTask; + }); + }) + .WithAccessToken(); }; ConfigureBff(setup); await InitializeAsync(); await Bff.BrowserClient.Login(); - var req = new HttpRequestMessage(HttpMethod.Get, Bff.Url(The.Path)); - req.Headers.Add("x-csrf", "1"); - req.Headers.Add("my-header-to-be-copied-by-yarp", "copied-value"); - var response = await Bff.BrowserClient.SendAsync(req); + ApiCallDetails result = await Bff.BrowserClient.CallBffHostApi( + url: Bff.Url(The.PathAndSubPath) + ); - response.IsSuccessStatusCode.ShouldBeTrue(); - response.Content.Headers.ContentType!.MediaType.ShouldBe("application/json"); - var json = await response.Content.ReadAsStringAsync(); - var apiResult = JsonSerializer.Deserialize(json).ShouldNotBeNull(); - apiResult.RequestHeaders["my-header-to-be-copied-by-yarp"].First().ShouldBe("copied-value"); + result.RequestHeaders.Keys.ShouldNotContain("added-by-custom-default-transform"); + result.RequestHeaders.TryGetValue("custom", out var customValue).ShouldBeTrue(); + customValue.ShouldBe(["with value"], + "The custom header should be added by the custom transform registered in the test."); - response.Content.Headers.Select(x => x.Key).ShouldNotContain("added-by-custom-default-transform", - "a custom transform doesn't run the defaults"); + result.RequestHeaders.TryGetValue("catch-all", out var catchAll).ShouldBeTrue(); + catchAll.ShouldBe([The.SubPath], + "The catch-all route value should be added to the request headers by the custom transform registered in the test."); } + // now I don't like timeouts in tests, but I don't know of a better way to create http timeouts. [Theory, MemberData(nameof(AllSetups))] - public async Task can_disable_anti_forgery_check(BffSetupType setup) + public async Task Can_register_default_forwarder_config_for_MapRemoteBffApiEndpoint(BffSetupType setup) { + var shouldDelay = false; + + Api.OnConfigure += app => + { + app.Use(async (c, n) => + { + if (shouldDelay) + { + await Task.Delay(TimeSpan.FromSeconds(5)); + } + await n(); + }); + }; + + Bff.OnConfigureServices += services => + { + // Add a default ForwarderRequestConfig that has a 100 ms timeout + services.AddSingleton(new ForwarderRequestConfig() + { + ActivityTimeout = TimeSpan.FromMilliseconds(100) + }); + }; Bff.OnConfigureEndpoints += app => { - app.MapRemoteBffApiEndpoint(The.Path, Api.Url(The.Path)) - .WithAccessToken(RequiredTokenType.None); + app.MapRemoteBffApiEndpoint( + localPath: The.Path, + apiAddress: Api.Url(The.Path)) + .WithAccessToken(); }; + ConfigureBff(setup); - await InitializeAsync(); + await Bff.BrowserClient.Login(); - Bff.BffOptions.DisableAntiForgeryCheck = (c) => true; + // first, ensure that the 'normal' process works, becuase delay's are turned off. + await Bff.BrowserClient.CallBffHostApi( + url: Bff.Url(The.PathAndSubPath) + ); - var req = new HttpRequestMessage(HttpMethod.Get, Bff.Url(The.Path)); - var response = await Bff.BrowserClient.SendAsync(req); + // turn on delays. Now the timeout of 100 ms should kick in. + shouldDelay = true; - response.StatusCode.ShouldBe(HttpStatusCode.OK); + await Bff.BrowserClient.CallBffHostApi( + url: Bff.Url(The.PathAndSubPath), + expectedStatusCode: HttpStatusCode.BadGateway + ); + } + + // now I don't like timeouts in tests, but I don't know of a better way to create http timeouts. + [Theory, MemberData(nameof(AllSetups))] + public async Task MapRemoteBffApiEndpoint_can_override_config_to_configure_a_timeout(BffSetupType setup) + { + var shouldDelay = false; + + Api.OnConfigure += app => + { + app.Use(async (c, n) => + { + if (shouldDelay) + { + await Task.Delay(TimeSpan.FromSeconds(5)); + } + await n(); + }); + }; + + Bff.OnConfigureEndpoints += app => + { + app.MapRemoteBffApiEndpoint( + localPath: The.Path, + apiAddress: Api.Url(The.Path), + requestConfig: new ForwarderRequestConfig() + { + // 100 ms timeout, which is not too short that the normal process might fail, + // but not too long that the test will take forever + ActivityTimeout = TimeSpan.FromMilliseconds(100) + }) + .WithAccessToken(); + }; + + ConfigureBff(setup); + await InitializeAsync(); + await Bff.BrowserClient.Login(); + + // first, ensure that the 'normal' process works, becuase delay's are turned off. + await Bff.BrowserClient.CallBffHostApi( + url: Bff.Url(The.PathAndSubPath) + ); + + // turn on delays. Now the timeout of 100 ms should kick in. + shouldDelay = true; + + await Bff.BrowserClient.CallBffHostApi( + url: Bff.Url(The.PathAndSubPath), + expectedStatusCode: HttpStatusCode.BadGateway + ); } } diff --git a/bff/test/Bff.Tests/Endpoints/YarpTests.cs b/bff/test/Bff.Tests/Endpoints/YarpTests.cs index 5b66b194c..8a9e1478d 100644 --- a/bff/test/Bff.Tests/Endpoints/YarpTests.cs +++ b/bff/test/Bff.Tests/Endpoints/YarpTests.cs @@ -37,7 +37,7 @@ public class YarpTests : BffTestBase await InitializeAsync(); await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.OK ); } @@ -50,7 +50,7 @@ public class YarpTests : BffTestBase ConfigureYarp(Some.RouteConfig().WithAntiforgeryCheck()); await InitializeAsync(); - var req = new HttpRequestMessage(HttpMethod.Get, The.SubPath); + var req = new HttpRequestMessage(HttpMethod.Get, The.PathAndSubPath); var response = await Bff.BrowserClient.SendAsync(req); response.StatusCode.ShouldBe(HttpStatusCode.Unauthorized); @@ -70,7 +70,7 @@ public class YarpTests : BffTestBase ConfigureYarp(Some.RouteConfig().WithAntiforgeryCheck()); await InitializeAsync(); - var req = new HttpRequestMessage(HttpMethod.Get, The.SubPath); + var req = new HttpRequestMessage(HttpMethod.Get, The.PathAndSubPath); var response = await Bff.BrowserClient.SendAsync(req); response.StatusCode.ShouldBe(HttpStatusCode.OK); @@ -85,7 +85,7 @@ public class YarpTests : BffTestBase await InitializeAsync(); await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.OK ); } @@ -99,7 +99,7 @@ public class YarpTests : BffTestBase await InitializeAsync(); await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.Unauthorized ); } @@ -113,12 +113,12 @@ public class YarpTests : BffTestBase await InitializeAsync(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.OK ); apiResult.Method.ShouldBe(HttpMethod.Get); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBeNull(); apiResult.ClientId.ShouldBeNull(); } @@ -136,12 +136,12 @@ public class YarpTests : BffTestBase await InitializeAsync(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.OK ); apiResult.Method.ShouldBe(HttpMethod.Get); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBeNull(); apiResult.ClientId.ShouldBeNull(); } @@ -156,11 +156,11 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath + path: The.PathAndSubPath ); apiResult.Method.ShouldBe(HttpMethod.Get); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBe(The.Sub); apiResult.ClientId.ShouldBe(The.ClientId); } @@ -178,12 +178,12 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, method: HttpMethod.Put ); apiResult.Method.ShouldBe(HttpMethod.Put); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBe(The.Sub); apiResult.ClientId.ShouldBe(The.ClientId); } @@ -198,12 +198,12 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, method: HttpMethod.Post ); apiResult.Method.ShouldBe(HttpMethod.Post); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBe(The.Sub); apiResult.ClientId.ShouldBe(The.ClientId); } @@ -218,12 +218,12 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, method: HttpMethod.Post ); apiResult.Method.ShouldBe(HttpMethod.Post); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBe(The.Sub); apiResult.ClientId.ShouldBe(The.ClientId); } @@ -238,11 +238,11 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath + path: The.PathAndSubPath ); apiResult.Method.ShouldBe(HttpMethod.Get); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBeNull(); apiResult.ClientId.ShouldBe(The.ClientId); } @@ -257,11 +257,11 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login(); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath + path: The.PathAndSubPath ); apiResult.Method.ShouldBe(HttpMethod.Get); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBe(The.Sub); apiResult.ClientId.ShouldBe(The.ClientId); } @@ -288,11 +288,11 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login("/somepath"); ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi( - path: "/somepath" + The.SubPath + path: "/somepath" + The.PathAndSubPath ); apiResult.Method.ShouldBe(HttpMethod.Get); - apiResult.Path.ShouldBe(The.SubPath); + apiResult.Path.ShouldBe(The.PathAndSubPath); apiResult.Sub.ShouldBe(The.Sub); apiResult.ClientId.ShouldBe(The.ClientId); } @@ -308,7 +308,7 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login(); await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.Unauthorized ); } @@ -324,7 +324,7 @@ public class YarpTests : BffTestBase await Bff.BrowserClient.Login(); await Bff.BrowserClient.CallBffHostApi( - path: The.SubPath, + path: The.PathAndSubPath, expectedStatusCode: HttpStatusCode.Forbidden ); } diff --git a/bff/test/Bff.Tests/Headers/ApiAndBffUseForwardedHeaders.cs b/bff/test/Bff.Tests/Headers/ApiAndBffUseForwardedHeaders.cs index 31b57fe37..66c708e8a 100644 --- a/bff/test/Bff.Tests/Headers/ApiAndBffUseForwardedHeaders.cs +++ b/bff/test/Bff.Tests/Headers/ApiAndBffUseForwardedHeaders.cs @@ -46,7 +46,7 @@ public class ApiAndBffUseForwardedHeaders : BffTestBase, IAsyncLifetime public async Task bff_host_name_should_propagate_to_api() { - ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi(The.SubPath); + ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); var host = apiResult.RequestHeaders["Host"].Single(); host.ShouldBe(Bff.Url().Host); @@ -55,7 +55,7 @@ public class ApiAndBffUseForwardedHeaders : BffTestBase, IAsyncLifetime [Fact] public async Task forwarded_host_name_with_header_forwarding_should_propagate_to_api() { - ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi(The.SubPath, + ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath, headers: new() { ["x-csrf"] = "1", diff --git a/bff/test/Bff.Tests/Headers/ApiUseForwardedHeaders.cs b/bff/test/Bff.Tests/Headers/ApiUseForwardedHeaders.cs index bc56e50c4..2447cb357 100644 --- a/bff/test/Bff.Tests/Headers/ApiUseForwardedHeaders.cs +++ b/bff/test/Bff.Tests/Headers/ApiUseForwardedHeaders.cs @@ -36,7 +36,7 @@ public class ApiUseForwardedHeaders : BffTestBase { await InitializeAsync(); - ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi(The.SubPath); + ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath); var host = apiResult.RequestHeaders["Host"].Single(); host.ShouldBe(Bff.Url().Host); @@ -47,7 +47,7 @@ public class ApiUseForwardedHeaders : BffTestBase { await InitializeAsync(); - ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi(The.SubPath, + ApiCallDetails apiResult = await Bff.BrowserClient.CallBffHostApi(The.PathAndSubPath, headers: new() { ["x-csrf"] = "1", diff --git a/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff_Yarp.verified.txt b/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff_Yarp.verified.txt index 98e9709e3..803ce1d5f 100644 --- a/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff_Yarp.verified.txt +++ b/bff/test/Bff.Tests/PublicApiVerificationTests.VerifyPublicApi_Bff_Yarp.verified.txt @@ -65,7 +65,7 @@ } public static class RouteBuilderExtensions { - public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapRemoteBffApiEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, Microsoft.AspNetCore.Http.PathString localPath, System.Uri apiAddress, System.Action? yarpTransformBuilder = null) { } + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapRemoteBffApiEndpoint(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, Microsoft.AspNetCore.Http.PathString localPath, System.Uri apiAddress, System.Action? yarpTransformBuilder = null, Yarp.ReverseProxy.Forwarder.ForwarderRequestConfig? requestConfig = null) { } } public sealed class UserAccessTokenParameters : System.IEquatable { diff --git a/bff/test/Bff.Tests/TestInfra/TestData.cs b/bff/test/Bff.Tests/TestInfra/TestData.cs index 8f2bbe4b2..4960cae20 100644 --- a/bff/test/Bff.Tests/TestInfra/TestData.cs +++ b/bff/test/Bff.Tests/TestInfra/TestData.cs @@ -30,7 +30,8 @@ public class TestData public Origin Origin = Origin.Parse($"https://{PropertyName()}:1234"); public int Port = 1234; public PathString Path = new PathString($"/{PropertyName()}"); - public PathString SubPath = new PathString($"/{PropertyName(nameof(Path))}/{PropertyName()}"); + public PathString SubPath = new PathString($"/{PropertyName()}"); + public PathString PathAndSubPath = new PathString($"/{PropertyName(nameof(Path))}/{PropertyName(nameof(SubPath))}"); public string Scope = PropertyName(); public string RouteId = PropertyName(); public string ClusterId = PropertyName();