Skip to content

Commit 299321c

Browse files
Fix /health endpoint NotSupportedException from source-generated JSON serializer (#39)
* Fix /health endpoint NotSupportedException from source-generated JSON serializer Replace anonymous type in /health endpoint with a proper HealthResponse record registered in SkillServerJsonContext. The anonymous type was not recognized by the source-generated serializer, causing a runtime crash. * Assert /health response body in integration test Add JSON deserialization and field-level assertions for status and timestamp to the health endpoint test, catching serializer mismatches earlier.
1 parent 452e767 commit 299321c

4 files changed

Lines changed: 21 additions & 1 deletion

File tree

src/SkillServer/Endpoints.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ private static void MapSkillEndpoints(this WebApplication app)
5050

5151
private static void MapHealthEndpoints(this WebApplication app)
5252
{
53-
app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = DateTimeOffset.UtcNow }));
53+
app.MapGet("/health", () => Results.Json(
54+
new HealthResponse { Status = "healthy", Timestamp = DateTimeOffset.UtcNow },
55+
SkillServerJsonContext.Default.HealthResponse));
5456
}
5557

5658
private static async Task<IResult> ListSkills(

src/SkillServer/Models/ApiModels.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,15 @@ public sealed record ApiKeySummary
186186
[JsonPropertyName("expiresAt")]
187187
public DateTimeOffset? ExpiresAt { get; init; }
188188
}
189+
190+
/// <summary>
191+
/// Response from the health check endpoint.
192+
/// </summary>
193+
public sealed record HealthResponse
194+
{
195+
[JsonPropertyName("status")]
196+
public required string Status { get; init; }
197+
198+
[JsonPropertyName("timestamp")]
199+
public required DateTimeOffset Timestamp { get; init; }
200+
}

src/SkillServer/Models/SkillServerJsonContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace SkillServer.Models;
2626
[JsonSerializable(typeof(IReadOnlyList<ApiKeySummary>))]
2727
[JsonSerializable(typeof(IReadOnlyList<CheckUpdateRequestItem>))]
2828
[JsonSerializable(typeof(IReadOnlyList<CheckUpdateResponseItem>))]
29+
[JsonSerializable(typeof(HealthResponse))]
2930
[JsonSourceGenerationOptions(
3031
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
3132
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]

tests/SkillServer.Integration.Tests/SkillServerIntegrationTests.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public async Task Health_ReturnsOk()
3030
var response = await _fixture.HttpClient.GetAsync("/health", ct);
3131

3232
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
33+
34+
var body = await response.Content.ReadFromJsonAsync<SkillServer.Models.HealthResponse>(ct);
35+
Assert.NotNull(body);
36+
Assert.Equal("healthy", body.Status);
37+
Assert.True(body.Timestamp > DateTimeOffset.MinValue);
3338
}
3439

3540
[Fact]

0 commit comments

Comments
 (0)