Add error handling for permission API calls and enhance logging in middleware
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m15s
All checks were successful
Build & Deploy Leave Service / build (push) Successful in 1m15s
This commit is contained in:
parent
d3501e831c
commit
d945deae4f
3 changed files with 72 additions and 40 deletions
|
|
@ -62,6 +62,10 @@ namespace BMA.EHR.Application.Repositories
|
||||||
new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", ""));
|
new AuthenticationHeaderValue("Bearer", AccessToken.Replace("Bearer ", ""));
|
||||||
client.DefaultRequestHeaders.Add("api-key", _configuration["API_KEY"]);
|
client.DefaultRequestHeaders.Add("api-key", _configuration["API_KEY"]);
|
||||||
var req = await client.GetAsync(apiPath);
|
var req = await client.GetAsync(apiPath);
|
||||||
|
if (!req.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
throw new Exception("Error calling permission API");
|
||||||
|
}
|
||||||
var res = await req.Content.ReadAsStringAsync();
|
var res = await req.Content.ReadAsStringAsync();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,30 @@ namespace BMA.EHR.Application.Repositories
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<GetProfileByKeycloakIdDto?> GetProfileByKeycloakIdNewAsync(Guid keycloakId, string? accessToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var apiPath = $"{_configuration["API"]}/org/dotnet/by-keycloak/{keycloakId}";
|
||||||
|
var apiKey = _configuration["API_KEY"];
|
||||||
|
|
||||||
|
var apiResult = await GetExternalAPIAsync(apiPath, accessToken ?? "", apiKey);
|
||||||
|
if (apiResult != null)
|
||||||
|
{
|
||||||
|
var raw = JsonConvert.DeserializeObject<GetProfileByKeycloakIdResultDto>(apiResult);
|
||||||
|
if (raw != null)
|
||||||
|
return raw.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<GetProfileLeaveByKeycloakDto?> GetProfileLeaveByKeycloakIdAsync(Guid keycloakId, string? accessToken)
|
public async Task<GetProfileLeaveByKeycloakDto?> GetProfileLeaveByKeycloakIdAsync(Guid keycloakId, string? accessToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -144,12 +144,22 @@ namespace BMA.EHR.Domain.Middlewares
|
||||||
{
|
{
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
|
|
||||||
|
// อ่านข้อมูล response ก่อนที่ stream จะถูก dispose
|
||||||
|
string? responseBodyForLogging = null;
|
||||||
|
if (memoryStream.Length > 0)
|
||||||
|
{
|
||||||
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
using var reader = new StreamReader(memoryStream, leaveOpen: true);
|
||||||
|
responseBodyForLogging = await reader.ReadToEndAsync();
|
||||||
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
}
|
||||||
|
|
||||||
// ทำ logging แบบ fire-and-forget เพื่อไม่ block response
|
// ทำ logging แบบ fire-and-forget เพื่อไม่ block response
|
||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await LogRequestAsync(context, _elasticClient!, startTime, stopwatch, pf, keycloakId, requestBodyJson, memoryStream, caughtException);
|
await LogRequestAsync(context, _elasticClient!, startTime, stopwatch, pf, keycloakId, requestBodyJson, responseBodyForLogging, caughtException);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -393,7 +403,7 @@ namespace BMA.EHR.Domain.Middlewares
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LogRequestAsync(HttpContext context, ElasticClient client, DateTime startTime, Stopwatch stopwatch,
|
private async Task LogRequestAsync(HttpContext context, ElasticClient client, DateTime startTime, Stopwatch stopwatch,
|
||||||
GetProfileByKeycloakIdLocal? pf, string keycloakId, string? requestBodyJson, MemoryStream memoryStream, Exception? caughtException)
|
GetProfileByKeycloakIdLocal? pf, string keycloakId, string? requestBodyJson, string? responseBodyForLogging, Exception? caughtException)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -412,48 +422,42 @@ namespace BMA.EHR.Domain.Middlewares
|
||||||
string? message = null;
|
string? message = null;
|
||||||
string? responseBodyJson = null;
|
string? responseBodyJson = null;
|
||||||
|
|
||||||
// อ่านข้อมูลจาก Response (ลด serialization ที่ซ้ำ)
|
// ใช้ response body ที่ส่งมาจากการอ่านก่อนหน้า
|
||||||
if (memoryStream.Length > 0)
|
if (!string.IsNullOrEmpty(responseBodyForLogging))
|
||||||
{
|
{
|
||||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
var contentType = context.Response.ContentType ?? "";
|
||||||
var responseBody = new StreamReader(memoryStream).ReadToEnd();
|
var isFileResponse = !contentType.StartsWith("application/json") && !contentType.StartsWith("text/html") && (
|
||||||
|
contentType.StartsWith("application/") ||
|
||||||
|
contentType.StartsWith("image/") ||
|
||||||
|
contentType.StartsWith("audio/") ||
|
||||||
|
context.Response.Headers.ContainsKey("Content-Disposition")
|
||||||
|
);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(responseBody))
|
if (isFileResponse)
|
||||||
{
|
{
|
||||||
var contentType = context.Response.ContentType ?? "";
|
responseBodyJson = "";
|
||||||
var isFileResponse = !contentType.StartsWith("application/json") && !contentType.StartsWith("text/html") && (
|
message = "success";
|
||||||
contentType.StartsWith("application/") ||
|
}
|
||||||
contentType.StartsWith("image/") ||
|
else
|
||||||
contentType.StartsWith("audio/") ||
|
{
|
||||||
context.Response.Headers.ContainsKey("Content-Disposition")
|
// ใช้ response body ที่มีอยู่แล้วโดยไม่ serialize ซ้ำ
|
||||||
);
|
responseBodyJson = responseBodyForLogging;
|
||||||
|
|
||||||
if (isFileResponse)
|
try
|
||||||
{
|
{
|
||||||
responseBodyJson = "";
|
var json = JsonSerializer.Deserialize<JsonElement>(responseBodyForLogging);
|
||||||
message = "success";
|
if (json.ValueKind == JsonValueKind.Array)
|
||||||
|
{
|
||||||
|
message = "success";
|
||||||
|
}
|
||||||
|
else if (json.TryGetProperty("message", out var messageElement))
|
||||||
|
{
|
||||||
|
message = messageElement.GetString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch
|
||||||
{
|
{
|
||||||
// ใช้ response body ที่มีอยู่แล้วโดยไม่ serialize ซ้ำ
|
message = caughtException?.Message ?? "Unknown error";
|
||||||
responseBodyJson = responseBody;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var json = JsonSerializer.Deserialize<JsonElement>(responseBody);
|
|
||||||
if (json.ValueKind == JsonValueKind.Array)
|
|
||||||
{
|
|
||||||
message = "success";
|
|
||||||
}
|
|
||||||
else if (json.TryGetProperty("message", out var messageElement))
|
|
||||||
{
|
|
||||||
message = messageElement.GetString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
message = caughtException?.Message ?? "Unknown error";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -467,7 +471,7 @@ namespace BMA.EHR.Domain.Middlewares
|
||||||
{
|
{
|
||||||
logType = logType,
|
logType = logType,
|
||||||
ip = context.Connection.RemoteIpAddress?.ToString(),
|
ip = context.Connection.RemoteIpAddress?.ToString(),
|
||||||
rootId = pf?.RootId,
|
rootId = pf?.RootDnaId,
|
||||||
systemName = SystemName,
|
systemName = SystemName,
|
||||||
startTimeStamp = startTime.ToString("o"),
|
startTimeStamp = startTime.ToString("o"),
|
||||||
endTimeStamp = endTime.ToString("o"),
|
endTimeStamp = endTime.ToString("o"),
|
||||||
|
|
@ -660,7 +664,7 @@ namespace BMA.EHR.Domain.Middlewares
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var apiPath = $"{_configuration["API"]}/org/dotnet/keycloak/{keycloakId}";
|
var apiPath = $"{_configuration["API"]}/org/dotnet/by-keycloak/{keycloakId}";
|
||||||
var apiKey = _configuration["API_KEY"];
|
var apiKey = _configuration["API_KEY"];
|
||||||
|
|
||||||
var apiResult = await GetExternalAPIAsync(apiPath, accessToken ?? "", apiKey);
|
var apiResult = await GetExternalAPIAsync(apiPath, accessToken ?? "", apiKey);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue