【问题标题】:How to read response using HttpsUrlconnection when transfer encoding is chunked传输编码分块时如何使用 HttpsUrlconnection 读取响应
【发布时间】:2016-06-11 04:27:55
【问题描述】:

我正在编写一个内部使用 HttpsUrlConnection 调用另一个 Url 的 servlet。从 servlet 中,我必须返回从 HttpsUrlConnection 调用中收到的相同响应和相同的响应标头。

为此,我正在使用 getHeaderFields() 读取所有标头:将返回的标头复制到我的 servlet 的 Httpservletresponse 对象。

另外,之后我尝试使用connection.getErrorStream() 读取响应(这主要发生在服务器返回状态> 400 时),这就是我使用getErrorStream 的原因。然后我读取字节并将字节复制到我的 servlet 的 HttpServletResponse 输出流中。

现在这在某些情况下可以正常工作。

但是,当我使用连接调用的服务器返回传输编码分块的响应时,当我调用我的 servlet API 时,如果我将响应和响应标头复制到 Httpservlet 响应,它将返回无效块编码的错误。

在这种情况下,在日志中我看到当我使用 getHeaderFields 读取标头时,我看到的第一个标头是传输编码分块,然后下一个标头名称为 null 并且它的值为 HTTP 1/1 。

另外,我看到的反应也不正确。

在这种情况下,如何从 httpsurlconnection 读取响应标头和响应正文并从我的 servlet 正确返回?

【问题讨论】:

    标签: java http servlets urlconnection httpsurlconnection


    【解决方案1】:

    我在分块编码方面遇到了类似的问题。与您不同的是,我的 servlet 在内部使用的是 HTTP 而不是 HTTPS。

    我也使用一种方法来复制标题字段。但我提供了一个由 servlet 容器管理的标头列表,因此我不会创建、复制或编辑它们:

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

    这些是我用于复制响应标头的方法:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-28
      • 2013-05-03
      • 2018-07-12
      • 2010-09-06
      • 1970-01-01
      • 2011-04-03
      • 2011-02-09
      • 1970-01-01
      相关资源
      最近更新 更多