简体   繁体   English

如何在不使用HttpEntity的情况下阅读它?

[英]How do I read HttpEntity without consuming it?

I've got org.apache.http.HttpResponse object, which I'm using at different places in the code. 我有org.apache.http.HttpResponse对象,该对象在代码的不同位置使用。 One of those places is for logging. 这些地方之一是日志记录。

The problem is that when I run following log code: 问题是当我运行以下日志代码时:

HttpEntity entity = response.getEntity();
try {
    String content = Base64.encodeToString(
            EntityUtils.toByteArray(entity), Base64.DEFAULT);
    sb.append(content + "\r\n");
} catch (Exception e) {
    sb.append("\r\n\r\n====EXCEPTION=====\r\n" + e.toString()
            + "\r\n");
}

and than I try to read entry content in the actual processing code, that causes the code to throw following exception: 然后,我尝试读取实际处理代码中的条目内容,这导致代码引发以下异常:

java.lang.IllegalStateException: Content has been consumed

My question is: how do I read the entity without consuming it in the log code? 我的问题是:如何读取实体而不在日志代码中使用它?

UPDATE here's the full code of the function I use to transform httpresponse to string: UPDATE这是我用来将httpresponse转换为字符串的函数的完整代码:

static String toString(org.apache.http.HttpResponse response) {
    try {
        if (response == null) {
            return "null";
        }

        StringBuilder sb = new StringBuilder();
        sb.append("==============BEGIN HttpResponse================\r\n");
        StatusLine sl = response.getStatusLine();
        if (sl == null) {
            sb.append("status line is null\r\n");
        } else {
            sb.append(String.format("%s %s\r\n", sl.getStatusCode(),
                    sl.getReasonPhrase()));
        }

        for (Header h : response.getAllHeaders()) {
            if (h == null) {
                sb.append("header is null\r\n");
                continue;
            }
            sb.append(String.format("%s: %s\r\n", h.getName(), h.getValue()));
        }

        sb.append("\r\r\r\n");

        HttpEntity entity = response.getEntity();
        if (entity == null) {
            sb.append("content is null");
        } else {
            try {
                String content = Base64.encodeToString(
                        EntityUtils.toByteArray(entity), Base64.DEFAULT);

                sb.append(content + "\r\n");
            } catch (Exception e) {
                sb.append("\r\n\r\n====EXCEPTION=====\r\n" + e.toString()
                        + "\r\n");
            }
        }

        sb.append("\r\n==============END HttpResponse================\r\n");

        return sb.toString();
    } catch (Exception e) {
        return e.toString();
    }
}

Ok. 好。 So what I ended up doing is implementing my own HttpEntity class, and than just using response.setEntity(...) to replace the previous entity. 因此,我最终要做的是实现自己的HttpEntity类,而不仅仅是使用response.setEntity(...)替换先前的实体。 That class stores the result as binary array and returns it as many times as necessary. 该类将结果存储为二进制数组,并根据需要返回多次。

It might give you some performance issues, but will work: Example of my HttpClient with logging. 它可能会给您带来一些性能问题,但是会起作用:带记录功能的HttpClient示例。

private CloseableHttpResponse invoke(HttpRequestBase http) {
        try {
            CloseableHttpResponse response = client.execute(http);
            if (http instanceof HttpPost) {
                InputStream inputStream = ((HttpPost) http).getEntity().getContent();
                String body = IOUtils.toString(inputStream, Charset.defaultCharset());

                HttpEntity respBody = response.getEntity();
                String responseBody = StreamUtils.copyToString(respBody.getContent(), Charset.defaultCharset());
                response.setEntity(new StringEntity(responseBody));
                LOG.info(String.format("Sending request: [%s] %s => [%s] \nPayload:\n%s \nResponse:\n%s", http.getMethod(), http.getURI(), response.getStatusLine(), body, responseBody));
            } else {
                LOG.info(String.format("Sending request: [%s] %s => [%s]", http.getMethod(), http.getURI(), response.getStatusLine()));
            }
            return response;
        } catch (IOException e) {
            throw new RuntimeException("HTTP request failed: " + http.toString(), e);
        }
    }

Main idea is following: 主要思想如下:
1. make http call 1.拨打http
2. copy to string your response body: 2.复制到您的响应正文中:

 HttpEntity respBody = response.getEntity();  
 String responseBody = StreamUtils.copyToString(respBody.getContent(), Charset.defaultCharset());
  1. log it 记录下来
  2. set new response entity like response.setEntity(new StringEntity(responseBody)); 设置新的响应实体,如response.setEntity(new StringEntity(responseBody));

This example work good for small test framework, not sure it's good code for production application 该示例适用于小型测试框架,不确定适用于生产应用程序的代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 保留 HTTPEntity 而不消耗 stream - Preserve a HTTPEntity without consuming the stream 如何修改HttpEntity的内容 - How do I modify the content of an HttpEntity HttpEntity <String> request = new HttpEntity <String> (); 我如何在java中模拟它 - HttpEntity<String> request = new HttpEntity<String>( ); How do I mock this in java 如何两次使用HttpEntity? - How to consume HttpEntity twice? 如何将HTTPServletResponse转换为HttpEntity? - how to convert HTTPServletResponse into HttpEntity? 使用 EntityUtils.consume(httpEntity) 直到 stream 结束时消费如何导致将连接释放回连接池? - How does consuming till the end of stream using EntityUtils.consume(httpEntity) result in releasing the connection back to the connection pool? 是否可以在不消耗流的情况下读取HttpRequest参数? - Is it possible to read HttpRequest parameters without consuming stream? 如何停止使用 Java 和 Python 客户端在 RabbitMQ 中消费? - How do I stop consuming in RabbitMQ with Java and Python clients? 如何在不使用Java进行任何缓冲的情况下读取文件? - How do I read a file without any buffering in Java? 如何在没有*忙等待的情况下读取SwingWorker的结果*? - How do I read a SwingWorker's result *without* busy wait?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM