package com.kexue.skills.interceptor;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 请求响应体缓存过滤器
 * 用于包装 HttpServletRequest 和 HttpServletResponse，使其可以重复读取请求体和捕获响应体
 * 
 * @author 王志维
 * @since 2026-04-14
 */
@Component
@Order(1)  // 确保在最前面执行
public class CachedBodyFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            
            // 跳过对 multipart/form-data 格式请求的包装，因为文件上传请求不能被重复读取
            String contentType = httpRequest.getContentType();
            if (contentType != null && contentType.startsWith("multipart/")) {
                chain.doFilter(request, response);
                return;
            }
            
            // 包装请求，使其可以重复读取请求体
            CachedBodyHttpServletRequest cachedRequest = new CachedBodyHttpServletRequest(httpRequest);
            
            // 包装响应，使其可以捕获响应体
            CachedBodyHttpServletResponse cachedResponse = new CachedBodyHttpServletResponse(httpResponse);
            
            // 继续过滤链
            chain.doFilter(cachedRequest, cachedResponse);
            
            // 将缓存的响应体写入真实响应
            cachedResponse.flushBuffer();
        } else {
            chain.doFilter(request, response);
        }
    }
}
