using Core.Blueprint.Common.DependencyInjection; using Furniture.Bff.Application.Adapters; using Furniture.Bff.Application.DependencyInjection; using Furniture.Bff.Application.Handlers; using Furniture.Bff.Contracts.Api; using Furniture.Bff.Rest.Adapters; using Furniture.Bff.Rest.Endpoints; using Furniture.Service.Grpc; using Microsoft.Extensions.Primitives; const string CorrelationHeaderName = "x-correlation-id"; var builder = WebApplication.CreateBuilder(args); var edgeProtocol = builder.Configuration["FurnitureBff:EdgeProtocol"] ?? "rest"; if (!string.Equals(edgeProtocol, "rest", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException( $"Furniture BFF supports one active edge protocol per deployment. Configured: '{edgeProtocol}'. Expected: 'rest'."); } builder.Services.AddHttpContextAccessor(); builder.Services.AddHealthChecks(); builder.Services.AddBlueprintRuntimeCore(); builder.Services.AddFurnitureBffApplicationRuntime(); builder.Services.AddScoped(); builder.Services.AddGrpcClient(options => { var serviceAddress = builder.Configuration["FurnitureService:GrpcAddress"] ?? "http://localhost:5252"; options.Address = new Uri(serviceAddress); }); var app = builder.Build(); app.Use(async (context, next) => { var correlationId = ResolveCorrelationId(context); context.Items[CorrelationHeaderName] = correlationId; context.Request.Headers[CorrelationHeaderName] = correlationId; context.Response.Headers[CorrelationHeaderName] = correlationId; await next(); }); app.MapGet($"{EndpointConventions.ApiPrefix}/{{furnitureId}}/availability", async ( string furnitureId, HttpContext context, IGetFurnitureAvailabilityHandler handler) => { var request = new GetFurnitureAvailabilityApiRequest( furnitureId, ResolveCorrelationId(context)); var response = await handler.HandleAsync(request); return Results.Ok(response); }); app.MapHealthChecks("/healthz"); app.Run(); string ResolveCorrelationId(HttpContext context) { if (context.Items.TryGetValue(CorrelationHeaderName, out var itemValue) && itemValue is string itemCorrelationId && !string.IsNullOrWhiteSpace(itemCorrelationId)) { return itemCorrelationId; } if (context.Request.Headers.TryGetValue(CorrelationHeaderName, out var headerValue) && !StringValues.IsNullOrEmpty(headerValue)) { return headerValue.ToString(); } return context.TraceIdentifier; }