Get Requestbody and Responsebody At Handlerinterceptor

Get RequestBody and ResponseBody at HandlerInterceptor

As far as I know, RequestBody and ResponseBody can be read only once. So you should not read them in an Interceptor.
Here's some explanation.

How can I get a body data from the request in an ExceptionHandler in Spring Boot?

The comments regarding using the ContentCachingRequestWrapper are accurate, this is the implementation using your controller advice that should work.

@Component
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
ContentCachingRequestWrapper contentCachingRequestWrapper = new ContentCachingRequestWrapper(
(HttpServletRequest) servletRequest);

filterChain.doFilter(contentCachingRequestWrapper, servletResponse);
}
}

The advice

@RestControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {

ContentCachingRequestWrapper nativeRequest = (ContentCachingRequestWrapper) ((ServletWebRequest) request).getNativeRequest();
String requestEntityAsString = new String(nativeRequest.getContentAsByteArray());

log.debug(requestEntityAsString);

return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
}

How to modify request body before reaching controller in spring boot

Short Answer

Yes, but not easily.

Details

I know of three options to change the body of a request
"before" it arrives at the handler method in the controller;

  1. Use AOP to change the request before the method is called.
  2. Create an HTTP filter.
  3. Create a custom Spring HandlerInterceptor.

Since you are already using spring-boot,
option 3, custom Spring HandlerInterceptor,
seems like the best option for you.

Here is a link to a Baeldung Article covering spring HandlerInterceptors.

The Baeldung article is not the full answer for your problem
because you can only read the InputStrem returned by HttpServletRequest one time.

You will need to create a wrapper class that extends HttpServletRequest
and wrap every request in your wrapper class within your custom HandlerInterceptor or in a custom Filter (Filter might be the way to go here).

Wrapper Class

  1. Read the HttpServletRequest InputStream in the wrapper class constructor
  2. Modify the body per your requirements.
  3. Write the modified body to a ByteArrayOutputStream.
  4. Use toByteArray to retrieve the actual byte[] from the stream.
  5. Close the ByteArrayOutputStream (try-with-resources is good for this).
  6. Override the getInputStream method.
  7. Wrap the byte[] in a ByteArrayInputStream every time the getInputStream is called. Return this stream.

How To Wrap the Request

  1. In your Filter, instantiate your wrapper class and pass in the original request (which is a parameter to the doFilter method).
  2. Pass the wrapper to the chain.doFilter method (not the original request).


Related Topics



Leave a reply



Submit