public interface RequestBodyAdvice {
boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType);
HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException;
Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
@Nullable
Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
}
HTTP 요청의 본문은 스트림 형식으로 전달되며, 한 번 읽으면 스트림은 소모된다는 것을 기억하자.
따라서, 요청 본문을 RequestBodyAdvice에서 읽고 수정하려면 스트림을 다시 생성하거나 복사하여 사용할 수 있도록 해야한다.
public abstract class RequestBodyAdviceAdapter implements RequestBodyAdvice {
/**
* The default implementation returns the InputMessage that was passed in.
*/
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
return inputMessage;
}
/**
* The default implementation returns the body that was passed in.
*/
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
/**
* The default implementation returns the body that was passed in.
*/
@Override
@Nullable
public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
}
RequestBodyAdviceAdapter를 상속받아 필요한 부분만 Override 한다.
@Slf4j
@RestControllerAdvice
public class CustomRequestBodyAdvice extends RequestBodyAdviceAdapter{
private final HttpServletRequest httpServletRequest;
// HttpServletRequest는 생성자 주입 또는 스프링 빈 주입으로 사용 가능
public CustomRequestBodyAdvice(HttpServletRequest httpServletRequest) {
this.httpServletRequest = httpServletRequest;
}
@Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
String clientIp = getClientIp(httpServletRequest);
String remoteIp = httpServletRequest.getRemoteAddr();
String requestUri = httpServletRequest.getRequestURI();
log.info("[Remote IP] : {}, [Client IP] : {}, [Request URI] : {}", remoteIp, clientIp, requestUri);
log.info("RequestBody Input Data : {}", body);
return body;
}
private String getClientIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
//IPv6 : 0:0:0:0:0:0:0:1
//IPv4 : 127.0.0.1
if (ip.contains("0.0") || ip.contains("0:0")) {
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
return ip;
}
}
ResponseBodyAdvice에 대한 내용은 아래 글을 참고하기 바란다.
ResponseBodyAdvice 인터페이스 파해치기 (37) | 2024.12.27 |
---|---|
Jackson - ObjectMapper 사용법 (readValue, writeValue, JsonNode, ObjectNode) (42) | 2024.12.26 |
Jackson - ObjectMapper Custom 설정 (0) | 2024.12.24 |
ImmutableList에 대한 고찰 (1) | 2024.10.13 |
SpringBoot CSV Read / Write (opencsv) (8) | 2024.09.12 |
댓글 영역