[英]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());
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.