user3565529
user3565529

Reputation: 1367

How to read response using HttpsUrlconnection when transfer encoding is chunked

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

Answers (1)

JimHawkins
JimHawkins

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

Related Questions