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).
|
// OpenAPI document for the Scalar API reference (Swashbuckle removed).
|
||||||
builder.Services.AddOpenApi();
|
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();
|
var app = builder.Build();
|
||||||
|
|
||||||
app.MapDefaultEndpoints();
|
app.MapDefaultEndpoints();
|
||||||
@@ -62,5 +69,6 @@ app.MapHealthRecordEndpoints();
|
|||||||
app.MapWeightRecordEndpoints();
|
app.MapWeightRecordEndpoints();
|
||||||
app.MapInbreedingEndpoints();
|
app.MapInbreedingEndpoints();
|
||||||
app.MapPhotoEndpoints();
|
app.MapPhotoEndpoints();
|
||||||
|
app.MapSaleAdEndpoints();
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|||||||
Reference in New Issue
Block a user