package io.company.localhost.common.wrapper; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import java.util.Objects; import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; import com.fasterxml.jackson.core.type.TypeReference; import io.company.localhost.utils.JacksonUtil; import io.netty.handler.codec.ValueConverter; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; import lombok.extern.slf4j.Slf4j; // body 읽어서 cash로 만듬 // 필요하면 filter로 사용 @Slf4j public class CachedBodyRequestWrapper extends HttpServletRequestWrapper { private final Charset encoding; private final byte[] cachedBody; private ValueConverter targetConvert; public CachedBodyRequestWrapper(HttpServletRequest request) throws IOException { super(request); String characterEncoding = request.getCharacterEncoding(); if (StringUtils.hasText(characterEncoding) == false) { characterEncoding = StandardCharsets.UTF_8.name(); } // XSS 방지를 이곳에서 하지 않을 경우 아래주석 해제 후 아래 //XSS 방지 이후 코드 삭제 // InputStream requestInputStream = request.getInputStream(); // this.cachedBody = StreamUtils.copyToByteArray(requestInputStream); this.encoding = Charset.forName(characterEncoding); // XSS 방지 String requestBody = null; try { requestBody = StreamUtils.copyToString(request.getInputStream(), Charset.defaultCharset()); } catch (IOException e) { log.error("StreamUtil.toString Exception", e); } if (requestBody == null) { InputStream requestInputStream = request.getInputStream(); this.cachedBody = StreamUtils.copyToByteArray(requestInputStream); return; } Object bodyObject = null; if (requestBody.startsWith("[")) { // List bodyObject = JacksonUtil.fromJson(requestBody, new TypeReference>>() { }); } else { // Map bodyObject = JacksonUtil.fromJson(requestBody, new TypeReference>() { }); } String newRequestBody = JacksonUtil.toJson(bodyObject); if (Objects.isNull(newRequestBody)) { newRequestBody = new String(""); } this.cachedBody = newRequestBody.getBytes(StandardCharsets.UTF_8); } /** json body 관련 메소드 START */ @Override public ServletInputStream getInputStream() throws IOException { return new CachedBodyServletInputStream(this.cachedBody); } @Override public BufferedReader getReader() throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody); return new BufferedReader(new InputStreamReader(byteArrayInputStream, encoding)); } /** json body 관련 메소드 END */ private class CachedBodyServletInputStream extends ServletInputStream { private InputStream cachedBodyInputStream; public CachedBodyServletInputStream(byte[] cachedBody) { this.cachedBodyInputStream = new ByteArrayInputStream(cachedBody); } @Override public boolean isFinished() { try { return this.cachedBodyInputStream.available() == 0; } catch (IOException e) { log.error("", e); return false; } } @Override public boolean isReady() { return true; } @Override public void setReadListener(ReadListener listener) { throw new UnsupportedOperationException(); } @Override public int read() throws IOException { return this.cachedBodyInputStream.read(); } } }