Skip to content

Commit cfa8b4b

Browse files
committed
Add health checks routing extensions
1 parent 6877014 commit cfa8b4b

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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.Text;
7+
using Microsoft.AspNetCore.Builder;
8+
using Microsoft.AspNetCore.Http;
9+
using Microsoft.AspNetCore.Routing;
10+
using Microsoft.Extensions.Options;
11+
12+
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks.Builder
13+
{
14+
public static class HealthCheckEndpointRouteBuilderExtensions
15+
{
16+
public static IEndpointConventionBuilder MapHealthChecks(
17+
this IEndpointRouteBuilder builder,
18+
string pattern)
19+
{
20+
if (builder == null)
21+
{
22+
throw new ArgumentNullException(nameof(builder));
23+
}
24+
25+
return MapHealthChecksCore(builder, pattern, null);
26+
}
27+
28+
public static IEndpointConventionBuilder MapHealthChecks(
29+
this IEndpointRouteBuilder builder,
30+
string pattern,
31+
HealthCheckOptions options)
32+
{
33+
if (builder == null)
34+
{
35+
throw new ArgumentNullException(nameof(builder));
36+
}
37+
38+
if (options == null)
39+
{
40+
throw new ArgumentNullException(nameof(options));
41+
}
42+
43+
return MapHealthChecksCore(builder, pattern, options);
44+
}
45+
46+
private static IEndpointConventionBuilder MapHealthChecksCore(IEndpointRouteBuilder builder, string pattern, HealthCheckOptions options)
47+
{
48+
var args = options != null ? new[] { Options.Create(options) } : Array.Empty<object>();
49+
50+
var pipeline = builder.CreateApplicationBuilder()
51+
.UseMiddleware<HealthCheckMiddleware>(args)
52+
.Build();
53+
54+
return builder.Map(pattern, "Health checks", pipeline);
55+
}
56+
}
57+
}

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: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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.Diagnostics.HealthChecks.Builder;
10+
using Microsoft.AspNetCore.Hosting;
11+
using Microsoft.AspNetCore.Routing;
12+
using Microsoft.AspNetCore.TestHost;
13+
using Moq;
14+
using Xunit;
15+
using Microsoft.Extensions.DependencyInjection;
16+
using Microsoft.AspNetCore.Http;
17+
18+
namespace Microsoft.AspNetCore.Diagnostics.HealthChecks
19+
{
20+
public class HealthCheckEndpointRouteBuilderExtensionsTest
21+
{
22+
[Fact]
23+
public async Task MapHealthChecks_ReturnsOk()
24+
{
25+
// Arrange
26+
var builder = new WebHostBuilder()
27+
.Configure(app =>
28+
{
29+
app.UseRouting(routes =>
30+
{
31+
routes.MapHealthChecks("/healthz");
32+
});
33+
})
34+
.ConfigureServices(services =>
35+
{
36+
services.AddRouting();
37+
services.AddHealthChecks();
38+
});
39+
var server = new TestServer(builder);
40+
var client = server.CreateClient();
41+
42+
// Act
43+
var response = await client.GetAsync("/healthz");
44+
45+
// Assert
46+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
47+
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
48+
Assert.Equal("Healthy", await response.Content.ReadAsStringAsync());
49+
}
50+
51+
[Fact]
52+
public async Task MapHealthChecks_WithOptions_ReturnsOk()
53+
{
54+
// Arrange
55+
var builder = new WebHostBuilder()
56+
.Configure(app =>
57+
{
58+
app.UseRouting(routes =>
59+
{
60+
routes.MapHealthChecks("/healthz", new HealthCheckOptions
61+
{
62+
ResponseWriter = async (context, report) =>
63+
{
64+
context.Response.ContentType = "text/plain";
65+
await context.Response.WriteAsync("Custom!");
66+
}
67+
});
68+
});
69+
})
70+
.ConfigureServices(services =>
71+
{
72+
services.AddRouting();
73+
services.AddHealthChecks();
74+
});
75+
var server = new TestServer(builder);
76+
var client = server.CreateClient();
77+
78+
// Act
79+
var response = await client.GetAsync("/healthz");
80+
81+
// Assert
82+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
83+
Assert.Equal("text/plain", response.Content.Headers.ContentType.ToString());
84+
Assert.Equal("Custom!", await response.Content.ReadAsStringAsync());
85+
}
86+
}
87+
}

0 commit comments

Comments
 (0)