diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Services/ApiGatewayRouteConfigService.cs b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Services/ApiGatewayRouteConfigService.cs
index 66f8df4bd..63f81e217 100644
--- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Services/ApiGatewayRouteConfigService.cs
+++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Services/ApiGatewayRouteConfigService.cs
@@ -3,6 +3,7 @@
using System.Collections;
using System.Text.Json;
+using System.Text.RegularExpressions;
using Amazon.Lambda.TestTool.Models;
using Amazon.Lambda.TestTool.Services.IO;
@@ -142,19 +143,16 @@ private bool IsRouteConfigValid(ApiGatewayRouteConfig routeConfig)
return false;
}
- var occurrences = routeConfig.Path.Split("{proxy+}").Length - 1;
- if (occurrences > 1)
+ var segments = routeConfig.Path.Trim('/').Split('/');
+ foreach (var segment in segments)
{
- _logger.LogError("The route config {Method} {Path} cannot have multiple greedy variables {{proxy+}}.",
- routeConfig.HttpMethod, routeConfig.Path);
- return false;
- }
-
- if (occurrences == 1 && !routeConfig.Path.EndsWith("/{proxy+}"))
- {
- _logger.LogError("The route config {Method} {Path} uses a greedy variable {{proxy+}} but does not end with it.",
- routeConfig.HttpMethod, routeConfig.Path);
- return false;
+ var regexPattern = "^(\\{[\\w.:-]+\\+?\\}|[a-zA-Z0-9.:_-]+)$";
+ if (!Regex.IsMatch(segment, regexPattern))
+ {
+ _logger.LogError("One or more path parts appear to be invalid. Parts are validated against this regular expression: {Regex}",
+ regexPattern);
+ return false;
+ }
}
return true;
@@ -412,7 +410,7 @@ private bool IsVariableSegment(string segment)
/// true if the segment is a greedy variable segment; false otherwise.
private bool IsGreedyVariable(string segment)
{
- return segment.Equals("{proxy+}", StringComparison.InvariantCultureIgnoreCase);
+ return segment.StartsWith("{") && segment.EndsWith("+}");
}
///
diff --git a/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.UnitTests/Services/ApiGatewayRouteConfigServiceTests.cs b/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.UnitTests/Services/ApiGatewayRouteConfigServiceTests.cs
index 633b04b28..1ac75b9f3 100644
--- a/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.UnitTests/Services/ApiGatewayRouteConfigServiceTests.cs
+++ b/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.UnitTests/Services/ApiGatewayRouteConfigServiceTests.cs
@@ -119,6 +119,45 @@ public void GetRouteConfig_ReturnsNullForNonMatchingPath()
Assert.Null(result);
}
+ [Theory]
+ [InlineData("", "", "")]
+ [InlineData("F1", "", "")]
+ [InlineData("F1", "GET", "")]
+ [InlineData("F1", "GET", "//")]
+ [InlineData("F1", "GET", "/{}")]
+ [InlineData("F1", "GET", "/{+}")]
+ [InlineData("F1", "GET", "/{proxy+}+}")]
+ public void GetRouteConfig_InvalidPath(string lambdaName, string method, string template)
+ {
+ // Arrange
+ var routeConfig = new ApiGatewayRouteConfig
+ {
+ LambdaResourceName = lambdaName,
+ HttpMethod = method,
+ Path = template
+ };
+
+ _mockEnvironmentManager
+ .Setup(m => m.GetEnvironmentVariables())
+ .Returns(new Dictionary
+ {
+ { Constants.LambdaConfigEnvironmentVariablePrefix, JsonSerializer.Serialize(routeConfig) }
+ });
+
+ // Act
+ _ = new ApiGatewayRouteConfigService(_mockEnvironmentManager.Object, _mockLogger.Object);
+
+ // Assert
+ _mockLogger.Verify(
+ x => x.Log(
+ LogLevel.Error,
+ It.IsAny(),
+ It.Is((v, t) => v.ToString() == $"The route config {method} {template} is not valid. It will be skipped."),
+ It.IsAny(),
+ ((Func)It.IsAny