using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Server.Kestrel.Core; using MongoDB.Driver; using OnlyOneAccessTemplate.Models; using OnlyOneAccessTemplate.Services; var builder = WebApplication.CreateBuilder(args); // Configurações otimizadas para produção ARM64 if (builder.Environment.IsProduction()) { // Configurar Kestrel para melhor performance builder.WebHost.ConfigureKestrel(options => { options.Limits.MaxConcurrentConnections = 100; options.Limits.MaxConcurrentUpgradedConnections = 100; options.Limits.MaxRequestBodySize = 10 * 1024 * 1024; // 10MB options.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); options.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10)); options.AddServerHeader = false; }); // Configurações de logging otimizadas builder.Logging.ClearProviders(); builder.Logging.AddConsole(); builder.Logging.SetMinimumLevel(LogLevel.Warning); } // Add services to the container. builder.Services.AddControllersWithViews(options => { if (builder.Environment.IsProduction()) { // Configurações de cache para produção options.CacheProfiles.Add("Default", new CacheProfile() { Duration = 300 // 5 minutos }); } }); // Configurar Response Caching builder.Services.AddResponseCaching(options => { options.MaximumBodySize = 1024 * 1024; // 1MB options.UseCaseSensitivePaths = false; }); // Configurar Response Compression builder.Services.AddResponseCompression(options => { options.EnableForHttps = true; }); // Add services to the container builder.Services.AddControllersWithViews(); // Session support builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); // MongoDB Configuration builder.Services.AddSingleton(sp => { var connectionString = builder.Configuration.GetConnectionString("MongoDB"); return new MongoClient(connectionString); }); // Rate Limiting Service builder.Services.AddScoped(); // Configuration Service (para substituir o ISiteConfigurationService se necessário) builder.Services.AddScoped(); // Configuração de localização para SEO multi-idioma builder.Services.Configure(options => { var supportedCultures = new[] { "pt-BR", "en-US", "es-ES" }; options.SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); }); builder.Services.AddScoped(sp => { var client = sp.GetRequiredService(); var databaseName = builder.Configuration.GetValue("MongoDB:DatabaseName"); return client.GetDatabase(databaseName); }); // Custom Services builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddHttpClient(); // Converter Services - Registrar todos os conversores dispon�veis builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); // Substituindo UpperLowerConversorService por API com Polly builder.Services.AddHttpClient(); builder.Services.AddScoped(); // HttpClient for external calls builder.Services.AddHttpClient(); builder.Services.AddHttpClient(); // Response Compression builder.Services.AddResponseCompression(options => { options.EnableForHttps = true; }); // Response Caching builder.Services.AddResponseCaching(); // Memory Cache builder.Services.AddMemoryCache(); // Loggingbuilder.Logging.ClearProviders(); builder.Logging.AddConsole(); builder.Logging.AddDebug(); var app = builder.Build(); // Configure the HTTP request pipeline if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = ctx => { // Cache estático por 1 hora ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=3600"); } }); // Session app.UseSession(); // Response Compression & Caching app.UseResponseCompression(); app.UseResponseCaching(); app.UseRequestLocalization(); // Middleware para detectar configuração por domínio app.Use(async (context, next) => { var host = context.Request.Host.Host; var configService = context.RequestServices.GetRequiredService(); var config = await configService.GetConfigurationAsync(host); context.Items["SiteConfig"] = config; // Se não encontrou config por domínio, usar fallback baseado no idioma da URL if (config == null) { var pathSegments = context.Request.Path.Value?.Split('/', StringSplitOptions.RemoveEmptyEntries); var language = "pt"; // default if (pathSegments?.Length > 0 && new[] { "en", "es", "pt" }.Contains(pathSegments[0])) { language = pathSegments[0]; } // Usar seu serviço existente como fallback var siteConfigService = context.RequestServices.GetRequiredService(); var fallbackConfig = await siteConfigService.GetConfigurationAsync(language); context.Items["SiteConfig"] = fallbackConfig; } await next(); }); app.UseRouting(); // Custom routing for multilingual support app.MapControllerRoute( name: "converter-api", pattern: "converter/api/{action}/{converterType?}", defaults: new { controller = "Converter" }); app.MapControllerRoute( name: "converter-config", pattern: "converter/config/{converterType}", defaults: new { controller = "Converter", action = "GetConverterConfig" }); // Rotas específicas por idioma app.MapControllerRoute( name: "converter_localized_specific", pattern: "{language:regex(^(pt|en|es)$)}/{converter}", defaults: new { controller = "Converter", action = "Index" }); // Rota para home localizada app.MapControllerRoute( name: "home_localized", pattern: "{language:regex(^(pt|en|es)$)}", defaults: new { controller = "Home", action = "Index" }); app.MapControllerRoute( name: "module_endpoint", pattern: "modules/{moduleId}", defaults: new { controller = "Module", action = "GetModule" }); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); // SEO Routes app.MapGet("/sitemap.xml", async (ISiteConfigurationService siteConfig) => { var sitemap = await siteConfig.GenerateSitemapAsync(); return Results.Content(sitemap, "application/xml"); }); app.MapGet("/robots.txt", async (ISiteConfigurationService siteConfig) => { var robots = await siteConfig.GenerateRobotsAsync(); return Results.Content(robots, "text/plain"); }); // Health check endpoint app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = DateTime.UtcNow })); // Initialize default data on startup (only in development) if (app.Environment.IsDevelopment()) { using var scope = app.Services.CreateScope(); var siteConfigService = scope.ServiceProvider.GetRequiredService(); var logger = scope.ServiceProvider.GetRequiredService>(); try { // Verificar se j� existem configura��es var languages = new[] { "pt", "en", "es" }; foreach (var lang in languages) { var configExists = await siteConfigService.ConfigurationExistsAsync(lang); if (!configExists) { logger.LogInformation("Criando configura��o padr�o para idioma: {Language}", lang); _ = await siteConfigService.GetConfigurationAsync(lang); // Isso criar� a configura��o padr�o } } // Inicializar módulos de exemplo try { var moduleService = scope.ServiceProvider.GetRequiredService(); // Verificar se já existe módulo de exemplo var existingModule = await moduleService.GetModuleConfigAsync("footer-message"); if (existingModule == null) { var exampleModule = new ModuleConfig { ModuleId = "footer-message", Name = "Módulo de Mensagem do Footer", Url = "https://httpbin.org/html", // URL de exemplo que retorna HTML RequestBy = "footer-message", IsActive = true, CacheMinutes = 10 }; await moduleService.SaveModuleConfigAsync(exampleModule); logger.LogInformation("Módulo de exemplo criado: {ModuleId}", exampleModule.ModuleId); } } catch (Exception ex) { logger.LogError(ex, "Erro ao inicializar módulos de exemplo"); } } catch (Exception ex) { logger.LogError(ex, "Erro ao inicializar dados padr�o"); } } app.Run();