簡體   English   中英

傳輸編碼分塊時如何使用HttpsUrlconnection讀取響應

[英]How to read response using HttpsUrlconnection when transfer encoding is chunked

我正在編寫一個內部使用HttpsUrlConnection調用另一個URL的servlet。 從servlet,我必須返回與從HttpsUrlConnection調用接收到的相同的響應和相同的響應標頭。

為此,我正在使用getHeaderFields()讀取所有標頭:將標頭復制到我的servlet的Httpservletresponse對象中。

另外,在那之后我嘗試使用connection.getErrorStream()讀取響應(這主要是在服務器返回狀態> 400時發生),這就是為什么我使用getErrorStream的原因。 然后,我讀取字節並將字節復制到我的Servlet的HttpServletResponse輸出流中。

現在在某些情況下可以正常工作。

但是,當我使用連接調用的服務器返回的響應帶有分塊的Transfer Encoding時,那么當我調用Servlet API時,如果將響應和響應標頭復制到Httpservlet響應,則它將返回錯誤的無效塊編碼。

在這種情況下,在日志中,我看到當我使用getHeaderFields讀取標頭時,看到的第一個標頭是分塊的傳輸編碼,然后下一個標頭名稱為null,其值為HTTP 1/1。

另外,我看到的回應也不正確。

在這種情況下,如何從httpsurlconnection讀取響應標頭和響應主體,並從我的servlet中正確返回它們?

我在分塊編碼時遇到了類似的問題。 與您不同的是,我的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());
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM