使用@RepositoryRestResource 时记录 Request/Response
Log Request/Response when Using @RepositoryRestResource
我正在使用 @RepositoryRestResource from spring-data-rest-api
. Since the JAX-RS controller is automatically generated,我无法手动添加记录器来记录传入的请求。是否存在将自动记录请求的注释?
我的代码:
@RepositoryRestResource(collectionResourceRel = "organizations", path = "organizations")
public interface OrganizationRepository extends JpaRepository<Organization, UUID> {
}
由于我的应用程序是用 Quarkus 编写的,而且我无法访问来自 spring-web
的拦截器,我创建了一个自定义注释并使用了过滤器。
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Logged { }
@Logged
@Provider
public class RequestLoggingFilter implements ContainerRequestFilter {
/**
* @param requestContext used to extract information from the HTTP request such as the URI, headers and HTTP entity.
*/
@Override
public void filter(ContainerRequestContext requestContext) {
String message = getEntityBody(requestContext);
requestContext.setProperty("StartTime", System.currentTimeMillis());
String url = requestContext.getUriInfo().getAbsolutePath().toString();
StructuredDataUtils.logRequestAsJson(url, message);
}
/**
* @param requestContext HTTP request containing the request body.
* @return the request body of an HTTP request.
*/
private String getEntityBody(ContainerRequestContext requestContext) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = requestContext.getEntityStream();
String result = null;
try {
ReaderWriter.writeTo(in, out);
byte[] requestEntity = out.toByteArray();
if (requestEntity.length == 0) {
result = "";
} else {
result = new String(requestEntity, "UTF-8");
}
requestContext.setEntityStream(new ByteArrayInputStream(requestEntity));
} catch (IOException e) {
result = e.getMessage();
}
if (result.contains("password")) {
result = maskPassword(result);
}
return result;
}
/**
* @param jsonString JSON string containing password field.
* @return JSON string with password field hidden.
*/
private String maskPassword(String jsonString) {
return jsonString.replaceAll("(\n?\s*\"password\"\s?:\s?\")[^\n\"]*(\",?\n?)", "********");
}
}
@Logged
@Provider
public class ResponseLoggingFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
String responseMessage = convertObjectToJson(responseContext.getEntity());
String responseStatus = responseContext.getStatusInfo().toString();
String responseTime = String.valueOf(System.currentTimeMillis() - (Long) requestContext.getProperty("StartTime"));
String calledServiceName = "d2d-server"; // TODO: pass service name in @Logged() and set default
StructuredDataUtils.setStructuredDataFields(responseMessage, calledServiceName, responseStatus, responseTime);
}
}
然后我简单地用 @Logged
标记一个方法来记录 HTTP req/resp。
我正在使用 @RepositoryRestResource from spring-data-rest-api
. Since the JAX-RS controller is automatically generated,我无法手动添加记录器来记录传入的请求。是否存在将自动记录请求的注释?
我的代码:
@RepositoryRestResource(collectionResourceRel = "organizations", path = "organizations")
public interface OrganizationRepository extends JpaRepository<Organization, UUID> {
}
由于我的应用程序是用 Quarkus 编写的,而且我无法访问来自 spring-web
的拦截器,我创建了一个自定义注释并使用了过滤器。
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Logged { }
@Logged
@Provider
public class RequestLoggingFilter implements ContainerRequestFilter {
/**
* @param requestContext used to extract information from the HTTP request such as the URI, headers and HTTP entity.
*/
@Override
public void filter(ContainerRequestContext requestContext) {
String message = getEntityBody(requestContext);
requestContext.setProperty("StartTime", System.currentTimeMillis());
String url = requestContext.getUriInfo().getAbsolutePath().toString();
StructuredDataUtils.logRequestAsJson(url, message);
}
/**
* @param requestContext HTTP request containing the request body.
* @return the request body of an HTTP request.
*/
private String getEntityBody(ContainerRequestContext requestContext) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = requestContext.getEntityStream();
String result = null;
try {
ReaderWriter.writeTo(in, out);
byte[] requestEntity = out.toByteArray();
if (requestEntity.length == 0) {
result = "";
} else {
result = new String(requestEntity, "UTF-8");
}
requestContext.setEntityStream(new ByteArrayInputStream(requestEntity));
} catch (IOException e) {
result = e.getMessage();
}
if (result.contains("password")) {
result = maskPassword(result);
}
return result;
}
/**
* @param jsonString JSON string containing password field.
* @return JSON string with password field hidden.
*/
private String maskPassword(String jsonString) {
return jsonString.replaceAll("(\n?\s*\"password\"\s?:\s?\")[^\n\"]*(\",?\n?)", "********");
}
}
@Logged
@Provider
public class ResponseLoggingFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
String responseMessage = convertObjectToJson(responseContext.getEntity());
String responseStatus = responseContext.getStatusInfo().toString();
String responseTime = String.valueOf(System.currentTimeMillis() - (Long) requestContext.getProperty("StartTime"));
String calledServiceName = "d2d-server"; // TODO: pass service name in @Logged() and set default
StructuredDataUtils.setStructuredDataFields(responseMessage, calledServiceName, responseStatus, responseTime);
}
}
然后我简单地用 @Logged
标记一个方法来记录 HTTP req/resp。