HttpRequestLogInterceptor.java 4.51 KB
package com.infoloop.tianting.intercepter;

import com.infoloop.tianting.utils.JsonUtil;
import lombok.Builder;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.util.StreamUtils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

@Component
@Slf4j
@SuppressWarnings("all")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class HttpRequestLogInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
        final var stopWatch = new StopWatch();
        stopWatch.start();
        final var response = clientHttpRequestExecution.execute(httpRequest, body);
        final var responseCopy = new BufferingClientHttpResponseWrapper(response);
        stopWatch.stop();
        final var resBody = new StringBuilder();
        try (final var bufferedReader = new BufferedReader(new InputStreamReader(responseCopy.getBody(), StandardCharsets.UTF_8))) {
            var line = bufferedReader.readLine();
            while (line != null) {
                resBody.append(line);
                line = bufferedReader.readLine();
            }
        }

        var reqBody = "";
        //这里可以自定义想打印什么方法或者请求的内容
        if (httpRequest.getHeaders().getContentType() != null) {
            String contentType = httpRequest.getHeaders().getContentType().toString();
            if (contentType.contains(MediaType.MULTIPART_FORM_DATA_VALUE)) {

            } else {
                if (body.length > 0) {
                    reqBody = new String(body, StandardCharsets.UTF_8);
                }
            }
        }

        log.info(JsonUtil.writeAsJson(RestLog.builder()
                .httpHeaders(httpRequest.getHeaders())
                .httpMethod(httpRequest.getMethodValue())
                .requestUrl(httpRequest.getURI().toString())
                .requestBody(reqBody)
                .responseBody(resBody.toString())
                .responseStatus(responseCopy.getRawStatusCode())
                .apiCostTime(stopWatch.getLastTaskTimeMillis())
                .build()));
        return responseCopy;
    }

    /**
     * 响应内容备份
     */
    static final class BufferingClientHttpResponseWrapper implements ClientHttpResponse {

        private final ClientHttpResponse response;

        private byte[] body;


        BufferingClientHttpResponseWrapper(ClientHttpResponse response) {
            this.response = response;
        }


        @Override
        public HttpStatus getStatusCode() throws IOException {
            return this.response.getStatusCode();
        }

        @Override
        public int getRawStatusCode() throws IOException {
            return this.response.getRawStatusCode();
        }

        @Override
        public String getStatusText() throws IOException {
            return this.response.getStatusText();
        }

        @Override
        public HttpHeaders getHeaders() {
            return this.response.getHeaders();
        }

        @Override
        public InputStream getBody() throws IOException {
            if (this.body == null) {
                this.body = StreamUtils.copyToByteArray(this.response.getBody());
            }
            return new ByteArrayInputStream(this.body);
        }

        @Override
        public void close() {
            this.response.close();
        }
    }

    /**
     * 定义日志的字段
     */
    @Data
    @Builder
    private static class RestLog {
        private String requestUrl;
        private String httpMethod;
        private HttpHeaders httpHeaders;
        private String requestBody;
        private String responseBody;
        private int responseStatus;
        private long apiCostTime;
    }

}