Apache httpclient 4.x 302重定向并关闭keepalive?

时间:2015-04-08 19:00:41

标签: java http apache-httpclient-4.x

我一直在尝试向服务器发出HTTP GET请求,该服务器使用HttpClient 4.4.1(GA)返回带有重定向路径的302。我有一些问题使它在不使用keepalive时无缝地工作。

这是我的代码:

    HttpGet httpget = new HttpGet("http://10.104.107.22:1354/video/Manifest");
    Header header = new BasicHeader(HttpHeaders.CONNECTION,
            "close");
    ArrayList<Header> headers = new ArrayList<>();
    headers.add(header);
    CloseableHttpClient client = HttpClients.custom().setDefaultHeaders(headers).build();
    HttpEntity entity = null;
    CloseableHttpResponse response = client.execute(httpget);

    try{    
        entity = response.getEntity();  
            if (entity != null) {
                long len = entity.getContentLength();
                if (len != -1 && len < 2048) {
                    responseBody = EntityUtils.toString(entity);
                } 
                else {
                    InputStream instream = entity.getContent();
                    try {
                        StringWriter writer = new StringWriter();
                        IOUtils.copy(instream, writer, "UTF-8");
                        responseBody = writer.toString();
                    } finally {
                        instream.close();
                    }
                }
            }
    }
    finally{
        EntityUtils.consume(entity);
        response.close();
        client.close();
    }

非常简单。

获取GET请求时,服务器以

响应
    HTTP/1.1 302 Moved Temporarily
    Content-Length: 0
    Location: http://10.104.107.22:1354/video/Manifest?sessionID=250849653588053716653279720260905006780
    Date: Mon, 06 Apr 2015 19:18:42 GMT

很酷,现在我们知道去哪了。问题是,httpclient然后抱怨错误:

    Apr 08, 2015 2:39:29 PM org.apache.http.impl.execchain.RetryExec execute
    INFO: I/O exception (org.apache.http.NoHttpResponseException) caught when processing request to /127.0.0.1->{}->http://10.104.107.22:1354:         The target server failed to respond
    Apr 08, 2015 2:39:29 PM org.apache.http.impl.execchain.RetryExec execute
    INFO: Retrying request to /127.0.0.1->{}->http://10.104.107.22:1354

说实话,然后重试从IOException恢复并在同一连接中发送带有重定向URL的另一个请求!

    GET /video/Manifest?sessionID=250849653588053716653279720260905006780 HTTP/1.1
    Connection: close
    Host: 10.104.107.22:1354
    User-Agent: Apache-HttpClient/4.4.1 (Java 1.5 minimum; Java/1.7.0_55)
    Accept-Encoding: gzip,deflate

现在,既然我们从头开始就指定了“Connection:close”作为标题,那么服务器会抓住这一点并关闭其侧面的套接字。然后我的客户端获得RST信号。重新发送的Url会再次重新发送请求,这次工作正常。

我正在尝试解决的问题是如何阻止客户端在同一连接中发送重定向请求。我设法通过在CloseableHttpClient对象上使用disableRedirectHandling()的第一个请求之后禁用重定向,然后在单独的连接中自己处理302响应来“解决”这个问题。如果我使用keepAlive来处理这个问题,事情也可以正常工作,虽然我必须在完成后用ConnectionKeepAliveStrategy策略超时客户端套接字。

有没有办法让HttpClient 4.4.1能够自动处理单独请求中302重定向的处理?

编辑:按要求为GET请求发布完整的通信。

    GET /video/Manifest HTTP/1.1
    Connection: close
    Host: 10.104.107.22:1354
    User-Agent: Apache-HttpClient/4.4.1 (Java 1.5 minimum; Java/1.7.0_55)
    Accept-Encoding: gzip,deflate

    HTTP/1.1 302 Moved Temporarily
    Content-Length: 0
    Location: http://10.104.107.22:1354/video/Manifest?sessionID=250849653588053716653279720260905006780
    Date: Wed, 08 Apr 2015 14:36:42 GMT

    GET /video/Manifest?sessionID=250849653588053716653279720260905006780 HTTP/1.1
    Connection: close
    Host: 10.104.107.22:1354
    User-Agent: Apache-HttpClient/4.4.1 (Java 1.5 minimum; Java/1.7.0_55)
    Accept-Encoding: gzip,deflate

然后我从服务器获取RST信号。

Header Wire +上下文记录。

    2015/04/08 15:57:25:657 EDT [DEBUG] RequestAddCookies - CookieSpec selected: default
    2015/04/08 15:57:25:667 EDT [DEBUG] RequestAuthCache - Auth cache not set in the context
    2015/04/08 15:57:25:668 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection request: [route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
    2015/04/08 15:57:25:679 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection leased: [id: 0][route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
    2015/04/08 15:57:25:681 EDT [DEBUG] MainClientExec - Opening connection /127.0.0.1->{}->http://10.104.107.22:1354
    2015/04/08 15:57:25:683 EDT [DEBUG] DefaultHttpClientConnectionOperator - Connecting to /10.104.107.22:1354
    2015/04/08 15:57:25:686 EDT [DEBUG] DefaultHttpClientConnectionOperator - Connection established 127.0.0.1:46323<->10.104.107.22:1354
    2015/04/08 15:57:25:686 EDT [DEBUG] MainClientExec - Executing request GET /video/Manifest HTTP/1.1
    2015/04/08 15:57:25:686 EDT [DEBUG] MainClientExec - Target auth state: UNCHALLENGED
    2015/04/08 15:57:25:687 EDT [DEBUG] MainClientExec - Proxy auth state: UNCHALLENGED
    2015/04/08 15:57:25:688 EDT [DEBUG] headers - http-outgoing-0 >> GET /video/Manifest HTTP/1.1
    2015/04/08 15:57:25:688 EDT [DEBUG] headers - http-outgoing-0 >> Connection: close
    2015/04/08 15:57:25:688 EDT [DEBUG] headers - http-outgoing-0 >> Host: 10.104.107.22:1354
    2015/04/08 15:57:25:688 EDT [DEBUG] headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.4.1 (Java/1.7.0_55)
    2015/04/08 15:57:25:688 EDT [DEBUG] headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
    2015/04/08 15:57:25:700 EDT [DEBUG] headers - http-outgoing-0 << HTTP/1.1 302 Moved Temporarily
    2015/04/08 15:57:25:700 EDT [DEBUG] headers - http-outgoing-0 << Content-Length: 0
    2015/04/08 15:57:25:701 EDT [DEBUG] headers - http-outgoing-0 << Location: http://10.104.107.22:1354/video/Manifest?sessionID=162729772390321694625639849465722594850
    2015/04/08 15:57:25:701 EDT [DEBUG] headers - http-outgoing-0 << Date: Wed, 08 Apr 2015 19:57:25 GMT
    2015/04/08 15:57:25:707 EDT [DEBUG] MainClientExec - Connection can be kept alive indefinitely
    2015/04/08 15:57:25:707 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection [id: 0][route: /127.0.0.1->{}->http://10.104.107.22:1354] can be kept alive indefinitely
    2015/04/08 15:57:25:707 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection released: [id: 0][route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 20]
    2015/04/08 15:57:25:709 EDT [DEBUG] DefaultRedirectStrategy - Redirect requested to location 'http://10.104.107.22:1354/video/Manifest?sessionID=162729772390321694625639849465722594850'
    2015/04/08 15:57:25:713 EDT [DEBUG] RedirectExec - Redirecting to 'http://10.104.107.22:1354/video/Manifest?sessionID=162729772390321694625639849465722594850' via /127.0.0.1->{}->http://10.104.107.22:1354
    2015/04/08 15:57:25:714 EDT [DEBUG] RequestAddCookies - CookieSpec selected: default
    2015/04/08 15:57:25:714 EDT [DEBUG] RequestAuthCache - Auth cache not set in the context
    2015/04/08 15:57:25:714 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection request: [route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 20]
    2015/04/08 15:57:25:715 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection leased: [id: 0][route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
    2015/04/08 15:57:25:715 EDT [DEBUG] MainClientExec - Executing request GET /video/Manifest?sessionID=162729772390321694625639849465722594850 HTTP/1.1
    2015/04/08 15:57:25:715 EDT [DEBUG] MainClientExec - Target auth state: UNCHALLENGED
    2015/04/08 15:57:25:716 EDT [DEBUG] MainClientExec - Proxy auth state: UNCHALLENGED
    2015/04/08 15:57:25:716 EDT [DEBUG] headers - http-outgoing-0 >> GET /video/Manifest?sessionID=162729772390321694625639849465722594850 HTTP/1.1
    2015/04/08 15:57:25:716 EDT [DEBUG] headers - http-outgoing-0 >> Connection: close
    2015/04/08 15:57:25:716 EDT [DEBUG] headers - http-outgoing-0 >> Host: 10.104.107.22:1354
    2015/04/08 15:57:25:716 EDT [DEBUG] headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.4.1 (Java/1.7.0_55)
    2015/04/08 15:57:25:717 EDT [DEBUG] headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
    2015/04/08 15:57:25:717 EDT [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-0: Close connection
    2015/04/08 15:57:25:718 EDT [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-0: Shutdown connection
    2015/04/08 15:57:25:718 EDT [DEBUG] MainClientExec - Connection discarded
    2015/04/08 15:57:25:718 EDT [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-0: Close connection
    2015/04/08 15:57:25:718 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection released: [id: 0][route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
    2015/04/08 15:57:25:718 EDT [INFO] RetryExec - I/O exception (org.apache.http.NoHttpResponseException) caught when processing request to /127.0.0.1->{}->http://10.104.107.22:1354: The target server failed to respond
    2015/04/08 15:57:25:718 EDT [DEBUG] RetryExec - The target server failed to respond <org.apache.http.NoHttpResponseException: The target server failed to respond>org.apache.http.NoHttpResponseException: The target server failed to respond
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:143)
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
        at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:261)
        at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:165)
        at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:167)
        at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272)
        at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
        at WorkingNonKeepAliveUseCase.requestWithoutKeepAlive(WorkingNonKeepAliveUseCase.java:109)
        at Runner.main(Runner.java:13)

    2015/04/08 15:57:25:720 EDT [INFO] RetryExec - Retrying request to /127.0.0.1->{}->http://10.104.107.22:1354
    2015/04/08 15:57:25:720 EDT [DEBUG] RequestAddCookies - CookieSpec selected: default
    2015/04/08 15:57:25:720 EDT [DEBUG] RequestAuthCache - Auth cache not set in the context
    2015/04/08 15:57:25:720 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection request: [route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
    2015/04/08 15:57:25:721 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection leased: [id: 1][route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
    2015/04/08 15:57:25:721 EDT [DEBUG] MainClientExec - Opening connection /127.0.0.1->{}->http://10.104.107.22:1354
    2015/04/08 15:57:25:721 EDT [DEBUG] DefaultHttpClientConnectionOperator - Connecting to /10.104.107.22:1354
    2015/04/08 15:57:25:721 EDT [DEBUG] DefaultHttpClientConnectionOperator - Connection established 127.0.0.1:40753<->10.104.107.22:1354
    2015/04/08 15:57:25:721 EDT [DEBUG] MainClientExec - Executing request GET /video/Manifest?sessionID=162729772390321694625639849465722594850 HTTP/1.1
    2015/04/08 15:57:25:721 EDT [DEBUG] MainClientExec - Target auth state: UNCHALLENGED
    2015/04/08 15:57:25:721 EDT [DEBUG] MainClientExec - Proxy auth state: UNCHALLENGED
    2015/04/08 15:57:25:722 EDT [DEBUG] headers - http-outgoing-1 >> GET /video/Manifest?sessionID=162729772390321694625639849465722594850 HTTP/1.1
    2015/04/08 15:57:25:722 EDT [DEBUG] headers - http-outgoing-1 >> Connection: close
    2015/04/08 15:57:25:722 EDT [DEBUG] headers - http-outgoing-1 >> Host: 10.104.107.22:1354
    2015/04/08 15:57:25:722 EDT [DEBUG] headers - http-outgoing-1 >> User-Agent: Apache-HttpClient/4.4.1 (Java/1.7.0_55)
    2015/04/08 15:57:25:722 EDT [DEBUG] headers - http-outgoing-1 >> Accept-Encoding: gzip,deflate
    2015/04/08 15:57:25:792 EDT [DEBUG] headers - http-outgoing-1 << HTTP/1.1 200 OK
    2015/04/08 15:57:25:792 EDT [DEBUG] headers - http-outgoing-1 << Content-Length: 17090
    2015/04/08 15:57:25:792 EDT [DEBUG] headers - http-outgoing-1 << Pragma: no-cache
    2015/04/08 15:57:25:793 EDT [DEBUG] headers - http-outgoing-1 << Cache-Control: max-age=0, no-cache, no-store
    2015/04/08 15:57:25:793 EDT [DEBUG] headers - http-outgoing-1 << Content-Type: application/vnd.ms-sstr+xml
    2015/04/08 15:57:25:793 EDT [DEBUG] headers - http-outgoing-1 << Date: Wed, 08 Apr 2015 19:57:25 GMT
    2015/04/08 15:57:25:794 EDT [DEBUG] MainClientExec - Connection can be kept alive indefinitely
    2015/04/08 15:57:26:795 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection [id: 1][route: /127.0.0.1->{}->http://10.104.107.22:1354] can be kept alive indefinitely
    2015/04/08 15:57:26:796 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection released: [id: 1][route: /127.0.0.1->{}->http://10.104.107.22:1354][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 20]
    2015/04/08 15:57:26:796 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection manager is shutting down
    2015/04/08 15:57:26:796 EDT [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-1: Close connection
    2015/04/08 15:57:26:797 EDT [DEBUG] DefaultManagedHttpClientConnection - http-outgoing-1: Close connection
    2015/04/08 15:57:26:797 EDT [DEBUG] PoolingHttpClientConnectionManager - Connection manager shut down

1 个答案:

答案 0 :(得分:0)

问题在于这部分

2015/04/08 15:57:25:700 EDT [DEBUG] headers - http-outgoing-0 << HTTP/1.1 302 Moved Temporarily
2015/04/08 15:57:25:700 EDT [DEBUG] headers - http-outgoing-0 << Content-Length: 0
2015/04/08 15:57:25:701 EDT [DEBUG] headers - http-outgoing-0 << Location: http://10.104.107.22:1354/video/Manifest?sessionID=162729772390321694625639849465722594850
2015/04/08 15:57:25:701 EDT [DEBUG] headers - http-outgoing-0 << Date: Wed, 08 Apr 2015 19:57:25 GMT 

服务器发回的重定向响应不包含服务器之后要关闭连接的任何线索。 HttpClient尽职尽责地将连接返回到池中,然后将其返回以处理导致I / O错误的重定向。

是否真的有理由完全禁用连接持久性?我认为你可能最好让HttpClient重用同一个会话的连接,然后在会话结束后立即从连接池中逐出所有持久连接。

来自Oleg Kalnichevski的后续评论。

  

HttpClient希望相反的端点明确说明其意图并发送&#39; Connection:close&#39;如果它打算放弃连接。

这解决了我的问题。