在运行时启用/禁用 SwaggerUI

Posted

技术标签:

【中文标题】在运行时启用/禁用 SwaggerUI【英文标题】:Enable/Disable SwaggerUI in runtime 【发布时间】:2021-07-13 06:22:57 【问题描述】:

我有 4 个环境开发、测试、暂存和生产。

我们必须只为生产环境禁用 Swagger,但这应该是可配置的,如果我们愿意,我们也可以启用它,以防万一在不重新构建应用程序的情况下测试某个端点。

这种 Swagger 的启用和禁用应该在运行时完成,正如我所提到的,我不想再次构建应用程序。

提前致谢。

【问题讨论】:

添加配置设置并仅在设置设置后启用 Swagger? 默认情况下,配置中间件将监控并重新加载对 appsettings.*.json 文件所做的更改。要在不重新启动应用程序的情况下获取它们的值,您需要使用 Options 中间件和 IOptionsMonitor 而不是 IOptionsIOptionsSnapshot 来访问配置值 @PanagiotisKanavos 重新加载配置对您没有帮助,因为您无法在运行时重新配置中间件管道(无需重新启动应用程序)。您需要使用app.MapWhenapp.UseWhen 访问最新配置。 @abdusco 仍然是 at runtime。在运行时并不意味着without restarting the appat runtime有很多度数。可能不需要使用MapWhen。即使在那里,使用IOptionsMonitor 也比使用自定义服务更好——或者不使用。 OP 在评论中提到了Azure API Management,这意味着问题不仅仅是启用 Swagger 【参考方案1】:

我通过配置来控制它,例如在appsettings.json


   "applicationSettings": 
      "serviceName": "Test",
      "swaggerUIEnabled": true
   

然后使用Swashbuckle.AspNetCore配置Startup.cs如下:

public class Startup

   private readonly IConfiguration _configuration;

   public Startup(IConfiguration configuration)
   
      _configuration = configuration;
   

   public void ConfigureServices(IServiceCollection services)
   
      services.AddSettings<ApplicationSettings>(_configuration.GetSection("applicationSettings"));

      // ...

      if (appSettings.SwaggerUIEnabled)
      
         services.AddSwaggerGen(c =>
         
            c.SwaggerDoc(appSettings.ServiceName,
               new OpenApiInfo
               
                  Title = appSettings.ServiceName,
                  Version = Assembly.GetEntryAssembly()?
                     .GetCustomAttribute<AssemblyInformationalVersionAttribute>()
                     .InformationalVersion ?? "NA"
               );
         );
      

      // ...
   

   public static void Configure(
      IApplicationBuilder app,
      IServiceProvider provider)
   
      // ...

      if (appSettings.SwaggerUIEnabled)
      
         app.UseStaticFiles()
            .UseSwagger()
            .UseSwaggerUI(c =>
            
               c.SwaggerEndpoint(Url.Combine("/", "swagger.json"), appSettings.ServiceName);
            );
      

      // ...
   

swaggerUIEnabled 配置设置将在所有非生产环境中为 true,在生产环境中为 false

注意:您需要在 wwwroot 下静态托管您的 Open API 规范(上述代码示例中的 swagger.json)。

【讨论】:

感谢您的回复。但是我已经这样做了,这将需要再次构建我不想做的应用程序。这种启用和禁用 SwaggerUI 应该在运行时完成,而无需构建应用程序。 如果您在 Azure 中托管您的应用并使用 Azure App Config,您可以使用 IOptionsMonitorIOptionsSnapshot 在运行时动态更新配置。或者,您可以在应用程序前面设置 API 网关(例如 Azure API 管理),您可以在其中阻止向 swagger UI 的请求(或返回 404 或其他内容)。 @RohanNegi 您无需重新编译即可更改配置文件中的设置。这就是配置设置的重点。只需更改生产服务器上的配置文件。您甚至可以使用环境变量或命令行参数覆盖它。在默认的 Web 主机中,环境变量会覆盖文件设置。您必须重新启动应用程序,除非您使用IOptions 功能 可以使用 Azure API 管理,这样我们就可以禁用 Swagger 相关的 URL @RohanNegi 外部服务与禁用您自己的服务端点有什么关系?你想问一个不同的问题吗?如何在特定时间将 Swagger 限制为特定客户?还是通过外部可信服务控制它?它很重要。您可以添加授权或限制访问。 at runtime 是一整套选择,从影响整个网络应用的设置到功能切换,再到影响单个请求的 cookie/令牌【参考方案2】:

虽然@Ryan.Bartsch 的回答是一种有效的方法,但它忽略了一个关键点:Startup.Configure 方法在启动时执行一次。当您更改配置时,IOptionsMonitor 会反映更改,但由于不会再次执行 Configure 方法,中间件管道将保持不变。您必须重新启动应用程序才能重新配置中间件。

要在运行时更改中间件,您可以使用IApplicationBuilder.UseWhen 并可选择启用 Swagger 中间件。这使您可以使用任何服务或普通的旧 IConfiguration(或 IOptionsSnapshot)来决定何时启用 Swagger。

来自the docs:

MapWhen 根据给定谓词的结果分支请求管道。任何Func&lt;HttpContext, bool&gt; 类型的谓词都可用于将请求映射到管道的新分支。 ...

UseWhen 还根据给定谓词的结果分支请求管道。与MapWhen 不同的是,如果该分支不短路或不包含终端中间件,则会重新加入主管道。

// remove default middleware
// app.UseSwagger(/*...*/);
// app.UseSwaggerUI(/*...*/);

app.UseWhen(context =>

    var swaggerToggle = context.RequestServices.GetRequiredService<SwaggerToggle>();
    var env = context.RequestServices.GetRequiredService<IWebHostEnvironment>();
    // enable swagger only in some cases, use a service, IConfiguration, ... anything, really.
    return env.IsDevelopment() || swaggerToggle.IsEnabled;
, builder => builder.UseSwagger(/*...*/).UseSwaggerUI(/*...*/));

// ... other middleware

SwaggerToggle 的示例实现如下:

public class SwaggerToggle

    public bool IsEnabled  get; set; 


// register the service as singleton
services.AddSingleton<SwaggerToggle>();

那么就可以通过端点来控制了

public class SwaggerToggleController : ControllerBase

    private readonly SwaggerToggle _swaggerToggle;

    public SwaggerToggleController(SwaggerToggle swaggerToggle)
    
        _swaggerToggle = swaggerToggle;
    
    
    [Authorize]
    [HttpPost]
    public ActionResult Toggle(bool enabled)
    
        _swaggerToggle.IsEnabled = enabled;
        return Ok(new  enabled );
    

【讨论】:

谢谢,@abdusco。这种方法对我有用。

以上是关于在运行时启用/禁用 SwaggerUI的主要内容,如果未能解决你的问题,请参考以下文章

在运行时本地启用/禁用 OpenMP

在 iOS 应用程序运行时启用/禁用 Crashlytics

在运行时禁用/启用 Firebase Crashlytics

如何在运行时将 UITableViewCell 从启用更改为禁用,使其文本从黑色变为灰色?

在应用程序运行时启用/禁用 Core Data 的 iCloud 同步

如何在运行时启用/禁用“org.eclipse.ui.editors”扩展