是否可以为SwaggerUI动态添加SwaggerEndpoint? [英] Is It Possible to Dynamically Add SwaggerEndpoints For SwaggerUI?

查看:125
本文介绍了是否可以为SwaggerUI动态添加SwaggerEndpoint?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在.NET Core中构建面向服务的体系结构.我们已经决定使用Ocelot作为我们的API网关.我已经将Ocelot与Consul集成在一起以进行服务发现.现在,我试图为所有下游服务创建一个统一的Swagger UI.

We're building out a services oriented architecture in .NET Core. We've decided to use Ocelot as our API gateway. I have integrated Ocelot with Consul for service discovery. Now I'm trying to attempt to create a unified Swagger UI for all the downstream services.

在发现服务之前,我们进行了以下Swagger设置:

Prior to service discovery we had Swagger setup like this:

// Enable middleware to serve generated Swagger as a JSON endpoint
app.UseSwagger(c => { c.RouteTemplate = "{documentName}/swagger.json"; });

// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
app.UseSwaggerUI(c =>
{
  c.SwaggerEndpoint("/docs/customer/swagger.json", "Customers Api Doc");
  c.SwaggerEndpoint("/docs/employee/swagger.json", "Employee Api Doc");
  c.SwaggerEndpoint("/docs/report/swagger.json", "Reports Api Doc");
});

在Swagger UI上,这提供了选择规格"下拉列表.开发人员喜欢此功能,我们希望保留它.但是,由于我们已经删除了手动配置以支持服务发现,因此我们也希望动态更新这些端点.

On the Swagger UI this provides a "select a spec" dropdown. The developers like this functionality and we'd like to keep it. However, now that we've removed the manual configuration in favor of service discovery we would also like to have these endpoints dynamically updated.

使用当前可用的Swagger解决方案,这可能吗?我还没有看到任何有关服务发现或能够动态配置UI的信息.有想法和建议吗?

With the current Swagger solution that's available is this possible? I haven't seen anything relating to service discovery or being able to dynamically configure the UI. Thoughts and suggestions?

我想出了一种方法来做到这一点.有点hack-ish,我希望有一种方法可以使这种方法不那么费力.

I've come up with a way to do this. It is a bit hack-ish and I'm hoping there is a way to do this that isn't so heavy handed.

public class Startup 
{
    static object LOCK = new object();

    SwaggerUIOptions options;

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<SwaggerUIOptions>((provider) =>
        {
            return this.options;
        });
        services.AddSingleton<IHostedService, SwaggerUIDocsAggregator>();
        services.AddSingleton<IConsulDiscoveryService, MyCounsulDiscoveryServiceImplementation>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Enable middleware to serve generated Swagger as a JSON endpoint
        app.UseSwagger(c => { c.RouteTemplate = "{documentName}/swagger.json"; });
        // Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
        app.UseSwaggerUI(c =>
        {
            this.options = c;
        });
    }
}

public class SwaggerUIDocsAggregator : IHostedService
{
    static object LOCK = new object();

    IConsulDiscoveryService discoveryService;
    SwaggerUIOptions options;
    Timer timer;
    bool polling = false;
    int pollingInterval = 600;

    public ConsulHostedService(IConsulDiscoveryService discoveryService, SwaggerUIOptions options)
    {
        this.discoveryService = discoveryService;
        this.options = options;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        this.timer = new Timer(async x =>
        {
            if (this.polling)
            {
                return;
            }

            lock (LOCK)
            {
                this.polling = true;
            }

            await this.UpdateDocs();

            lock (LOCK)
            {
                this.polling = false;
            }

        }, null, 0, pollingInterval);
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        this.timer.Dispose();
        this.timer = null;
    }

    private async Task UpdateDocs()
    {
        var discoveredServices = await this.discoveryService.LookupServices();

        var urls = new JArray();

        foreach (var kvp in discoveredServices)
        {
            var serviceName = kvp.Key;

            if (!urls.Any(u => (u as JObject).GetValue("url").Value<string>().Equals($"/{serviceName}/docs/swagger.json")))
            {

                urls.Add(JObject.FromObject(new { url = $"/{serviceName}/docs/swagger.json", name = serviceName }));
            }
        }

        this.options.ConfigObject["urls"] = urls;
    }
}

推荐答案

将Ocelot api网关作为所有下游服务的统一Swagger UI进行集成的简便方法是项目

Easy way for integration Ocelot api gateway as a unified Swagger UI for all the downstream services is project MMLib.SwaggerForOcelot.

这篇关于是否可以为SwaggerUI动态添加SwaggerEndpoint?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆