From deca5b652683ad49a1b35c72ad95e0b8986ccd15 Mon Sep 17 00:00:00 2001 From: Alex Pop Date: Tue, 30 Apr 2024 23:23:31 +0100 Subject: [PATCH] feature: added support for aliases with api routes --- .../Services/RouteInfoFactory.cs | 10 +-- .../Services/RouteService.cs | 31 ++++++--- .../ValueTypes/BlockClusterConfig.cs | 5 +- .../NodeDoesNotExistAndRouteIsNotProxied.cs | 4 +- .../NodeExistsAndRendererDoesNotMatch.cs | 4 +- .../NodeExistsAndRendererMatched.cs | 4 +- ...stsAndRendererMatchedWithFullUriRouting.cs | 4 +- .../PathIsAliasWithApiRouteCall.cs | 63 +++++++++++++++++++ .../RouteServiceSpecs/PathIsProxiedApiCall.cs | 4 +- .../PathIsRewrittenStaticResource.cs | 4 +- ...sRewrittenStaticResourceWithQueryString.cs | 4 +- ...houldNotPerformNodeLookupIfExcludedPath.cs | 1 + .../ShouldPerformNodeLookup.cs | 1 + 13 files changed, 119 insertions(+), 20 deletions(-) create mode 100644 tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsAliasWithApiRouteCall.cs diff --git a/src/Zengenti.Contensis.RequestHandler.Application/Services/RouteInfoFactory.cs b/src/Zengenti.Contensis.RequestHandler.Application/Services/RouteInfoFactory.cs index f56da73..da76c32 100644 --- a/src/Zengenti.Contensis.RequestHandler.Application/Services/RouteInfoFactory.cs +++ b/src/Zengenti.Contensis.RequestHandler.Application/Services/RouteInfoFactory.cs @@ -83,10 +83,12 @@ public RouteInfo Create( var queryString = BuildQueryString(originUri); // Handle API requests - bool isApiRequest = Constants.Paths.ApiPrefixes.Any(prefix => path.StartsWithCaseInsensitive(prefix)) && - !path.StartsWithCaseInsensitive("/api/publishing/request-handler") && - !path.StartsWithCaseInsensitive("/api/preview-toolbar/blocks"); - if (isApiRequest) + bool isContensisApiRequest = + Constants.Paths.ApiPrefixes.Any(prefix => path.StartsWithCaseInsensitive(prefix)) && + !path.StartsWithCaseInsensitive("/api/publishing/request-handler") && + !path.StartsWithCaseInsensitive("/api/preview-toolbar/blocks") && + _blockClusterConfig.AliasesWithApiRoutes?.ContainsCaseInsensitive(_requestContext.Alias) != true; + if (isContensisApiRequest) { var apiHost = $"api-{_requestContext.Alias}.cloud.contensis.com"; var apiUrl = $"https://{apiHost}"; diff --git a/src/Zengenti.Contensis.RequestHandler.Application/Services/RouteService.cs b/src/Zengenti.Contensis.RequestHandler.Application/Services/RouteService.cs index 504eb84..a26e925 100644 --- a/src/Zengenti.Contensis.RequestHandler.Application/Services/RouteService.cs +++ b/src/Zengenti.Contensis.RequestHandler.Application/Services/RouteService.cs @@ -11,6 +11,7 @@ namespace Zengenti.Contensis.RequestHandler.Application.Services; public class RouteService : IRouteService { + private readonly BlockClusterConfig _blockClusterConfig; private readonly INodeService _nodeService; private readonly IPublishingService _publishingService; private readonly IRouteInfoFactory _routeInfoFactory; @@ -19,6 +20,7 @@ public class RouteService : IRouteService private readonly ILogger _logger; public RouteService( + BlockClusterConfig blockClusterConfig, INodeService nodeService, IPublishingService publishingService, IRouteInfoFactory routeInfoFactory, @@ -26,6 +28,7 @@ public RouteService( ICacheKeyService cacheKeyService, ILogger logger) { + _blockClusterConfig = blockClusterConfig; _nodeService = nodeService; _publishingService = publishingService; _routeInfoFactory = routeInfoFactory; @@ -177,19 +180,31 @@ public async Task GetRouteForRequest(Uri originUri, Headers headers) return returnInfo; } - private static bool ShouldPerformNodeLookup(string path) + private bool ShouldPerformNodeLookup(string path) { // Don't like this hard-coded path, maybe move to config? // We can negate anything that is a rewritten static path - var pathIsRewritten = StaticPath.Parse(path)?.IsRewritten; - bool doLookup = path.ToLowerInvariant() != "/favicon.ico" && - !path.StartsWithCaseInsensitive("/contensis-preview-toolbar/") && - !pathIsRewritten.GetValueOrDefault() && - !Constants.Paths.ApiPrefixes.Any(path.StartsWithCaseInsensitive) && - !Constants.Paths.PassThroughPrefixes.Any(path.StartsWithCaseInsensitive); + var pathIsRewritten = StaticPath.Parse(path)?.IsRewritten ?? false; + if (pathIsRewritten) + { + return false; + } + + if (path.ToLowerInvariant() == "/favicon.ico" || + path.StartsWithCaseInsensitive("/contensis-preview-toolbar/") || + Constants.Paths.PassThroughPrefixes.Any(path.StartsWithCaseInsensitive)) + { + return false; + } + + if (Constants.Paths.ApiPrefixes.Any(path.StartsWithCaseInsensitive) && + _blockClusterConfig.AliasesWithApiRoutes?.ContainsCaseInsensitive(_requestContext.Alias) != true) + { + return false; + } - return doLookup; + return true; } private void CheckAndSetProjectHeaders(Headers headers) diff --git a/src/Zengenti.Contensis.RequestHandler.Domain/ValueTypes/BlockClusterConfig.cs b/src/Zengenti.Contensis.RequestHandler.Domain/ValueTypes/BlockClusterConfig.cs index b5b2831..7c9d909 100644 --- a/src/Zengenti.Contensis.RequestHandler.Domain/ValueTypes/BlockClusterConfig.cs +++ b/src/Zengenti.Contensis.RequestHandler.Domain/ValueTypes/BlockClusterConfig.cs @@ -1,3 +1,6 @@ namespace Zengenti.Contensis.RequestHandler.Domain.ValueTypes; -public record BlockClusterConfig(string? BlockClusterIngressIp = null, string? BlockAddressSuffix = null); \ No newline at end of file +public record BlockClusterConfig( + string? BlockClusterIngressIp = null, + string? BlockAddressSuffix = null, + string[]? AliasesWithApiRoutes = null); \ No newline at end of file diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeDoesNotExistAndRouteIsNotProxied.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeDoesNotExistAndRouteIsNotProxied.cs index 57600ac..e01c111 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeDoesNotExistAndRouteIsNotProxied.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeDoesNotExistAndRouteIsNotProxied.cs @@ -24,10 +24,12 @@ public void GivenARequestPathDoesNotExistsAsANode() var requestContext = Substitute.For(); var cacheKeyService = Substitute.For(); var logger = Substitute.For>(); - var routeInfoFactory = new RouteInfoFactory(requestContext, new BlockClusterConfig()); + var blockClusterConfig = new BlockClusterConfig(); + var routeInfoFactory = new RouteInfoFactory(requestContext, blockClusterConfig); var rendererService = SpecHelper.CreatePublishingService(routeInfoFactory); _sut = new RouteService( + blockClusterConfig, _nodeService, rendererService, routeInfoFactory, diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererDoesNotMatch.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererDoesNotMatch.cs index e27f4e6..859b7ae 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererDoesNotMatch.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererDoesNotMatch.cs @@ -31,11 +31,13 @@ public void GivenARequestPathExistsAsANode() var requestContext = Substitute.For(); var cacheKeyService = Substitute.For(); var logger = Substitute.For>(); + var blockClusterConfig = new BlockClusterConfig(); var routeInfoFactory = - new RouteInfoFactory(requestContext, new BlockClusterConfig()); + new RouteInfoFactory(requestContext, blockClusterConfig); var publishingService = SpecHelper.CreatePublishingService(routeInfoFactory); _sut = new RouteService( + blockClusterConfig, _nodeService, publishingService, routeInfoFactory, diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererMatched.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererMatched.cs index 1925817..59f9ea2 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererMatched.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererMatched.cs @@ -27,7 +27,8 @@ public void GivenARequestPathExistsAsANode() requestContext.ProjectUuid.Returns(_projectUuid); var cacheKeyService = Substitute.For(); var logger = Substitute.For>(); - var routeInfoFactory = new RouteInfoFactory(requestContext, new BlockClusterConfig()); + var blockClusterConfig = new BlockClusterConfig(); + var routeInfoFactory = new RouteInfoFactory(requestContext, blockClusterConfig); _publishingService = SpecHelper.CreatePublishingService(routeInfoFactory); _node = new Node @@ -42,6 +43,7 @@ public void GivenARequestPathExistsAsANode() _nodeService.GetByPath(Path).Returns(_node); _sut = new RouteService( + blockClusterConfig, _nodeService, _publishingService, routeInfoFactory, diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererMatchedWithFullUriRouting.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererMatchedWithFullUriRouting.cs index 5b80020..2329567 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererMatchedWithFullUriRouting.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/NodeExistsAndRendererMatchedWithFullUriRouting.cs @@ -27,7 +27,8 @@ public void GivenARequestPathExistsAsANode() requestContext.ProjectUuid.Returns(_projectUuid); var cacheKeyService = Substitute.For(); var logger = Substitute.For>(); - var routeInfoFactory = new RouteInfoFactory(requestContext, new BlockClusterConfig()); + var blockClusterConfig = new BlockClusterConfig(); + var routeInfoFactory = new RouteInfoFactory(requestContext, blockClusterConfig); _publishingService = SpecHelper.CreatePublishingService(routeInfoFactory, enableFullUriRouting: true); _node = new Node @@ -42,6 +43,7 @@ public void GivenARequestPathExistsAsANode() _nodeService.GetByPath(Path).Returns(_node); _sut = new RouteService( + blockClusterConfig, _nodeService, _publishingService, routeInfoFactory, diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsAliasWithApiRouteCall.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsAliasWithApiRouteCall.cs new file mode 100644 index 0000000..35b893d --- /dev/null +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsAliasWithApiRouteCall.cs @@ -0,0 +1,63 @@ +using Microsoft.Extensions.Logging; +using NSubstitute; +using TestStack.BDDfy; +using Zengenti.Contensis.RequestHandler.Application.Services; +using Zengenti.Contensis.RequestHandler.Domain.Interfaces; +using Zengenti.Contensis.RequestHandler.Domain.ValueTypes; + +namespace Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs.Services.RouteServiceSpecs; + +public class PathIsAliasWithApiRouteCall +{ + private const string Host = "http://www.mysite.com"; + private const string Path = "/api/delivery/website/"; + private readonly Uri _originUri = new(Host + Path); + private readonly Headers _headers = new(); + + private RouteService _sut; + private INodeService _nodeService; + private RouteInfo _result; + + public void GivenARequestPathIsAnApiCall() + { + _nodeService = Substitute.For(); + + var logger = Substitute.For>(); + var requestContext = SpecHelper.CreateRequestContext(); + var cacheKeyService = Substitute.For(); + var blockClusterConfig = new BlockClusterConfig( + AliasesWithApiRoutes: new[] + { + "test" + }); + var routeInfoFactory = new RouteInfoFactory( + requestContext, + blockClusterConfig); + var publishingService = SpecHelper.CreatePublishingService(routeInfoFactory); + + _sut = new RouteService( + blockClusterConfig, + _nodeService, + publishingService, + routeInfoFactory, + requestContext, + cacheKeyService, + logger); + } + + public async Task WhenTheRouteIsRequested() + { + _result = await _sut.GetRouteForRequest(_originUri, _headers); + } + + public void ThenNodeLookupIsPerformed() + { + _nodeService.ReceivedWithAnyArgs().GetByPath(Path); + } + + [Test] + public void Run() + { + this.BDDfy(); + } +} \ No newline at end of file diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsProxiedApiCall.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsProxiedApiCall.cs index ef2cd38..1c51fe5 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsProxiedApiCall.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsProxiedApiCall.cs @@ -27,10 +27,12 @@ public void GivenARequestPathIsAnApiCall() var logger = Substitute.For>(); var requestContext = SpecHelper.CreateRequestContext(); var cacheKeyService = Substitute.For(); - var routeInfoFactory = new RouteInfoFactory(requestContext, new BlockClusterConfig()); + var blockClusterConfig = new BlockClusterConfig(); + var routeInfoFactory = new RouteInfoFactory(requestContext, blockClusterConfig); var publishingService = SpecHelper.CreatePublishingService(routeInfoFactory); _sut = new RouteService( + blockClusterConfig, _nodeService, publishingService, routeInfoFactory, diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsRewrittenStaticResource.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsRewrittenStaticResource.cs index e0c6304..d8c4a82 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsRewrittenStaticResource.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsRewrittenStaticResource.cs @@ -24,8 +24,9 @@ public void GivenARequestPathIsARewrittenStaticResourcePath() requestContext.ProjectUuid.Returns(_projectUuid); var cacheKeyService = Substitute.For(); var logger = Substitute.For>(); + var blockClusterConfig = new BlockClusterConfig(); var routeInfoFactory = - new RouteInfoFactory(requestContext, new BlockClusterConfig()); + new RouteInfoFactory(requestContext, blockClusterConfig); var publishingService = SpecHelper.CreatePublishingService(routeInfoFactory); var block = publishingService.GetBlockById("blogs"); @@ -33,6 +34,7 @@ public void GivenARequestPathIsARewrittenStaticResourcePath() $"/{Constants.Paths.StaticPathUniquePrefix}{RouteInfo.GetUrlFriendlyHash(_projectUuid)}{Constants.Paths.StaticPathUniquePrefix}{block.Uuid}/static/images/header.png"; _sut = new RouteService( + blockClusterConfig, _nodeService, publishingService, routeInfoFactory, diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsRewrittenStaticResourceWithQueryString.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsRewrittenStaticResourceWithQueryString.cs index af87d23..9d826c4 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsRewrittenStaticResourceWithQueryString.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/PathIsRewrittenStaticResourceWithQueryString.cs @@ -26,7 +26,8 @@ public void GivenARequestPathIsARewrittenStaticResourcePathWithAQueryString() requestContext.ProjectUuid.Returns(_projectUuid); var cacheKeyService = Substitute.For(); var logger = Substitute.For>(); - var routeInfoFactory = new RouteInfoFactory(requestContext, new BlockClusterConfig()); + var blockClusterConfig = new BlockClusterConfig(); + var routeInfoFactory = new RouteInfoFactory(requestContext, blockClusterConfig); var publishingService = SpecHelper.CreatePublishingService(routeInfoFactory); var block = publishingService.GetBlockById("blogs"); @@ -35,6 +36,7 @@ public void GivenARequestPathIsARewrittenStaticResourcePathWithAQueryString() _originUri = new Uri("http://www.origin.com" + _requestPath); _sut = new RouteService( + blockClusterConfig, _nodeService, publishingService, routeInfoFactory, diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/ShouldNotPerformNodeLookupIfExcludedPath.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/ShouldNotPerformNodeLookupIfExcludedPath.cs index e744876..6a291bf 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/ShouldNotPerformNodeLookupIfExcludedPath.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/ShouldNotPerformNodeLookupIfExcludedPath.cs @@ -24,6 +24,7 @@ public void GivenARequestPathIsAnExcludedPath() var routeInfoFactory = Substitute.For(); _sut = new RouteService( + new BlockClusterConfig(), _nodeService, publishingService, routeInfoFactory, diff --git a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/ShouldPerformNodeLookup.cs b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/ShouldPerformNodeLookup.cs index ce672ae..1c0000d 100644 --- a/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/ShouldPerformNodeLookup.cs +++ b/tests/Zengenti.Contensis.RequestHandler.LocalDevelopment.Unit.Specs/Services/RouteServiceSpecs/ShouldPerformNodeLookup.cs @@ -25,6 +25,7 @@ public void GivenARequestPathIsAnExcludedPath() var routeInfoFactory = Substitute.For(); _sut = new RouteService( + new BlockClusterConfig(), _nodeService, publishingService, routeInfoFactory,