Skip to content

Commit 5ab3c89

Browse files
authored
Add health checks routing extensions (#5127)
1 parent 28cf059 commit 5ab3c89

File tree

3 files changed

+158
-0
lines changed

3 files changed

+158
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using Microsoft.AspNetCore.Builder;
6+
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
7+
using Microsoft.Extensions.Options;
8+
using Microsoft.AspNetCore.Routing;
9+
10+
namespace Microsoft.AspNetCore.Builder
11+
{
12+
/// <summary>
13+
/// Provides extension methods for <see cref="IEndpointRouteBuilder"/> to add health checks.
14+
/// </summary>
15+
public static class HealthCheckEndpointRouteBuilderExtensions
16+
{
17+
/// <summary>
18+
/// Adds a health checks endpoint to the <see cref="IEndpointRouteBuilder"/> with the specified template.
19+
/// </summary>
20+
/// <param name="builder">The <see cref="IEndpointRouteBuilder"/> to add the health checks endpoint to.</param>
21+
/// <param name="pattern">The URL pattern of the health checks endpoint.</param>
22+
/// <returns>A convention builder for the health checks endpoint.</returns>
23+
public static IEndpointConventionBuilder MapHealthChecks(
24+
this IEndpointRouteBuilder builder,
25+
string pattern)
26+
{
27+
if (builder == null)
28+
{
29+
throw new ArgumentNullException(nameof(builder));
30+
}
31+
32+
return MapHealthChecksCore(builder, pattern, null);
33+
}
34+
35+
/// <summary>
36+
/// Adds a health checks endpoint to the <see cref="IEndpointRouteBuilder"/> with the specified template and options.
37+
/// </summary>
38+
/// <param name="builder">The <see cref="IEndpointRouteBuilder"/> to add the health checks endpoint to.</param>
39+
/// <param name="pattern">The URL pattern of the health checks endpoint.</param>
40+
/// <param name="options">A <see cref="HealthCheckOptions"/> used to configure the health checks.</param>
41+
/// <returns>A convention builder for the health checks endpoint.</returns>
42+
public static IEndpointConventionBuilder MapHealthChecks(
43+
this IEndpointRouteBuilder builder,
44+
string pattern,
45+
HealthCheckOptions options)
46+
{
47+
if (builder == null)
48+
{
49+
throw new ArgumentNullException(nameof(builder));
50+
}
51+
52+
if (options == null)
53+
{
54+
throw new ArgumentNullException(nameof(options));
55+
}
56+
57+
return MapHealthChecksCore(builder, pattern, options);
58+
}
59+
60+
private static IEndpointConventionBuilder MapHealthChecksCore(IEndpointRouteBuilder builder, string pattern, HealthCheckOptions options)
61+
{
62+
var args = options != null ? new[] { Options.Create(options) } : Array.Empty<object>();
63+
64+
var pipeline = builder.CreateApplicationBuilder()
65+
.UseMiddleware<HealthCheckMiddleware>(args)
66+
.Build();
67+
68+
return builder.Map(pattern, "Health checks", pipeline);
69+
}
70+
}
71+
}

src/Middleware/HealthChecks/src/Microsoft.AspNetCore.Diagnostics.HealthChecks.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
<ItemGroup>
1919
<Reference Include="Microsoft.AspNetCore.Http.Abstractions" />
20+
<Reference Include="Microsoft.AspNetCore.Routing" />
2021
<Reference Include="Microsoft.Extensions.Diagnostics.HealthChecks" />
2122
<Reference Include="Microsoft.Extensions.Options" />
2223
<Reference Include="Microsoft.Net.Http.Headers" />
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Net;
7+
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Builder;
9+
using Microsoft.AspNetCore.Hosting;
10+
using Microsoft.AspNetCore.Routing;
11+
using Microsoft.AspNetCore.TestHost;
12+
using Moq;
13+
using Xunit;
14+
using Microsoft.Extensions.DependencyInjection;
15+
using Microsoft.AspNetCore.Http;
16+
17+
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
18+
{
19+
public class HealthCheckEndpointRouteBuilderExtensionsTest
20+
{
21+
[Fact]
22+
public async Task MapHealthChecks_ReturnsOk()
23+
{
24+
// Arrange
25+
var builder = new WebHostBuilder()
26+
.Configure(app =>
27+
{
28+
app.UseRouting(routes =>
29+
{
30+
routes.MapHealthChecks("/healthz");
31+
});
32+
})
33+
.ConfigureServices(services =>
34+
{
35+
services.AddRouting();
36+
services.AddHealthChecks();
37+
});
38+
var server = new TestServer(builder);
39+
var client = server.CreateClient();
40+
41+
// Act
42+
var response = await client.GetAsync("/healthz");
43+
44+
// Assert
45+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
46+
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
47+
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
48+
}
49+
50+
[Fact]
51+
public async Task MapHealthChecks_WithOptions_ReturnsOk()
52+
{
53+
// Arrange
54+
var builder = new WebHostBuilder()
55+
.Configure(app =>
56+
{
57+
app.UseRouting(routes =>
58+
{
59+
routes.MapHealthChecks("/healthz", new HealthCheckOptions
60+
{
61+
ResponseWriter = async (context, report) =>
62+
{
63+
context.Response.ContentType = "text/plain";
64+
await context.Response.WriteAsync("Custom!");
65+
}
66+
});
67+
});
68+
})
69+
.ConfigureServices(services =>
70+
{
71+
services.AddRouting();
72+
services.AddHealthChecks();
73+
});
74+
var server = new TestServer(builder);
75+
var client = server.CreateClient();
76+
77+
// Act
78+
var response = await client.GetAsync("/healthz");
79+
80+
// Assert
81+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
82+
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
83+
Assert.Equal("Custom!", await response.Content.ReadAsStringAsync());
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)