From 1234320b8a8abf0044bcd52cf74695117b6d363d Mon Sep 17 00:00:00 2001 From: Radoslav Radev Date: Mon, 11 Mar 2024 19:44:58 +0100 Subject: [PATCH 1/3] implemented a workaround for Conul service discovary. all thought the solution in this PR works (please take it as just guidance on how to fix it) , i didnt had time to get fully familiar with your code base and just aplied a hot fix --- .../Middleware/SwaggerForOcelotMiddleware.cs | 46 +++++++++---------- .../DownstreamSwaggerDocsRepository.cs | 6 +++ .../SwaggerServiceDiscoveryProvider.cs | 6 +++ 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs b/src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs index 544c8b9..7e1cea6 100644 --- a/src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs +++ b/src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs @@ -14,6 +14,7 @@ using Microsoft.OpenApi.Writers; using System.Text; using Microsoft.OpenApi.Models; +using MMLib.SwaggerForOcelot.ServiceDiscovery; namespace MMLib.SwaggerForOcelot.Middleware { @@ -42,13 +43,9 @@ public class SwaggerForOcelotMiddleware /// The SwaggerJsonTransformer /// Swagger provider. /// Downstream interceptor. - public SwaggerForOcelotMiddleware( - RequestDelegate next, - SwaggerForOcelotUIOptions options, - IOptionsMonitor> routes, - ISwaggerJsonTransformer transformer, - ISwaggerProvider swaggerProvider, - ISwaggerDownstreamInterceptor downstreamInterceptor = null) + public SwaggerForOcelotMiddleware(RequestDelegate next, SwaggerForOcelotUIOptions options, + IOptionsMonitor> routes, ISwaggerJsonTransformer transformer, + ISwaggerProvider swaggerProvider, ISwaggerDownstreamInterceptor downstreamInterceptor = null) { _transformer = Check.NotNull(transformer, nameof(transformer)); _next = Check.NotNull(next, nameof(next)); @@ -64,11 +61,11 @@ public SwaggerForOcelotMiddleware( /// The context. /// Swagger endpoint repository. /// Repository for obtaining downstream swagger docs. - public async Task Invoke(HttpContext context, - ISwaggerEndPointProvider swaggerEndPointRepository, + public async Task Invoke(HttpContext context, ISwaggerEndPointProvider swaggerEndPointRepository, IDownstreamSwaggerDocsRepository downstreamSwaggerDocs) { - (string version, SwaggerEndPointOptions endPoint) = GetEndPoint(context.Request.Path, swaggerEndPointRepository); + (string version, SwaggerEndPointOptions endPoint) = + GetEndPoint(context.Request.Path, swaggerEndPointRepository); if (_downstreamInterceptor != null && !_downstreamInterceptor.DoDownstreamSwaggerEndpoint(context, version, endPoint)) @@ -84,22 +81,22 @@ public async Task Invoke(HttpContext context, return; } - IEnumerable routeOptions = _routes.CurrentValue - .ExpandConfig(endPoint) - .GroupByPaths(); + IEnumerable routeOptions = _routes.CurrentValue.ExpandConfig(endPoint).GroupByPaths(); RouteOptions route = routeOptions.FirstOrDefault(r => r.SwaggerKey == endPoint.Key); string content = await downstreamSwaggerDocs.GetSwaggerJsonAsync(route, endPoint, version); - if (endPoint.TransformByOcelotConfig) - { - content = _transformer.Transform( - content, - routeOptions, - GetServerName(context, endPoint), - endPoint); - } + if (SwaggerServiceDiscoveryProvider.ServiceProviderType != "Consul") // ignore if Consul , this will just replace the freshly fetched swagger json from the service with an empty one + if (endPoint.TransformByOcelotConfig) + { + content = _transformer.Transform( + content, + routeOptions, + GetServerName(context, endPoint), + endPoint); + } + content = await ReconfigureUpstreamSwagger(context, content); await context.Response.WriteAsync(content); @@ -124,8 +121,8 @@ private string GetServerName(HttpContext context, SwaggerEndPointOptions endPoin string serverName; if (string.IsNullOrWhiteSpace(_options.ServerOcelot)) { - serverName = endPoint.HostOverride - ?? $"{context.Request.Scheme}://{context.Request.Host.Value.RemoveSlashFromEnd()}"; + serverName = endPoint.HostOverride ?? + $"{context.Request.Scheme}://{context.Request.Host.Value.RemoveSlashFromEnd()}"; } else { @@ -156,8 +153,7 @@ private async Task ReconfigureUpstreamSwagger(HttpContext context, strin return swaggerJson; } - private (string version, SwaggerEndPointOptions endpoint) GetEndPoint( - string path, + private (string version, SwaggerEndPointOptions endpoint) GetEndPoint(string path, ISwaggerEndPointProvider swaggerEndPointRepository) { (string Version, string Key) endPointInfo = GetEndPointInfo(path); diff --git a/src/MMLib.SwaggerForOcelot/Repositories/DownstreamSwaggerDocsRepository.cs b/src/MMLib.SwaggerForOcelot/Repositories/DownstreamSwaggerDocsRepository.cs index 2c9615b..12a2efd 100644 --- a/src/MMLib.SwaggerForOcelot/Repositories/DownstreamSwaggerDocsRepository.cs +++ b/src/MMLib.SwaggerForOcelot/Repositories/DownstreamSwaggerDocsRepository.cs @@ -46,6 +46,12 @@ public async Task GetSwaggerJsonAsync( var clientName = _options.Value.HttpClientName ?? ((route?.DangerousAcceptAnyServerCertificateValidator ?? false) ? ServiceCollectionExtensions.IgnoreSslCertificate : string.Empty); var httpClient = _httpClientFactory.CreateClient(clientName); + if (!(url.StartsWith("http://") || url.StartsWith("https://"))) //the url that gets constructed when using consul misses the http schema , and trows an exception + { + url = "https://" + url; //appending https because that`s what i use (there is no real way to figure out the protocol from Consul) + } + + SetHttpVersion(httpClient, route); AddHeaders(httpClient); diff --git a/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs b/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs index bab1ea6..19c53df 100644 --- a/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs +++ b/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs @@ -81,6 +81,9 @@ private async Task GetSwaggerUri(SwaggerEndPointConfig endPoint, RouteOptio { var conf = _configurationCreator.Create(_options.CurrentValue.GlobalConfiguration); + ServiceProviderType = conf.Type; // get a way to detect who the service provider is + + var downstreamRoute = new DownstreamRouteBuilder() .WithUseServiceDiscovery(true) .WithServiceName(endPoint.Service.Name) @@ -125,6 +128,9 @@ private string GetScheme(ServiceHostAndPort service, RouteOptions route) _ => string.Empty, }; + + public static string ServiceProviderType { get; set; } + private static string GetErrorMessage(SwaggerEndPointConfig endPoint) => $"Service with swagger documentation '{endPoint.Service.Name}' cann't be discovered"; } } From ebf8afc6a14844d89ac026e78f112eb73ff6f1a9 Mon Sep 17 00:00:00 2001 From: Radoslav Radev Date: Fri, 15 Mar 2024 12:31:53 +0100 Subject: [PATCH 2/3] added changes requested to, accept PR --- .../Middleware/SwaggerForOcelotMiddleware.cs | 40 ++++++++++--------- .../DownstreamSwaggerDocsRepository.cs | 5 +-- .../SwaggerServiceDiscoveryProvider.cs | 4 +- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs b/src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs index 7e1cea6..4e4fa5d 100644 --- a/src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs +++ b/src/MMLib.SwaggerForOcelot/Middleware/SwaggerForOcelotMiddleware.cs @@ -1,4 +1,4 @@ -using Kros.Utils; +using Kros.Utils; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using MMLib.SwaggerForOcelot.Configuration; @@ -43,9 +43,13 @@ public class SwaggerForOcelotMiddleware /// The SwaggerJsonTransformer /// Swagger provider. /// Downstream interceptor. - public SwaggerForOcelotMiddleware(RequestDelegate next, SwaggerForOcelotUIOptions options, - IOptionsMonitor> routes, ISwaggerJsonTransformer transformer, - ISwaggerProvider swaggerProvider, ISwaggerDownstreamInterceptor downstreamInterceptor = null) + public SwaggerForOcelotMiddleware( + RequestDelegate next, + SwaggerForOcelotUIOptions options, + IOptionsMonitor> routes, + ISwaggerJsonTransformer transformer, + ISwaggerProvider swaggerProvider, + ISwaggerDownstreamInterceptor downstreamInterceptor = null) { _transformer = Check.NotNull(transformer, nameof(transformer)); _next = Check.NotNull(next, nameof(next)); @@ -61,11 +65,11 @@ public SwaggerForOcelotMiddleware(RequestDelegate next, SwaggerForOcelotUIOption /// The context. /// Swagger endpoint repository. /// Repository for obtaining downstream swagger docs. - public async Task Invoke(HttpContext context, ISwaggerEndPointProvider swaggerEndPointRepository, + public async Task Invoke(HttpContext context, + ISwaggerEndPointProvider swaggerEndPointRepository, IDownstreamSwaggerDocsRepository downstreamSwaggerDocs) { - (string version, SwaggerEndPointOptions endPoint) = - GetEndPoint(context.Request.Path, swaggerEndPointRepository); + (string version, SwaggerEndPointOptions endPoint) = GetEndPoint(context.Request.Path, swaggerEndPointRepository); if (_downstreamInterceptor != null && !_downstreamInterceptor.DoDownstreamSwaggerEndpoint(context, version, endPoint)) @@ -81,21 +85,20 @@ public async Task Invoke(HttpContext context, ISwaggerEndPointProvider swaggerEn return; } - IEnumerable routeOptions = _routes.CurrentValue.ExpandConfig(endPoint).GroupByPaths(); + IEnumerable routeOptions = _routes.CurrentValue + .ExpandConfig(endPoint) + .GroupByPaths(); RouteOptions route = routeOptions.FirstOrDefault(r => r.SwaggerKey == endPoint.Key); string content = await downstreamSwaggerDocs.GetSwaggerJsonAsync(route, endPoint, version); - - if (SwaggerServiceDiscoveryProvider.ServiceProviderType != "Consul") // ignore if Consul , this will just replace the freshly fetched swagger json from the service with an empty one + if (SwaggerServiceDiscoveryProvider.ServiceProviderType != "Consul") + { if (endPoint.TransformByOcelotConfig) { - content = _transformer.Transform( - content, - routeOptions, - GetServerName(context, endPoint), - endPoint); + content = _transformer.Transform(content, routeOptions, GetServerName(context, endPoint), endPoint); } + } content = await ReconfigureUpstreamSwagger(context, content); @@ -121,8 +124,8 @@ private string GetServerName(HttpContext context, SwaggerEndPointOptions endPoin string serverName; if (string.IsNullOrWhiteSpace(_options.ServerOcelot)) { - serverName = endPoint.HostOverride ?? - $"{context.Request.Scheme}://{context.Request.Host.Value.RemoveSlashFromEnd()}"; + serverName = endPoint.HostOverride + ?? $"{context.Request.Scheme}://{context.Request.Host.Value.RemoveSlashFromEnd()}"; } else { @@ -153,7 +156,8 @@ private async Task ReconfigureUpstreamSwagger(HttpContext context, strin return swaggerJson; } - private (string version, SwaggerEndPointOptions endpoint) GetEndPoint(string path, + private (string version, SwaggerEndPointOptions endpoint) GetEndPoint( + string path, ISwaggerEndPointProvider swaggerEndPointRepository) { (string Version, string Key) endPointInfo = GetEndPointInfo(path); diff --git a/src/MMLib.SwaggerForOcelot/Repositories/DownstreamSwaggerDocsRepository.cs b/src/MMLib.SwaggerForOcelot/Repositories/DownstreamSwaggerDocsRepository.cs index 12a2efd..a597746 100644 --- a/src/MMLib.SwaggerForOcelot/Repositories/DownstreamSwaggerDocsRepository.cs +++ b/src/MMLib.SwaggerForOcelot/Repositories/DownstreamSwaggerDocsRepository.cs @@ -46,12 +46,11 @@ public async Task GetSwaggerJsonAsync( var clientName = _options.Value.HttpClientName ?? ((route?.DangerousAcceptAnyServerCertificateValidator ?? false) ? ServiceCollectionExtensions.IgnoreSslCertificate : string.Empty); var httpClient = _httpClientFactory.CreateClient(clientName); - if (!(url.StartsWith("http://") || url.StartsWith("https://"))) //the url that gets constructed when using consul misses the http schema , and trows an exception + if (!(url.StartsWith("http://",StringComparison.InvariantCultureIgnoreCase) || url.StartsWith("https://",StringComparison.InvariantCultureIgnoreCase))) { - url = "https://" + url; //appending https because that`s what i use (there is no real way to figure out the protocol from Consul) + url = "https://" + url; } - SetHttpVersion(httpClient, route); AddHeaders(httpClient); diff --git a/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs b/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs index 19c53df..34c8d77 100644 --- a/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs +++ b/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs @@ -81,8 +81,7 @@ private async Task GetSwaggerUri(SwaggerEndPointConfig endPoint, RouteOptio { var conf = _configurationCreator.Create(_options.CurrentValue.GlobalConfiguration); - ServiceProviderType = conf.Type; // get a way to detect who the service provider is - + ServiceProviderType = conf.Type; var downstreamRoute = new DownstreamRouteBuilder() .WithUseServiceDiscovery(true) @@ -128,7 +127,6 @@ private string GetScheme(ServiceHostAndPort service, RouteOptions route) _ => string.Empty, }; - public static string ServiceProviderType { get; set; } private static string GetErrorMessage(SwaggerEndPointConfig endPoint) => $"Service with swagger documentation '{endPoint.Service.Name}' cann't be discovered"; From 59786fc90dffc5c42a58a32c9a68402e25efadc1 Mon Sep 17 00:00:00 2001 From: Radoslav Radev Date: Tue, 26 Mar 2024 21:33:22 +0100 Subject: [PATCH 3/3] updated the ServiceProviderType to support null since the conf is null when unit testing --- .../ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs b/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs index 34c8d77..bd5b7a3 100644 --- a/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs +++ b/src/MMLib.SwaggerForOcelot/ServiceDiscovery/SwaggerServiceDiscoveryProvider.cs @@ -81,7 +81,7 @@ private async Task GetSwaggerUri(SwaggerEndPointConfig endPoint, RouteOptio { var conf = _configurationCreator.Create(_options.CurrentValue.GlobalConfiguration); - ServiceProviderType = conf.Type; + ServiceProviderType = conf?.Type; var downstreamRoute = new DownstreamRouteBuilder() .WithUseServiceDiscovery(true) @@ -127,7 +127,7 @@ private string GetScheme(ServiceHostAndPort service, RouteOptions route) _ => string.Empty, }; - public static string ServiceProviderType { get; set; } + public static string? ServiceProviderType { get; set; } private static string GetErrorMessage(SwaggerEndPointConfig endPoint) => $"Service with swagger documentation '{endPoint.Service.Name}' cann't be discovered"; }