I have a @RestControllerAdvice where I handle an Exception in Spring Boot. I would like to log an information that is sent through request body. How can I get this information from a spring WebRequest?
This is my sample exception handler.
@RestControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {
// I want to add something here that I could log an info that is in the request body.
return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
}
CodePudding user response:
Refer the code below — using the method logPostOrPutRequestBody we are able to read the InputStream from HttpServletRequest and log it to standard output.
@Component
public class LogRequestFilter implements Filter {
private final Logger logger = LoggerFactory.getLogger(LogRequestFilter.class);
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
logPostOrPutRequestBody((HttpServletRequest) servletRequest);
filterChain.doFilter(servletRequest, servletResponse);
}
private void logPostOrPutRequestBody(HttpServletRequest httpRequest) throws IOException {
if(Arrays.asList("POST", "PUT").contains(httpRequest.getMethod())) {
String characterEncoding = httpRequest.getCharacterEncoding();
Charset charset = Charset.forName(characterEncoding);
String bodyInStringFormat = readInputStreamInStringFormat(httpRequest.getInputStream(), charset);
logger.info("Request body: {}", bodyInStringFormat);
}
}
private String readInputStreamInStringFormat(InputStream stream, Charset charset) throws IOException {
final int MAX_BODY_SIZE = 1024;
final StringBuilder bodyStringBuilder = new StringBuilder();
if (!stream.markSupported()) {
stream = new BufferedInputStream(stream);
}
stream.mark(MAX_BODY_SIZE 1);
final byte[] entity = new byte[MAX_BODY_SIZE 1];
final int bytesRead = stream.read(entity);
if (bytesRead != -1) {
bodyStringBuilder.append(new String(entity, 0, Math.min(bytesRead, MAX_BODY_SIZE), charset));
if (bytesRead > MAX_BODY_SIZE) {
bodyStringBuilder.append("...");
}
}
stream.reset();
return bodyStringBuilder.toString();
}
}
CodePudding user response:
RequestBody and ResponseBody can be read-only once so other ways to achieve the body in the exception handler Visit here