cambiado requisito de cabeceras en todas las llamadas y simualcion de datos en la 3 llamada para pruebas

This commit is contained in:
2026-09-09 14:57:46 +02:00
parent 65bde15ea8
commit 5c3c12c02c
3 changed files with 54 additions and 80 deletions

View File

@@ -15,19 +15,13 @@ public sealed class OpeController : ControllerBase
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
private readonly OpeOptions _options;
private readonly InternalDenunciasClient _internalApi;
private readonly OpeFieldMapper _fieldMapper;
private readonly ILogger<OpeController> _logger;
public OpeController(
IOptions<OpeOptions> options,
InternalDenunciasClient internalApi,
OpeFieldMapper fieldMapper,
ILogger<OpeController> logger)
{
_options = options.Value;
_internalApi = internalApi;
_fieldMapper = fieldMapper;
_logger = logger;
}
@@ -82,54 +76,25 @@ public sealed class OpeController : ControllerBase
});
}
try
{
var result = await _internalApi.GetFieldsAsync(
lookup,
requestContext.TransactionId,
cancellationToken);
// Respuesta temporal de pruebas: no consulta la API interna ni exige
// que el expediente exista. FIELD_0 conserva exactamente el valor
// recibido y el resto de campos devuelve un valor ficticio.
_logger.LogInformation(
"Respuesta OPE de prueba para el expediente solicitado {Expediente}. TransactionId={TransactionId}",
identifier,
requestContext.TransactionId);
if (result.Status == InternalLookupStatus.NotFound || result.Fields is null)
var testData = new Dictionary<string, OpeFieldValue>(StringComparer.Ordinal)
{
return Error(
"No se ha encontrado la denuncia o expediente solicitado",
OpeErrorCauses.ElementNotExists,
null);
["FIELD_0"] = new OpeFieldValue("STRING", identifier)
};
for (var index = 1; index < _options.OutputFields.Count; index++)
{
testData[$"FIELD_{index}"] = new OpeFieldValue("STRING", "dato de prueba");
}
return Json(_fieldMapper.Map(result.Fields), OpeMediaTypes.GenericOperationResponse);
}
catch (OperationCanceledException) when (!HttpContext.RequestAborted.IsCancellationRequested)
{
_logger.LogWarning(
"Timeout consultando ApiDenuncias para una OPE. TransactionId={TransactionId}",
requestContext.TransactionId);
return Error("Error en el conector", OpeErrorCauses.ConnectorError, null);
}
catch (HttpRequestException exception)
{
_logger.LogWarning(
exception,
"No se ha podido conectar con ApiDenuncias. TransactionId={TransactionId}",
requestContext.TransactionId);
return Error("Error en el conector", OpeErrorCauses.ConnectorError, null);
}
catch (InternalApiException exception)
{
_logger.LogWarning(
exception,
"ApiDenuncias ha devuelto una respuesta no utilizable. TransactionId={TransactionId}",
requestContext.TransactionId);
return Error("Error en el conector", OpeErrorCauses.ConnectorError, null);
}
catch (InvalidDataException exception)
{
_logger.LogError(
exception,
"El contrato entre ApiOPE y ApiDenuncias no coincide. TransactionId={TransactionId}",
requestContext.TransactionId);
return Error("Error en el conector", OpeErrorCauses.ConnectorError, null);
}
return Json(new OpeDataEnvelope(testData), OpeMediaTypes.GenericOperationResponse);
}
private static ContentResult Error(

View File

@@ -2,7 +2,6 @@ using System.Security.Claims;
using ApiOPE.Configuration;
using ApiOPE.Contracts;
using ApiOPE.Services;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using System.Security.Cryptography;
using System.Text;
@@ -31,8 +30,7 @@ public sealed class OpeAuthenticationMiddleware
HttpContext context,
OpeTokenValidator tokenValidator,
OpeResponseSigner responseSigner,
OpeRequestFileLogger requestFileLogger,
IOptions<OpeOptions> options)
OpeRequestFileLogger requestFileLogger)
{
var authentication = context.GetEndpoint()?.Metadata.GetMetadata<OpeAuthenticatedAttribute>();
if (authentication is null)
@@ -54,12 +52,6 @@ public sealed class OpeAuthenticationMiddleware
return;
}
if (!ValidateOrganizationHeaders(context.Request.Headers, options.Value, out var organizationFailure))
{
await RejectAsync(context, organizationFailure, requestFileLogger, token, validation.RequestContext);
return;
}
OpeRequestContextStore.Set(context, validation.RequestContext);
context.User = new ClaimsPrincipal(new ClaimsIdentity(
[
@@ -92,6 +84,13 @@ public sealed class OpeAuthenticationMiddleware
validation.RequestContext.TransactionId.ToString(),
context.TraceIdentifier,
Fingerprint(validation.RequestContext.ClientToken),
context.Connection.RemoteIpAddress?.ToString(),
ReadHeader(context.Request.Headers, OrganizationIdHeaderName),
ReadHeader(context.Request.Headers, OrganizationDir3HeaderName),
ReadHeader(context.Request.Headers, OrganizationCifHeaderName),
ReadHeader(context.Request.Headers, "Content-Type"),
ReadHeader(context.Request.Headers, "Accept"),
ReadHeader(context.Request.Headers, "User-Agent"),
null));
}
}
@@ -118,6 +117,13 @@ public sealed class OpeAuthenticationMiddleware
requestContext?.TransactionId.ToString(),
context.TraceIdentifier,
string.IsNullOrWhiteSpace(token) ? null : Fingerprint(token),
context.Connection.RemoteIpAddress?.ToString(),
ReadHeader(context.Request.Headers, OrganizationIdHeaderName),
ReadHeader(context.Request.Headers, OrganizationDir3HeaderName),
ReadHeader(context.Request.Headers, OrganizationCifHeaderName),
ReadHeader(context.Request.Headers, "Content-Type"),
ReadHeader(context.Request.Headers, "Accept"),
ReadHeader(context.Request.Headers, "User-Agent"),
reason));
await OpeResponseWriter.WriteErrorAsync(
@@ -132,26 +138,10 @@ public sealed class OpeAuthenticationMiddleware
private static string Fingerprint(string value)
=> Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(value)))[..12];
private static bool ValidateOrganizationHeaders(
IHeaderDictionary headers,
OpeOptions options,
out string failureReason)
{
var valid = MatchesHeader(headers, OrganizationIdHeaderName, options.OrganizationId) &&
MatchesHeader(headers, OrganizationDir3HeaderName, options.OrganizationDir3) &&
MatchesHeader(headers, OrganizationCifHeaderName, options.OrganizationCif);
failureReason = valid
? string.Empty
: "Las cabeceras de organizacion no corresponden al conector configurado.";
return valid;
}
private static bool MatchesHeader(IHeaderDictionary headers, string name, string expected)
{
return TryGetSingleHeader(headers, name, out var value) &&
string.Equals(value, expected, StringComparison.OrdinalIgnoreCase);
}
private static string? ReadHeader(IHeaderDictionary headers, string name)
=> headers.TryGetValue(name, out var values) && values.Count > 0
? string.Join(",", values.ToArray()).Trim()
: null;
private static bool TryGetSingleHeader(
IHeaderDictionary headers,

View File

@@ -59,6 +59,13 @@ public sealed record OpeRequestLogEntry(
string? TransactionId,
string? RequestId,
string? ClientTokenFingerprint,
string? RemoteIp,
string? OrganizationId,
string? OrganizationDir3,
string? OrganizationCif,
string? ContentType,
string? Accept,
string? UserAgent,
string? FailureReason)
{
public string ToDisplayLine()
@@ -69,8 +76,20 @@ public sealed record OpeRequestLogEntry(
Path,
$"HTTP {StatusCode}",
Result,
$"ip={Clean(RemoteIp)}",
$"orgId={Clean(OrganizationId)}",
$"dir3={Clean(OrganizationDir3)}",
$"cif={Clean(OrganizationCif)}",
$"contentType={Clean(ContentType)}",
$"accept={Clean(Accept)}",
$"userAgent={Clean(UserAgent)}",
$"transaccion={TransactionId ?? "-"}",
$"peticion={RequestId ?? "-"}",
$"cliente={ClientTokenFingerprint ?? "-"}",
$"motivo={FailureReason ?? "-"}");
$"motivo={Clean(FailureReason)}");
private static string Clean(string? value)
=> string.IsNullOrWhiteSpace(value)
? "-"
: value.Replace("\r", " ").Replace("\n", " ").Trim();
}