Reputation: 1367
I am writing a servlet which internally uses HttpsUrlConnection to call another Url. From the servlet, I have to return the same response and same response headers that I receive from the HttpsUrlConnection call.
For that, I was reading all the headers using getHeaderFields()
: copy the headers returned to the Httpservletresponse object of my servlet.
Also, After that I am trying to read response after that using connection.getErrorStream()
(this is mostly happening when server returns status > 400), thats why I use getErrorStream. Then I read the bytes and copy the bytes to HttpServletResponse outputstream of my servlet.
Now this is working fine is some cases.
But when the server that I call using the connection returns response with Transfer Encoding chunked, then when I call my servlet API, it is returning an error for invalid chunk encoding if I copy the response and response headers to the Httpservlet response.
In this case, in the logs I see that when I read the headers using getHeaderFields, the first header that i see is Transfer encoding chunked, then the next header name is null and it has value HTTP 1/1 .
Also, the response I see is also not proper.
How to read the response headers and the response body in this case from the httpsurlconnection and return that from my servlet properly?
Upvotes: 1
Views: 1033
Reputation: 4994
I faced a similar issue with chunked encoding. The difference to you is that my servlet used HTTP instead of HTTPS internally.
I use a method to copy the header fields, too. But I supply a list of headers that are managed by the servlet container, so I don't create, copy or edit them:
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"
}));
These are the methods I use for copying the response 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);
}
Method 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());
}
Upvotes: 1