如何在不消费的情况下阅读HttpEntity?

时间:2014-09-23 16:28:45

标签: java android httpresponse

我有org.apache.http.HttpResponse个对象,我在代码的不同位置使用它。其中一个地方是伐木。

问题是当我运行以下日志代码时:

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

并且我尝试读取实际处理代码中的条目内容,这会导致代码抛出以下异常:

java.lang.IllegalStateException: Content has been consumed

我的问题是:如何在不使用日志代码的情况下阅读实体?

更新 这里是我用来将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();
    }
}

2 个答案:

答案 0 :(得分:0)

确定。所以我最终做的是实现我自己的HttpEntity类,而不仅仅是使用response.setEntity(...)来替换前一个实体。该类将结果存储为二进制数组,并根据需要多次返回。

答案 1 :(得分:0)

它可能会给您带来一些性能问题,但是会起作用: 我的带有记录功能的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);
        }
    }

主要思想如下:
1.拨打http
2.复制到响应正文中:

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

该示例适用于小型测试框架,不确定适用于生产应用程序的代码