OneConversorTemplate/OnlyOneAccessTemplate/Program.cs
2025-06-08 12:44:02 -03:00

297 lines
9.6 KiB
C#
Raw Blame History

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<IMongoClient>(sp =>
{
var connectionString = builder.Configuration.GetConnectionString("MongoDB");
return new MongoClient(connectionString);
});
// Rate Limiting Service
builder.Services.AddScoped<IRateLimitService, RateLimitService>();
// Configuration Service (para substituir o ISiteConfigurationService se necessário)
builder.Services.AddScoped<IConfigurationService, ConfigurationService>();
// Configuração de localização para SEO multi-idioma
builder.Services.Configure<RequestLocalizationOptions>(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<IMongoClient>();
var databaseName = builder.Configuration.GetValue<string>("MongoDB:DatabaseName");
return client.GetDatabase(databaseName);
});
// Custom Services
builder.Services.AddScoped<ISiteConfigurationService, SiteConfigurationService>();
builder.Services.AddScoped<ILanguageService, LanguageService>();
builder.Services.AddScoped<ISeoService, SeoService>();
builder.Services.AddScoped<IConversionService, ConversionService>();
builder.Services.AddScoped<IModuleService, ModuleService>();
builder.Services.AddHttpClient<IModuleService, ModuleService>();
// Converter Services - Registrar todos os conversores dispon<6F>veis
builder.Services.AddScoped<TextCaseConverterService>();
builder.Services.AddScoped<CsvToJsonConverterService>();
builder.Services.AddScoped<ImageToTextConverterService>();
// Substituindo UpperLowerConversorService por API com Polly
builder.Services.AddHttpClient<ITextConversionApiService, TextConversionApiService>();
builder.Services.AddScoped<ApiBasedSentenceConverterService>();
// HttpClient for external calls
builder.Services.AddHttpClient<ConversionService>();
builder.Services.AddHttpClient<ImageToTextConverterService>();
// 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<IConfigurationService>();
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<ISiteConfigurationService>();
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<ISiteConfigurationService>();
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
try
{
// Verificar se j<> existem configura<72><61>es
var languages = new[] { "pt", "en", "es" };
foreach (var lang in languages)
{
var configExists = await siteConfigService.ConfigurationExistsAsync(lang);
if (!configExists)
{
logger.LogInformation("Criando configura<72><61>o padr<64>o para idioma: {Language}", lang);
_ = await siteConfigService.GetConfigurationAsync(lang); // Isso criar<61> a configura<72><61>o padr<64>o
}
}
// Inicializar módulos de exemplo
try
{
var moduleService = scope.ServiceProvider.GetRequiredService<IModuleService>();
// 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<64>o");
}
}
app.Run();