🐛 Feign日志multipart请求解析非文件字段打印,文件部分用占位符替代
This commit is contained in:
@@ -33,8 +33,12 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 自定义Feign日志记录器,只记录出入参信息
|
||||
@@ -62,10 +66,13 @@ public class CustomFeignLogger extends Logger {
|
||||
Map<String, Collection<String>> headers = request.headers();
|
||||
byte[] body = request.body();
|
||||
|
||||
String contentType = getContentType(headers);
|
||||
String bodyStr;
|
||||
if (body == null || body.length == 0) {
|
||||
bodyStr = "[无]";
|
||||
} else if (isBinaryContent(getContentType(headers))) {
|
||||
} else if (isMultipartContent(contentType)) {
|
||||
bodyStr = parseMultipartBody(body, contentType);
|
||||
} else if (isBinaryContent(contentType)) {
|
||||
bodyStr = "[二进制数据,长度=" + body.length + "字节]";
|
||||
} else {
|
||||
bodyStr = new String(body, StandardCharsets.UTF_8);
|
||||
@@ -122,7 +129,7 @@ public class CustomFeignLogger extends Logger {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为二进制内容或不应打印的内容(如文件上传)
|
||||
* 判断是否为二进制内容
|
||||
*/
|
||||
private boolean isBinaryContent(String contentType) {
|
||||
if (contentType == null || contentType.isEmpty()) {
|
||||
@@ -132,7 +139,77 @@ public class CustomFeignLogger extends Logger {
|
||||
return lowerContentType.startsWith(BINARY_CONTENT_TYPE_PREFIX)
|
||||
|| lowerContentType.startsWith(IMAGE_CONTENT_TYPE_PREFIX)
|
||||
|| lowerContentType.startsWith(AUDIO_CONTENT_TYPE_PREFIX)
|
||||
|| lowerContentType.startsWith(VIDEO_CONTENT_TYPE_PREFIX)
|
||||
|| lowerContentType.startsWith(MULTIPART_CONTENT_TYPE_PREFIX);
|
||||
|| lowerContentType.startsWith(VIDEO_CONTENT_TYPE_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为multipart内容
|
||||
*/
|
||||
private boolean isMultipartContent(String contentType) {
|
||||
return contentType != null && contentType.toLowerCase().startsWith(MULTIPART_CONTENT_TYPE_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析multipart请求体,文件部分用占位符替代,文本字段保留打印
|
||||
*/
|
||||
private String parseMultipartBody(byte[] body, String contentType) {
|
||||
String boundary = extractBoundary(contentType);
|
||||
if (boundary == null) {
|
||||
return "[multipart数据,长度=" + body.length + "字节]";
|
||||
}
|
||||
String bodyStr = new String(body, StandardCharsets.UTF_8);
|
||||
String delimiter = "--" + boundary;
|
||||
String[] parts = bodyStr.split(delimiter);
|
||||
|
||||
List<String> fields = new ArrayList<>();
|
||||
for (String part : parts) {
|
||||
if (part.isEmpty() || part.startsWith("--") || part.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
int headerEnd = part.indexOf("\r\n\r\n");
|
||||
if (headerEnd < 0) {
|
||||
continue;
|
||||
}
|
||||
String headers = part.substring(0, headerEnd);
|
||||
String value = part.substring(headerEnd + 4);
|
||||
if (value.endsWith("\r\n")) {
|
||||
value = value.substring(0, value.length() - 2);
|
||||
}
|
||||
|
||||
String name = extractParam(headers, "name");
|
||||
|
||||
if (headers.contains("filename=")) {
|
||||
String filename = extractParam(headers, "filename");
|
||||
fields.add(name + "=[文件: " + filename + "]");
|
||||
} else {
|
||||
fields.add(name + "=" + value);
|
||||
}
|
||||
}
|
||||
return fields.isEmpty() ? "[multipart数据]" : "{" + String.join(", ", fields) + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Content-Type中提取boundary
|
||||
*/
|
||||
private String extractBoundary(String contentType) {
|
||||
for (String param : contentType.split(";")) {
|
||||
param = param.trim();
|
||||
if (param.toLowerCase().startsWith("boundary=")) {
|
||||
return param.substring("boundary=".length()).trim();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从headers中提取参数值(如name、filename)
|
||||
*/
|
||||
private String extractParam(String headers, String paramName) {
|
||||
Pattern pattern = Pattern.compile(paramName + "=\"([^\"]*)\"");
|
||||
Matcher matcher = pattern.matcher(headers);
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
return paramName;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user