Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LNK-3288: Combined swagger spec for all services in BFF #582

Draft
wants to merge 15 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions DotNet/LinkAdmin.BFF/Application/Swagger/ServiceSpecAppender.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using LantanaGroup.Link.Shared.Application.Models.Configs;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Readers;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace LantanaGroup.Link.LinkAdmin.BFF.Application.Swagger;

public class ServiceSpecAppender(
IOptions<ServiceRegistry> serviceRegistry,
HttpClient httpClient,
ILogger<ServiceSpecAppender> logger) : IDocumentFilter
{
private static readonly Dictionary<string, string> _responseCache = new();
seanmcilvenna marked this conversation as resolved.
Show resolved Hide resolved

private async Task<OpenApiDocument> GetServiceSpec(string swaggerSpecUrl)
{
if (!_responseCache.TryGetValue(swaggerSpecUrl, out var response))
{
response = await httpClient.GetStringAsync(swaggerSpecUrl);
_responseCache[swaggerSpecUrl] = response;
}

var openApiDocument = new OpenApiStringReader().Read(response, out var diagnostic);
return openApiDocument;
}

private static string GetDotNetSwaggerSpecUrl(string serviceUrl)
{
return serviceUrl.TrimEnd('/') + "/swagger/v1/swagger.json";
}

private static string GetJavaSwaggerSpecUrl(string serviceUrl)
{
return serviceUrl.TrimEnd('/') + "/v3/api-docs";
}

private async Task AddServiceSpec(OpenApiDocument swaggerDoc, string swaggerSpecUrl)
{
try
{
var serviceSpec = await GetServiceSpec(swaggerSpecUrl);
foreach (var path in serviceSpec.Paths)
{
// Assumes that the proxy path of the service is the same as the paths in the service spec
swaggerDoc.Paths.Add(path.Key, path.Value);
}
}
catch (Exception ex)
{
logger.LogWarning(ex, "Failed to add service spec to swagger doc");
}
}
seanmcilvenna marked this conversation as resolved.
Show resolved Hide resolved

public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
var tasks = new List<Task>();

if (!string.IsNullOrEmpty(serviceRegistry.Value.AuditServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.AuditServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.AccountServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.AccountServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.CensusServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetJavaSwaggerSpecUrl(serviceRegistry.Value.CensusServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.DataAcquisitionServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.DataAcquisitionServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.MeasureServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetJavaSwaggerSpecUrl(serviceRegistry.Value.MeasureServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.NormalizationServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.NormalizationServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.NotificationServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.NotificationServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.QueryDispatchServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.QueryDispatchServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.ReportServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.ReportServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.SubmissionServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.SubmissionServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.TenantService?.TenantServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.TenantService.TenantServiceUrl)));

if (!string.IsNullOrEmpty(serviceRegistry.Value.ValidationServiceUrl))
tasks.Add(AddServiceSpec(swaggerDoc, GetDotNetSwaggerSpecUrl(serviceRegistry.Value.ValidationServiceUrl)));

Task.WhenAll(tasks).GetAwaiter().GetResult();
}
seanmcilvenna marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions DotNet/LinkAdmin.BFF/LinkAdmin.BFF.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<PackageReference Include="Microsoft.Extensions.Compliance.Redaction" Version="8.7.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.0.0-preview" />
<PackageReference Include="Microsoft.Extensions.Telemetry" Version="8.7.0" />
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.6.22" />
seanmcilvenna marked this conversation as resolved.
Show resolved Hide resolved
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
<PackageReference Include="Serilog" Version="4.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
Expand Down
4 changes: 3 additions & 1 deletion DotNet/LinkAdmin.BFF/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Serilog.Exceptions;
using Serilog.Settings.Configuration;
using System.Reflection;
using System.Reflection.Metadata;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.DataProtection;
Expand All @@ -25,6 +26,7 @@
using LantanaGroup.Link.Shared.Application.Extensions;
using LantanaGroup.Link.Shared.Settings;
using LantanaGroup.Link.LinkAdmin.BFF.Application.Interfaces.Infrastructure;
using LantanaGroup.Link.LinkAdmin.BFF.Application.Swagger;
using LantanaGroup.Link.LinkAdmin.BFF.Infrastructure.Telemetry;
using LantanaGroup.Link.Shared.Application.Middleware;
using LantanaGroup.Link.Shared.Application.Extensions.ExternalServices;
Expand Down Expand Up @@ -303,7 +305,7 @@ static void RegisterServices(WebApplicationBuilder builder)
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);

c.DocumentFilter<ServiceSpecAppender>();
});

// Add logging redaction services
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class ServiceRegistry
public string QueryDispatchServiceUrl { get; set; } = null!;
public string ReportServiceUrl { get; set; } = null!;
public string SubmissionServiceUrl { get; set; } = null!;
public string ValidationServiceUrl { get; set; } = null!;
public TenantServiceRegistration TenantService { get; set; } = null!;

public string AccountServiceApiUrl
Expand Down
Loading