Skip to content

Commit

Permalink
Remove redundant routes
Browse files Browse the repository at this point in the history
  • Loading branch information
satano committed Dec 3, 2023
1 parent 698d55b commit bb579b1
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private RouteDocs GetRouteDocs(RouteOptions route)
JToken paths = docs[OpenApiProperties.Paths];
string downstreamPath = GetDownstreamPath(route);
JProperty path = paths.OfType<JProperty>().FirstOrDefault(p =>
downstreamPath.Equals(p.Name.WithSlashEnding(), StringComparison.CurrentCultureIgnoreCase));
downstreamPath.Equals(p.Name.WithSlashEnding(), StringComparison.OrdinalIgnoreCase));

return new RouteDocs()
{
Expand Down
2 changes: 1 addition & 1 deletion src/MMLib.SwaggerForOcelot/Configuration/RouteOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ private string DownstreamPathWithVirtualDirectory
/// Gets a value indicating whether this instance can catch all.
/// </summary>
public bool CanCatchAll
=> DownstreamPathTemplate.EndsWith(CatchAllPlaceHolder, StringComparison.CurrentCultureIgnoreCase);
=> DownstreamPathTemplate.EndsWith(CatchAllPlaceHolder, StringComparison.OrdinalIgnoreCase);

/// <summary>
/// Gets the upstream path.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private string TransformOpenApi(
private void RenameAndRemovePaths(IEnumerable<RouteOptions> routes, JToken paths, string basePath)
{
var oldPaths = new List<JProperty>();
var newPaths = new Dictionary<string, JProperty>();
var newPaths = new Dictionary<string, JProperty>(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < paths.Count(); i++)
{
var oldPath = paths.ElementAt(i) as JProperty;
Expand Down Expand Up @@ -281,9 +281,35 @@ static bool MatchPaths(RouteOptions route, string downstreamPath)
: route.DownstreamPathWithSlash.Equals(downstreamPath, StringComparison.OrdinalIgnoreCase);

string downstreamPathWithBasePath = PathHelper.BuildPath(basePath, downstreamPath);
return routes
var matchedRoutes = routes
.Where(route => route.ContainsHttpMethod(method) && MatchPaths(route, downstreamPathWithBasePath))
.ToList();

RemoveRedundantRoutes(matchedRoutes);
return matchedRoutes;
}

// Redundant routes are routes with the ALMOST same upstream path templates. For example these path templates
// are redundant:
// - /api/projects/Projects
// - /api/projects/Projects/
// - /api/projects/Projects/{everything}
//
// `route.UpstreamPath` contains route without trailing slash and without catch-all placeholder, so all previous
// routes have the same upstream path `/api/projects/Projects`. The logic is to keep just the shortestof the path
// templates. If we would keep all routes, it will throw an exception during the generation of the swagger document
// later because of the same paths.
private static void RemoveRedundantRoutes(List<RouteOptions> routes)
{
IEnumerable<IGrouping<string, RouteOptions>> groups = routes
.GroupBy(route => route.UpstreamPath, StringComparer.OrdinalIgnoreCase)
.Where(group => group.Count() > 1);
foreach (var group in groups)
{
group.OrderBy(r => r.DownstreamPathTemplate.Length)
.Skip(1)
.ForEach(r => routes.Remove(r));
}
}

private static void AddHost(JObject swagger, string swaggerHost)
Expand All @@ -305,7 +331,7 @@ private static string ConvertDownstreamPathToUpstreamPath(string downstreamPath,
downstreamPath = PathHelper.BuildPath(downstreamBasePath, downstreamPath);
}

int pos = downstreamPath.IndexOf(downstreamPattern, StringComparison.CurrentCultureIgnoreCase);
int pos = downstreamPath.IndexOf(downstreamPattern, StringComparison.OrdinalIgnoreCase);
if (pos < 0)
{
return downstreamPath;
Expand Down

0 comments on commit bb579b1

Please sign in to comment.