Почему мой пользовательский ClientHttpRequestInterceptor с пустым ответом - PullRequest
0 голосов
/ 25 апреля 2018

Я сделал следующее для моего пользовательского перехватчика регистрации

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()));
    }
}

И я устанавливаю перехватчик на restTemplate

   @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 Ответ

0 голосов
/ 27 апреля 2018

Поскольку входной поток может быть использован только один раз, и для sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.

* 1005 не доступна функция 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;
}

}

...