OneConversorTemplate/OnlyOneAccessTemplate/Controllers/DynamicProxyController.cs
2025-06-08 18:49:54 -03:00

113 lines
4.3 KiB
C#

using Microsoft.AspNetCore.Mvc;
using OnlyOneAccessTemplate.Services;
namespace OnlyOneAccessTemplate.Controllers
{
[Route("api/modules")]
public class DynamicProxyController : ControllerBase
{
private readonly IModuleService _moduleService;
private readonly HttpClient _httpClient;
private readonly IRateLimitService _rateLimitService;
private readonly ILogger<DynamicProxyController> _logger;
public DynamicProxyController(
IModuleService moduleService,
HttpClient httpClient,
IRateLimitService rateLimitService,
ILogger<DynamicProxyController> logger)
{
_moduleService = moduleService;
_httpClient = httpClient;
_rateLimitService = rateLimitService;
_logger = logger;
}
[HttpPost("{moduleId}/{action}")]
[HttpGet("{moduleId}/{action}")]
[HttpPut("{moduleId}/{action}")]
[HttpDelete("{moduleId}/{action}")]
public async Task<IActionResult> ProxyRequest(string moduleId, string action)
{
try
{
// Buscar configuração do módulo
var module = await _moduleService.GetModuleConfigAsync(moduleId);
if (module == null || !module.IsActive)
{
return NotFound(new { success = false, message = "Módulo não encontrado ou inativo" });
}
// Rate limiting
var clientIP = GetClientIP();
await _rateLimitService.RecordRequestAsync(clientIP);
if (await _rateLimitService.ShouldShowCaptchaAsync(clientIP))
{
return StatusCode(429, new
{
success = false,
message = "Rate limit exceeded",
requiresCaptcha = true
});
}
// Verificar se o endpoint existe no mapeamento
if (!module.ProxyMappings.ContainsKey(action))
{
return NotFound(new { success = false, message = $"Ação '{action}' não disponível para este módulo" });
}
var targetUrl = module.ProxyMappings[action];
// Preparar requisição
var requestMessage = new HttpRequestMessage(
new HttpMethod(Request.Method),
targetUrl + Request.QueryString);
// Copiar headers necessários
foreach (var header in module.Headers)
{
requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
// Copiar corpo da requisição se necessário
if (Request.ContentLength > 0)
{
requestMessage.Content = new StreamContent(Request.Body);
if (Request.ContentType != null)
{
requestMessage.Content.Headers.TryAddWithoutValidation("Content-Type", Request.ContentType);
}
}
_logger.LogInformation("Proxying {Method} request to {ModuleId}.{Action} -> {TargetUrl}",
Request.Method, moduleId, action, targetUrl);
// Fazer requisição
var response = await _httpClient.SendAsync(requestMessage);
var responseContent = await response.Content.ReadAsStringAsync();
// Retornar resposta
Response.StatusCode = (int)response.StatusCode;
if (response.Content.Headers.ContentType?.MediaType != null)
{
Response.ContentType = response.Content.Headers.ContentType.MediaType;
}
return Content(responseContent);
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro no proxy para {ModuleId}.{Action}", moduleId, action);
return StatusCode(500, new { success = false, message = "Erro interno do servidor" });
}
}
private string GetClientIP()
{
return HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
}
}
}