分块传输编码时如何使用 HttpsUrlconnection 读取响应
How to read response using HttpsUrlconnection when transfer encoding is chunked
我正在编写一个 servlet,它在内部使用 HttpsUrlConnection 来调用另一个 Url。从 servlet,我必须 return 与我从 HttpsUrl 连接调用收到的相同响应和相同响应 header。
为此,我正在使用 getHeaderFields()
读取所有 headers:将 headers returned 复制到我的 Httpservletresponse object小服务程序。
此外,在那之后我尝试使用 connection.getErrorStream()
读取响应(这主要发生在服务器 return 的状态 > 400 时),这就是我使用 getErrorStream 的原因。然后我读取字节并将字节复制到我的 servlet 的 HttpServletResponse 输出流。
现在这在某些情况下工作正常。
但是当我调用的服务器使用传输编码分块的连接 returns 响应时,当我调用我的 servlet API 时,它是 returning 一个错误如果我将响应和响应 headers 复制到 Httpservlet 响应,则块编码无效。
在这种情况下,在日志中我看到当我使用 getHeaderFields 读取 headers 时,我看到的第一个 header 是分块传输编码,然后是下一个 header 名称为空,它的值为 HTTP 1/1 .
另外,我看到的回复也不对
如何从 httpsurlconnection 正确读取响应 headers 和响应 body 以及从我的 servlet 正确读取 return?
我遇到了类似的分块编码问题。与您不同的是,我的 servlet 在内部使用 HTTP 而不是 HTTPS。
我也使用一种方法来复制 header 字段。但是我提供了一个由 servlet 容器管理的 header 列表,所以我不创建、复制或编辑它们:
private static final Set forbiddenCopyHeaders = new HashSet<>(Arrays.asList(new String[]{
"connection"
, "transfer-encoding"
, "content-length"
, "via"
, "x-forwarded-for"
, "x-forwarded-host"
, "x-forwarded-server"
}));
这些是我用来复制响应的方法 headers:
private void copyResponseHeaders(CloseableHttpResponse internResponse, HttpServletResponse response)
{
Header[] headers = internResponse.getAllHeaders();
Header[] connHeaders = internResponse.getHeaders("connection");
StringBuilder connectionValue = new StringBuilder();
for (Header connHeader : connHeaders)
{
connectionValue.append(connHeader.getValue()).append(", ");
}
for (Header header : headers)
{
String headerName = header.getName();
boolean copyAllowed = !forbiddenCopyHeaders.contains(headerName.toLowerCase())
&& !StringUtils.containsIgnoreCase(connectionValue.toString(), headerName);
if (copyAllowed)
{
if (response.containsHeader(headerName))
{
response.addHeader(headerName, header.getValue());
}
else
{
response.setHeader(headerName, header.getValue());
}
}
}
setViaHeader(internResponse, response);
}
方法 setViaHeader():
private void setViaHeader(CloseableHttpResponse response, HttpServletResponse customerResponse)
{
String serverHostName = "companyServer";
try
{
serverHostName = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e)
{
logger.error("für den VIA-Header kann der Hostname nicht ermittelt werden", e);
System.err.println("für den VIA-Header kann der Hostname nicht ermittelt werden: " +
ExceptionUtils.getStackTrace(e));
}
Header[] originalViaHeaders = response.getHeaders("via");
StringBuilder via = new StringBuilder("");
if ((originalViaHeaders != null) && (originalViaHeaders.length > 0))
{
for (Header viaHeader : originalViaHeaders)
{
via.append(viaHeader.getValue()).append(", ");
}
}
via.append(response.getStatusLine().getProtocolVersion().toString()).append(" ").append(serverHostName);
customerResponse.setHeader("via", via.toString());
}
我正在编写一个 servlet,它在内部使用 HttpsUrlConnection 来调用另一个 Url。从 servlet,我必须 return 与我从 HttpsUrl 连接调用收到的相同响应和相同响应 header。
为此,我正在使用 getHeaderFields()
读取所有 headers:将 headers returned 复制到我的 Httpservletresponse object小服务程序。
此外,在那之后我尝试使用 connection.getErrorStream()
读取响应(这主要发生在服务器 return 的状态 > 400 时),这就是我使用 getErrorStream 的原因。然后我读取字节并将字节复制到我的 servlet 的 HttpServletResponse 输出流。
现在这在某些情况下工作正常。
但是当我调用的服务器使用传输编码分块的连接 returns 响应时,当我调用我的 servlet API 时,它是 returning 一个错误如果我将响应和响应 headers 复制到 Httpservlet 响应,则块编码无效。
在这种情况下,在日志中我看到当我使用 getHeaderFields 读取 headers 时,我看到的第一个 header 是分块传输编码,然后是下一个 header 名称为空,它的值为 HTTP 1/1 .
另外,我看到的回复也不对
如何从 httpsurlconnection 正确读取响应 headers 和响应 body 以及从我的 servlet 正确读取 return?
我遇到了类似的分块编码问题。与您不同的是,我的 servlet 在内部使用 HTTP 而不是 HTTPS。
我也使用一种方法来复制 header 字段。但是我提供了一个由 servlet 容器管理的 header 列表,所以我不创建、复制或编辑它们:
private static final Set forbiddenCopyHeaders = new HashSet<>(Arrays.asList(new String[]{
"connection"
, "transfer-encoding"
, "content-length"
, "via"
, "x-forwarded-for"
, "x-forwarded-host"
, "x-forwarded-server"
}));
这些是我用来复制响应的方法 headers:
private void copyResponseHeaders(CloseableHttpResponse internResponse, HttpServletResponse response)
{
Header[] headers = internResponse.getAllHeaders();
Header[] connHeaders = internResponse.getHeaders("connection");
StringBuilder connectionValue = new StringBuilder();
for (Header connHeader : connHeaders)
{
connectionValue.append(connHeader.getValue()).append(", ");
}
for (Header header : headers)
{
String headerName = header.getName();
boolean copyAllowed = !forbiddenCopyHeaders.contains(headerName.toLowerCase())
&& !StringUtils.containsIgnoreCase(connectionValue.toString(), headerName);
if (copyAllowed)
{
if (response.containsHeader(headerName))
{
response.addHeader(headerName, header.getValue());
}
else
{
response.setHeader(headerName, header.getValue());
}
}
}
setViaHeader(internResponse, response);
}
方法 setViaHeader():
private void setViaHeader(CloseableHttpResponse response, HttpServletResponse customerResponse)
{
String serverHostName = "companyServer";
try
{
serverHostName = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e)
{
logger.error("für den VIA-Header kann der Hostname nicht ermittelt werden", e);
System.err.println("für den VIA-Header kann der Hostname nicht ermittelt werden: " +
ExceptionUtils.getStackTrace(e));
}
Header[] originalViaHeaders = response.getHeaders("via");
StringBuilder via = new StringBuilder("");
if ((originalViaHeaders != null) && (originalViaHeaders.length > 0))
{
for (Header viaHeader : originalViaHeaders)
{
via.append(viaHeader.getValue()).append(", ");
}
}
via.append(response.getStatusLine().getProtocolVersion().toString()).append(" ").append(serverHostName);
customerResponse.setHeader("via", via.toString());
}