복붙노트

[SPRING] 빈 응답이있는 내 사용자 정의 ClientHttpRequestInterceptor

SPRING

빈 응답이있는 내 사용자 정의 ClientHttpRequestInterceptor

내 커스텀 로깅 인터셉터를 위해 다음을 수행했다.

public class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {
    private final static Logger log = LoggerFactory.getLogger(HttpLoggingInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        logRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        logResponse(response);
        return response;
    }

    private void logRequest(HttpRequest request, byte[] body) throws IOException {
        log.info("Request URI : {}, Method : {}, Headers : {}, Request body : {}", request.getURI(), request.getMethod(), request.getHeaders(), new String(body, "UTF-8"));

    }

    private void logResponse(ClientHttpResponse response) throws IOException {
        log.info("Response Status code : {}, Status text : {}, Headers : {}, Response body: {}", response.getStatusCode(), response.getStatusText(), response.getHeaders(), StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
    }
}

그리고 나는 나머지 요격기에 요격기를 설치하고있다.

   @Autowired
    public RestTemplate restTemplate;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        List<ClientHttpRequestInterceptor> clientHttpRequestInterceptors = new ArrayList<>();
        clientHttpRequestInterceptors.add(new HttpLoggingInterceptor());
//        clientHttpRequestInterceptors.addAll(restTemplate.getInterceptors());
        restTemplate.setInterceptors(clientHttpRequestInterceptors);
//        restTemplate.setInterceptors(Collections.singletonList(new HttpLoggingInterceptor()));
}

로거가 응답을 콘솔에 올바르게 인쇄하고 있지만 결국 응답은 호출자에게 비어있는 것으로 반환됩니다. 나는 그것을 디버그하고 파악할 수 없다.

StreamUtils.copyToString (response.getBody (), Charset.defaultCharset ())이 입력 스트림을 한 번 읽었으며 더 이상 응답 본문 (이제 비어 있음)이 없다는 것을 알아 냈습니다.

다른 사람도 같은 문제에 직면 해 있으며 원래 InputStream에서 읽지 않고 InputStream을 복제 할 생각이 있습니까?

해결법

  1. ==============================

    1.입력 스트림은 한 번만 소비 될 수 있고 sun.net.www.protocol.http.HttpURLConnection $ HttpInputStream에 사용할 수있는 reset () 또는 mark (***) 함수가 없기 때문에

    입력 스트림은 한 번만 소비 될 수 있고 sun.net.www.protocol.http.HttpURLConnection $ HttpInputStream에 사용할 수있는 reset () 또는 mark (***) 함수가 없기 때문에

    다음과 같은 방법으로 restTemplate을 작성하여 응답을 여러 번 읽을 수있는 방법은 한 가지뿐입니다.

    @Bean
    public RestTemplate getfxoWsClientRestTemplate(){
        RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
        restTemplate.setInterceptors(Collections.singletonList(new HttpLoggingInterceptor()));
        return  restTemplate;
    }
    

    LoggingIntercepter는 다음과 같이 작성할 수 있습니다.

    public class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {
    
        private final static Logger logger = LoggerFactory.getLogger(HttpLoggingInterceptor.class);
    
        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        logger.info("request method: {}, request URI: {}, request headers: {}, request body: {}",
                request.getMethod(), request.getURI(), request.getHeaders(), new String(body, Charset.forName("UTF-8")));
    
        ClientHttpResponse response = execution.execute(request, body);
    
        logger.info("response status code: {}, response headers: {}, response body: {}",
                response.getStatusCode(), response.getHeaders(), new String(ByteStreams.toByteArray(response.getBody()), Charset.forName("UTF-8")));
    
        return response;
    }
    

    }

  2. from https://stackoverflow.com/questions/50023708/why-my-custom-clienthttprequestinterceptor-with-empty-response by cc-by-sa and MIT license