在运行时启用/禁用 SwaggerUI
Posted
技术标签:
【中文标题】在运行时启用/禁用 SwaggerUI【英文标题】:Enable/Disable SwaggerUI in runtime 【发布时间】:2021-07-13 06:22:57 【问题描述】:我有 4 个环境开发、测试、暂存和生产。
我们必须只为生产环境禁用 Swagger,但这应该是可配置的,如果我们愿意,我们也可以启用它,以防万一在不重新构建应用程序的情况下测试某个端点。
这种 Swagger 的启用和禁用应该在运行时完成,正如我所提到的,我不想再次构建应用程序。
提前致谢。
【问题讨论】:
添加配置设置并仅在设置设置后启用 Swagger? 默认情况下,配置中间件将监控并重新加载对 appsettings.*.json 文件所做的更改。要在不重新启动应用程序的情况下获取它们的值,您需要使用 Options 中间件和IOptionsMonitor
而不是 IOptions
或 IOptionsSnapshot
来访问配置值
@PanagiotisKanavos 重新加载配置对您没有帮助,因为您无法在运行时重新配置中间件管道(无需重新启动应用程序)。您需要使用app.MapWhen
或app.UseWhen
访问最新配置。
@abdusco 仍然是 at runtime
。在运行时并不意味着without restarting the app
。 at 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,您可以使用IOptionsMonitor
或 IOptionsSnapshot
在运行时动态更新配置。或者,您可以在应用程序前面设置 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<HttpContext, bool>
类型的谓词都可用于将请求映射到管道的新分支。 ...
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的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 应用程序运行时启用/禁用 Crashlytics
在运行时禁用/启用 Firebase Crashlytics
如何在运行时将 UITableViewCell 从启用更改为禁用,使其文本从黑色变为灰色?