diff --git a/src/Http/Routing/src/Matching/DfaMatcherBuilder.cs b/src/Http/Routing/src/Matching/DfaMatcherBuilder.cs index b5b3721b23..180d91a177 100644 --- a/src/Http/Routing/src/Matching/DfaMatcherBuilder.cs +++ b/src/Http/Routing/src/Matching/DfaMatcherBuilder.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -429,7 +429,10 @@ namespace Microsoft.AspNetCore.Routing.Matching candidates, endpointSelectorPolicies?.ToArray() ?? Array.Empty(), JumpTableBuilder.Build(currentDefaultDestination, currentExitDestination, pathEntries), - BuildPolicy(currentExitDestination, node.NodeBuilder, policyEntries)); + // Use the final exit destination when building the policy state. + // We don't want to use either of the current destinations because they refer routing states, + // and a policy state should never transition back to a routing state. + BuildPolicy(exitDestination, node.NodeBuilder, policyEntries)); return currentStateIndex; diff --git a/src/Http/Routing/test/UnitTests/Matching/HostMatcherPolicyIntegrationTestBase.cs b/src/Http/Routing/test/UnitTests/Matching/HostMatcherPolicyIntegrationTestBase.cs index e3cb4732b6..2feddaace0 100644 --- a/src/Http/Routing/test/UnitTests/Matching/HostMatcherPolicyIntegrationTestBase.cs +++ b/src/Http/Routing/test/UnitTests/Matching/HostMatcherPolicyIntegrationTestBase.cs @@ -273,6 +273,38 @@ namespace Microsoft.AspNetCore.Routing.Matching MatcherAssert.AssertMatch(httpContext, endpoint); } + [Fact] + public async Task Match_CatchAllRouteWithMatchingHost_Success() + { + // Arrange + var endpoint = CreateEndpoint("/{**path}", hosts: new string[] { "contoso.com", }); + + var matcher = CreateMatcher(endpoint); + var httpContext = CreateContext("/hello", "contoso.com"); + + // Act + await matcher.MatchAsync(httpContext); + + // Assert + MatcherAssert.AssertMatch(httpContext, endpoint, new { path = "hello" }); + } + + [Fact] + public async Task Match_CatchAllRouteFailureHost_NoMatch() + { + // Arrange + var endpoint = CreateEndpoint("/{**path}", hosts: new string[] { "contoso.com", }); + + var matcher = CreateMatcher(endpoint); + var httpContext = CreateContext("/hello", "nomatch.com"); + + // Act + await matcher.MatchAsync(httpContext); + + // Assert + MatcherAssert.AssertNotMatch(httpContext); + } + private static Matcher CreateMatcher(params RouteEndpoint[] endpoints) { var services = new ServiceCollection()