FEAT-12a: POST /gerbils/sale-ad endpoint (503 AiKeyMissing when unconfigured, 502 AiUpstreamError) + DI wiring
This commit is contained in:
34
GerbilManagerWebAPI/Endpoints/SaleAdEndpoints.cs
Normal file
34
GerbilManagerWebAPI/Endpoints/SaleAdEndpoints.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using GerbilManagerWebAPI.SaleAd;
|
||||
|
||||
namespace GerbilManagerWebAPI.Endpoints
|
||||
{
|
||||
/// <summary>
|
||||
/// FEAT-12a: POST /gerbils/sale-ad — AI-gestütztes Abgabe-Inserat (frozen
|
||||
/// contract, see gerbil-manager-web/src/api/saleAd.ts).
|
||||
///
|
||||
/// 503 {code:"AiKeyMissing"} while the AI section is unconfigured — the
|
||||
/// frontend maps exactly this code to its German disabled-state hint.
|
||||
/// </summary>
|
||||
public static class SaleAdEndpoints
|
||||
{
|
||||
public static IEndpointRouteBuilder MapSaleAdEndpoints(this IEndpointRouteBuilder app)
|
||||
{
|
||||
app.MapPost("/gerbils/sale-ad",
|
||||
async (SaleAdRequest request, SaleAdService service, CancellationToken ct) =>
|
||||
{
|
||||
var result = await service.GenerateAsync(request, ct);
|
||||
return result.Status switch
|
||||
{
|
||||
SaleAdStatus.Ok => Results.Ok(new SaleAdResponse(result.Text!)),
|
||||
SaleAdStatus.NotConfigured => Results.Json(
|
||||
new SaleAdError("AiKeyMissing", result.Error ?? ""), statusCode: 503),
|
||||
_ => Results.Json(
|
||||
new SaleAdError("AiUpstreamError", result.Error ?? ""), statusCode: 502),
|
||||
};
|
||||
})
|
||||
.WithTags("SaleAd");
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,13 @@ builder.Services.AddCors(options => options.AddPolicy(LanCorsPolicy, policy =>
|
||||
// OpenAPI document for the Scalar API reference (Swashbuckle removed).
|
||||
builder.Services.AddOpenApi();
|
||||
|
||||
// FEAT-12a: provider-agnostic AI config (env vars AI__BaseUrl/AI__ApiKey/AI__Model
|
||||
// or user-secrets — never committed) + typed client for sale-ad generation.
|
||||
builder.Services.AddOptions<GerbilManagerWebAPI.SaleAd.AiOptions>()
|
||||
.BindConfiguration(GerbilManagerWebAPI.SaleAd.AiOptions.SectionName);
|
||||
builder.Services.AddHttpClient<GerbilManagerWebAPI.SaleAd.SaleAdService>(
|
||||
http => http.Timeout = TimeSpan.FromSeconds(60));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapDefaultEndpoints();
|
||||
@@ -62,5 +69,6 @@ app.MapHealthRecordEndpoints();
|
||||
app.MapWeightRecordEndpoints();
|
||||
app.MapInbreedingEndpoints();
|
||||
app.MapPhotoEndpoints();
|
||||
app.MapSaleAdEndpoints();
|
||||
|
||||
app.Run();
|
||||
|
||||
Reference in New Issue
Block a user