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

This commit is contained in:
Suphonchai Phoonsawat 2026-01-22 11:58:26 +07:00
parent d3501e831c
commit d945deae4f
3 changed files with 72 additions and 40 deletions

View file

@ -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;
} }

View file

@ -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

View file

@ -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);