diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiPathsRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiPathsRules.cs index d94f7a31a..422accabc 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiPathsRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiPathsRules.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Properties; @@ -36,7 +35,6 @@ public static class OpenApiPathsRules } }); - private static readonly Regex regexPath = new Regex("\\{([^/}]+)\\}", RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)); /// /// A relative path to an individual endpoint. The field name MUST begin with a slash. /// @@ -50,7 +48,7 @@ public static class OpenApiPathsRules { context.Enter(path); - var pathSignature = regexPath.Replace(path, "{}"); + var pathSignature = GetPathSignature(path); if (!hashSet.Add(pathSignature)) context.CreateError(nameof(PathMustBeUnique), @@ -60,6 +58,38 @@ public static class OpenApiPathsRules } }); + /// + /// Replaces placeholders in the path with {}, e.g. /pets/{petId} becomes /pets/{} . + /// + /// The input path + /// The path signature + private static string GetPathSignature(string path) + { + int i = 0; + + while (i < path.Length) + { + int openBrace = path.IndexOf('{', i); + + if (openBrace < 0) + { + return path; + } + + int closeBrace = path.IndexOf('}', openBrace); + + if (closeBrace < 0) + { + return path; + } + + path = path.Substring(0, openBrace + 1) + path.Substring(closeBrace, path.Length - closeBrace); + i = openBrace + 2; + } + + return path; + } + // add more rules } }