[Developer] #424 show ORDS request response details

Refs #424
This commit is contained in:
devmrko
2026-06-23 11:54:57 +09:00
parent ad7764ecd3
commit 7d3bc02123
4 changed files with 174 additions and 7 deletions

View File

@@ -10,10 +10,38 @@ public record ProbeResult(
int rowCount,
List<String> maskedColumns,
String errorCode,
String errorMessage
String errorMessage,
String requestHeaders,
String requestPayload,
String responseHeaders,
String responseBody
) {
public static ProbeResult blocked(ProbeStatus status, String errorCode, String errorMessage) {
return new ProbeResult(status, List.of(), List.of(), 0, List.of(), errorCode, errorMessage);
return blocked(status, errorCode, errorMessage, null, null, null, null);
}
public static ProbeResult blocked(
ProbeStatus status,
String errorCode,
String errorMessage,
String requestHeaders,
String requestPayload,
String responseHeaders,
String responseBody
) {
return new ProbeResult(
status,
List.of(),
List.of(),
0,
List.of(),
errorCode,
errorMessage,
requestHeaders,
requestPayload,
responseHeaders,
responseBody
);
}
}

View File

@@ -97,21 +97,47 @@ public class OrdsProbeService {
ProbeStatus.OBJECT_DISABLED, "OBJECT_DISABLED", e.getMessage()));
}
String requestHeaders = null;
String requestPayload = null;
try {
URI uri = buildUri(object.ordsPath(), command.limit());
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(command.bearerToken());
requestHeaders = prettyHeaders(maskedRequestHeaders(headers));
requestPayload = prettyJson("{}");
ResponseEntity<String> response = ordsRestTemplate.exchange(
uri, HttpMethod.POST, new HttpEntity<>(headers), String.class);
ProbeResult result = parseSuccess(response.getBody(), object.objectId());
ProbeResult result = parseSuccess(
response.getBody(),
object.objectId(),
requestHeaders,
requestPayload,
prettyHeaders(response.getHeaders()),
prettyJson(response.getBody())
);
return auditAndReturn(command, result);
} catch (HttpStatusCodeException e) {
ProbeStatus status = errorClassifier.classify(e.getStatusCode(), e.getResponseBodyAsString());
return auditAndReturn(command, ProbeResult.blocked(
status, status.name(), trimMessage(e.getResponseBodyAsString())));
status,
status.name(),
trimMessage(e.getResponseBodyAsString()),
requestHeaders,
requestPayload,
prettyHeaders(e.getResponseHeaders()),
prettyJson(e.getResponseBodyAsString())
));
} catch (ResourceAccessException e) {
ProbeStatus status = classifyResourceAccess(e);
return auditAndReturn(command, ProbeResult.blocked(status, status.name(), resourceAccessMessage(status, e)));
return auditAndReturn(command, ProbeResult.blocked(
status,
status.name(),
resourceAccessMessage(status, e),
requestHeaders,
requestPayload,
"{}",
""
));
} catch (Exception e) {
return auditAndReturn(command, ProbeResult.blocked(
ProbeStatus.INVALID_ORDS_RESPONSE, "INVALID_ORDS_RESPONSE", e.getMessage()));
@@ -129,7 +155,14 @@ public class OrdsProbeService {
.toUri();
}
private ProbeResult parseSuccess(String body, long objectId) throws Exception {
private ProbeResult parseSuccess(
String body,
long objectId,
String requestHeaders,
String requestPayload,
String responseHeaders,
String responseBody
) throws Exception {
JsonNode root = objectMapper.readTree(body);
JsonNode rowsNode = root.has("rows") ? root.get("rows") : root;
rowsNode = root.has("items") ? root.get("items") : rowsNode;
@@ -153,7 +186,11 @@ public class OrdsProbeService {
rows.size(),
findMaskedColumns(objectId, rows),
null,
null
null,
requestHeaders,
requestPayload,
responseHeaders,
responseBody
);
}
@@ -230,4 +267,53 @@ public class OrdsProbeService {
}
return body.length() <= 500 ? body : body.substring(0, 500);
}
private HttpHeaders maskedRequestHeaders(HttpHeaders headers) {
HttpHeaders masked = new HttpHeaders();
masked.putAll(headers);
List<String> authorization = headers.get(HttpHeaders.AUTHORIZATION);
if (authorization != null && !authorization.isEmpty()) {
masked.set(HttpHeaders.AUTHORIZATION, maskBearer(authorization.get(0)));
}
return masked;
}
private String maskBearer(String value) {
if (value == null || value.isBlank()) {
return "";
}
if (!value.toLowerCase(Locale.ROOT).startsWith("bearer ")) {
return "****";
}
String token = value.substring("Bearer ".length());
String suffix = token.length() <= 6 ? "" : token.substring(token.length() - 6);
return "Bearer ****" + suffix;
}
private String prettyHeaders(HttpHeaders headers) {
if (headers == null || headers.isEmpty()) {
return "{}";
}
return prettyObject(headers);
}
private String prettyJson(String body) {
if (body == null || body.isBlank()) {
return "";
}
try {
return objectMapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(objectMapper.readTree(body));
} catch (Exception ignored) {
return body;
}
}
private String prettyObject(Object value) {
try {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);
} catch (Exception ignored) {
return String.valueOf(value);
}
}
}