113 lines
4.3 KiB
C#
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";
|
|
}
|
|
}
|
|
} |