edd*_*P23 9 swagger swagger-ui openapi asp.net-core-2.2
我正在使用此处描述的 Dotnet Core 运行状况检查。简而言之,它看起来像这样:
首先,您可以像这样配置服务:
services.AddHealthChecks()
.AddSqlServer("connectionString", name: "SQlServerHealthCheck")
... // Add multiple other checks
Run Code Online (Sandbox Code Playgroud)
然后,您注册一个端点,如下所示:
app.UseHealthChecks("/my/healthCheck/endpoint");
Run Code Online (Sandbox Code Playgroud)
我们也在使用 Swagger(又名 Open API),我们通过 Swagger UI 查看所有端点,但看不到健康检查端点。
有没有办法将它添加到控制器方法中,以便 Swagger 自动获取端点,或者以另一种方式将它与 swagger 集成?
到目前为止,我发现的最佳解决方案是添加自定义硬编码端点(如此处所述),但维护起来并不好。
我使用了这种方法,它对我来说效果很好:https : //www.codit.eu/blog/documenting-asp-net-core-health-checks-with-openapi
添加一个新控制器,例如 HealthController 并将 HealthCheckService 注入构造函数。当您在 Startup.cs 中调用 AddHealthChecks 时,将 HealthCheckService 添加为依赖项:
重建时 HealthController 应该出现在 Swagger 中:
[Route("api/v1/health")]
public class HealthController : Controller
{
private readonly HealthCheckService _healthCheckService;
public HealthController(HealthCheckService healthCheckService)
{
_healthCheckService = healthCheckService;
}
/// <summary>
/// Get Health
/// </summary>
/// <remarks>Provides an indication about the health of the API</remarks>
/// <response code="200">API is healthy</response>
/// <response code="503">API is unhealthy or in degraded state</response>
[HttpGet]
[ProducesResponseType(typeof(HealthReport), (int)HttpStatusCode.OK)]
[SwaggerOperation(OperationId = "Health_Get")]
public async Task<IActionResult> Get()
{
var report = await _healthCheckService.CheckHealthAsync();
return report.Status == HealthStatus.Healthy ? Ok(report) : StatusCode((int)HttpStatusCode.ServiceUnavailable, report);
}
}
Run Code Online (Sandbox Code Playgroud)
我注意到的一件事是端点仍然是“/health”(或您在 Startup.cs 中设置的任何内容)而不是“/api/vxx/health”,但它仍然会在 Swagger 中正确显示。
由于 Swagger 已更新,.NET 2.x 和 3.1/Swagger 4.0.0 和 5.0.0 之间发生了重大变化
以下是适用于 5.0.0 的穷人解决方案版本(请参阅 eddyP23 答案)。
public class HealthChecksFilter : IDocumentFilter
{
public const string HealthCheckEndpoint = @"/healthcheck";
public void Apply(OpenApiDocument openApiDocument, DocumentFilterContext context)
{
var pathItem = new OpenApiPathItem();
var operation = new OpenApiOperation();
operation.Tags.Add(new OpenApiTag { Name = "ApiHealth" });
var properties = new Dictionary<string, OpenApiSchema>();
properties.Add("status", new OpenApiSchema() { Type = "string" });
properties.Add("errors", new OpenApiSchema() { Type = "array" });
var response = new OpenApiResponse();
response.Content.Add("application/json", new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "object",
AdditionalPropertiesAllowed = true,
Properties = properties,
}
});
operation.Responses.Add("200", response);
pathItem.AddOperation(OperationType.Get, operation);
openApiDocument?.Paths.Add(HealthCheckEndpoint, pathItem);
}
}
Run Code Online (Sandbox Code Playgroud)
仍在寻找更好的解决方案,但穷人的解决方案是这样的:
public const string HealthCheckEndpoint = "/my/healthCheck/endpoint";
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
var pathItem = new PathItem();
pathItem.Get = new Operation()
{
Tags = new[] { "ApiHealth" },
Produces = new[] { "application/json" }
};
var properties = new Dictionary<string, Schema>();
properties.Add("status", new Schema(){ Type = "string" });
properties.Add("errors", new Schema(){ Type = "array" });
var exampleObject = new { status = "Healthy", errors = new List<string>()};
pathItem.Get.Responses = new Dictionary<string, Response>();
pathItem.Get.Responses.Add("200", new Response() {
Description = "OK",
Schema = new Schema() {
Properties = properties,
Example = exampleObject }});
swaggerDoc.Paths.Add(HealthCheckEndpoint, pathItem);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7766 次 |
| 最近记录: |