173 lines
5.7 KiB
C#
173 lines
5.7 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Asp.Versioning;
|
|
using FluentValidation;
|
|
using Hellang.Middleware.ProblemDetails;
|
|
using BookingService.API.Application.Behaviors;
|
|
using BookingService.Infrastructure;
|
|
using Serilog;
|
|
|
|
// EN: Configure Serilog early / VI: Cấu hình Serilog sớm
|
|
Log.Logger = new LoggerConfiguration()
|
|
.WriteTo.Console()
|
|
.CreateBootstrapLogger();
|
|
|
|
try
|
|
{
|
|
Log.Information("Starting BookingService API / Khởi động BookingService API");
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// EN: Configure Serilog / VI: Cấu hình Serilog
|
|
builder.Host.UseSerilog((context, services, configuration) => configuration
|
|
.ReadFrom.Configuration(context.Configuration)
|
|
.ReadFrom.Services(services)
|
|
.Enrich.FromLogContext()
|
|
.WriteTo.Console());
|
|
|
|
// EN: Add Infrastructure services / VI: Thêm Infrastructure services
|
|
builder.Services.AddInfrastructure(builder.Configuration);
|
|
|
|
// EN: Add MediatR with behaviors / VI: Thêm MediatR với behaviors
|
|
builder.Services.AddMediatR(cfg =>
|
|
{
|
|
cfg.RegisterServicesFromAssemblyContaining<Program>();
|
|
cfg.AddOpenBehavior(typeof(LoggingBehavior<,>));
|
|
cfg.AddOpenBehavior(typeof(ValidatorBehavior<,>));
|
|
cfg.AddOpenBehavior(typeof(TransactionBehavior<,>));
|
|
});
|
|
|
|
// EN: Add FluentValidation / VI: Thêm FluentValidation
|
|
builder.Services.AddValidatorsFromAssemblyContaining<Program>();
|
|
|
|
// EN: Add API versioning / VI: Thêm API versioning
|
|
builder.Services.AddApiVersioning(options =>
|
|
{
|
|
options.DefaultApiVersion = new ApiVersion(1, 0);
|
|
options.AssumeDefaultVersionWhenUnspecified = true;
|
|
options.ReportApiVersions = true;
|
|
options.ApiVersionReader = ApiVersionReader.Combine(
|
|
new UrlSegmentApiVersionReader(),
|
|
new HeaderApiVersionReader("X-Api-Version"));
|
|
})
|
|
.AddApiExplorer(options =>
|
|
{
|
|
options.GroupNameFormat = "'v'VVV";
|
|
options.SubstituteApiVersionInUrl = true;
|
|
});
|
|
|
|
// EN: Add controllers / VI: Thêm controllers
|
|
builder.Services.AddControllers();
|
|
|
|
// EN: Add ProblemDetails middleware (RFC 7807) / VI: Thêm ProblemDetails middleware
|
|
builder.Services.AddProblemDetails(options =>
|
|
{
|
|
options.IncludeExceptionDetails = (ctx, ex) =>
|
|
builder.Environment.IsDevelopment();
|
|
});
|
|
|
|
// EN: Add Swagger / VI: Thêm Swagger
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerGen(options =>
|
|
{
|
|
options.SwaggerDoc("v1", new()
|
|
{
|
|
Title = "BookingService API",
|
|
Version = "v1",
|
|
Description = "BookingService microservice API / API microservice BookingService"
|
|
});
|
|
});
|
|
|
|
// EN: Add health checks / VI: Thêm health checks
|
|
builder.Services.AddHealthChecks()
|
|
.AddNpgSql(
|
|
builder.Configuration.GetConnectionString("DefaultConnection")
|
|
?? builder.Configuration["DATABASE_URL"]
|
|
?? "",
|
|
name: "postgresql",
|
|
tags: ["db", "postgresql"]);
|
|
|
|
// EN: Add JWT Bearer authentication via IAM IdentityServer OIDC discovery
|
|
// VI: Thêm JWT Bearer authentication qua IAM IdentityServer OIDC discovery
|
|
var jwtAuthority = builder.Configuration["Jwt:Authority"] ?? "http://localhost:5001";
|
|
builder.Services.AddAuthentication(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme)
|
|
.AddJwtBearer(options =>
|
|
{
|
|
options.Authority = jwtAuthority;
|
|
options.RequireHttpsMetadata = false;
|
|
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
|
|
{
|
|
ValidateIssuer = false,
|
|
ValidateAudience = false,
|
|
ValidateLifetime = true,
|
|
};
|
|
});
|
|
builder.Services.AddAuthorization();
|
|
|
|
// EN: Add CORS / VI: Thêm CORS
|
|
builder.Services.AddCors(options =>
|
|
{
|
|
options.AddDefaultPolicy(policy =>
|
|
{
|
|
policy.AllowAnyOrigin()
|
|
.AllowAnyMethod()
|
|
.AllowAnyHeader();
|
|
});
|
|
});
|
|
|
|
var app = builder.Build();
|
|
|
|
// EN: Configure middleware pipeline / VI: Cấu hình middleware pipeline
|
|
app.UseSerilogRequestLogging();
|
|
app.UseProblemDetails();
|
|
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.UseSwagger();
|
|
app.UseSwaggerUI(c =>
|
|
{
|
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "BookingService API v1");
|
|
c.RoutePrefix = "swagger";
|
|
});
|
|
}
|
|
|
|
app.UseCors();
|
|
app.UseRouting();
|
|
app.UseAuthentication();
|
|
app.UseAuthorization();
|
|
|
|
// EN: Map health check endpoints / VI: Map health check endpoints
|
|
app.MapHealthChecks("/health");
|
|
app.MapHealthChecks("/health/live", new()
|
|
{
|
|
Predicate = _ => false // EN: Just checks app is running / VI: Chỉ kiểm tra app đang chạy
|
|
});
|
|
app.MapHealthChecks("/health/ready");
|
|
|
|
// EN: Map controllers / VI: Map controllers
|
|
app.MapControllers();
|
|
|
|
// EN: Run the application / VI: Chạy ứng dụng
|
|
// EN: Auto-apply EF Core migrations on startup
|
|
// VI: Tự động áp dụng EF Core migrations khi khởi động
|
|
using (var scope = app.Services.CreateScope())
|
|
{
|
|
var dbContext = scope.ServiceProvider.GetRequiredService<BookingContext>();
|
|
await dbContext.Database.MigrateAsync();
|
|
}
|
|
|
|
app.Run();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Fatal(ex, "Application terminated unexpectedly / Ứng dụng kết thúc bất ngờ");
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
Log.CloseAndFlush();
|
|
}
|
|
|
|
// EN: Make Program class accessible for integration tests
|
|
// VI: Làm cho class Program có thể truy cập cho integration tests
|
|
public partial class Program { }
|