diff --git a/src/main/java/cc/fascinated/log/TransactionLogger.java b/src/main/java/cc/fascinated/log/TransactionLogger.java new file mode 100644 index 0000000..b0cabcc --- /dev/null +++ b/src/main/java/cc/fascinated/log/TransactionLogger.java @@ -0,0 +1,78 @@ +package cc.fascinated.log; + +import cc.fascinated.util.IPUtils; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.http.server.ServletServerHttpRequest; +import org.springframework.http.server.ServletServerHttpResponse; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +@ControllerAdvice +@Slf4j(topic = "Req/Res Transaction") +public class TransactionLogger implements ResponseBodyAdvice { + @Override + public Object beforeBodyWrite(Object body, @NonNull MethodParameter returnType, @NonNull MediaType selectedContentType, + @NonNull Class> selectedConverterType, @NonNull ServerHttpRequest rawRequest, + @NonNull ServerHttpResponse rawResponse) { + HttpServletRequest request = ((ServletServerHttpRequest) rawRequest).getServletRequest(); + HttpServletResponse response = ((ServletServerHttpResponse) rawResponse).getServletResponse(); + + // Get the request ip ip + String ip = IPUtils.getRealIp(request); + + // Getting params + Map params = new HashMap<>(); + for (Entry entry : request.getParameterMap().entrySet()) { + params.put(entry.getKey(), Arrays.toString(entry.getValue())); + } + + // Getting headers + Map headers = new HashMap<>(); + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + headers.put(headerName, request.getHeader(headerName)); + } + + // Log the request + log.info(String.format("[Req] %s | %s | '%s', params=%s, headers=%s", + request.getMethod(), + ip, + request.getRequestURI(), + params, + headers + )); + + // Getting response headers + headers = new HashMap<>(); + for (String headerName : response.getHeaderNames()) { + headers.put(headerName, response.getHeader(headerName)); + } + + // Log the response + log.info(String.format("[Res] %s, headers=%s", + response.getStatus(), + headers + )); + return body; + } + + @Override + public boolean supports(@NonNull MethodParameter returnType, @NonNull Class> converterType) { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/cc/fascinated/util/IPUtils.java b/src/main/java/cc/fascinated/util/IPUtils.java new file mode 100644 index 0000000..73554d8 --- /dev/null +++ b/src/main/java/cc/fascinated/util/IPUtils.java @@ -0,0 +1,42 @@ +package cc.fascinated.util; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class IPUtils { + /** + * The headers that contain the IP. + */ + private static final String[] IP_HEADERS = new String[] { + "CF-Connecting-IP", + "X-Forwarded-For" + }; + + /** + * Get the real IP from the given request. + * + * @param request the request + * @return the real IP + */ + public static String getRealIp(HttpServletRequest request) { + String ip = request.getRemoteAddr(); + for (String headerName : IP_HEADERS) { + String header = request.getHeader(headerName); + if (header == null) { + continue; + } + if (!header.contains(",")) { // Handle single IP + ip = header; + break; + } + // Handle multiple IPs + String[] ips = header.split(","); + for (String ipHeader : ips) { + ip = ipHeader; + break; + } + } + return ip; + } +} \ No newline at end of file diff --git a/target/classes/images/default_head.png b/target/classes/images/default_head.png deleted file mode 100644 index 32b3889..0000000 Binary files a/target/classes/images/default_head.png and /dev/null differ