javax.net.ssl.HttpsURLConnection vs org.apache.http.client.HttpClient

问题描述

我正在尝试从 apache httpClient 获取响应信息,但是我没有得到我需要的信息。 HttpsURLConnection 过去给了我一些问题,我不想使用它。我正在尝试从深入了解这些库并为我提供原因或解决方案的人那里获得帮助。

当我尝试使用 HttpsURLConnection 调用 URL 时,它为我提供了所有“文档”url 调用,我可以遍历所有...

public InputStream getResource(String resource,String username,String password) throws Exception {
        int redirects = 0;

        // Place an upper limit on the number of redirects we will follow
        while (redirects < 10) {
            ++redirects;

            // Configure a connection to the resource server and submit the request for our resource.
            URL url = new URL(resource);
            HttpsURLConnection connection = null;
            if (url.getProtocol().equalsIgnoreCase("https")) {
                connection = (HttpsURLConnection) url.openConnection();
            } else {
                connection = (HttpsURLConnection) new URL("https",url.getAuthority(),url.getFile()).openConnection();
            }
            connection.setRequestMethod("GET");
            connection.setInstanceFollowRedirects(false);
            connection.setUseCaches(false);
            connection.setDoInput(true);

            // If this is the URS server,add in the authentication header.
            if (resource.startsWith(URS)) {
                connection.setDoOutput(true);
                connection.setRequestProperty("Authorization","Basic " + Base64.getEncoder().encodetoString((username + ":" + password).getBytes()));
            }

            if (connection.getResponseCode() == 200) {
                return connection.getInputStream();
            }

            if (connection.getResponseCode() != 302) {
                throw new Exception("Invalid response from server - status " + connection.getResponseCode());
            }
            
            resource = connection.getHeaderField("Location");
        }
        
        throw new Exception("Redirection limit exceeded");
    }

... 使用此代码,我可以遍历每个 url,我可以发送基本身份验证,然后登录页面。之后,我再打电话给其他时间并获取它的信息...

enter image description here

使用 HttpsURLConnection 我得到了这 2 个文档,我只是阅读了第一个的“位置”。然后我用基本的身份验证。

如果我尝试对 org.apache.http.client.HttpClient 做同样的事情......

public Optional<HttpPayloadResponse> getResource(String resource,String password) throws Exception {
        int redirects = 0;

        // Place an upper limit on the number of redirects we will follow
        while (redirects < 10) {
            ++redirects;
            
            BasicHttpQuery basicHttpQuery = new BasicHttpQuery();
            basicHttpQuery.setTimeOutMillis(20000);
            basicHttpQuery.setHttpRequestType(HttpRequestTypeEnum.GET);
            basicHttpQuery.setUrl(resource);
            basicHttpQuery.setTimeOutMillis(30000);
            
            Optional<HttpPayloadResponse> response = EoHttpClient.executeHttpQuery(basicHttpQuery);
            
            if (response.get().getResponseHeaders().get("Location").equals(URL_FILE_2_DOWNLOAD)) {
                return response;
            } else {
                // If this is the URS server,add in the authentication header.
                if (resource.startsWith(URS)) {
                    basicHttpQuery.getHttpHeader().put("Authorization","Basic " + Base64.getEncoder().encodetoString((username + ":" + password).getBytes()));
                }
                
                resource = response.get().getResponseHeaders().get("Location");
            }
        }
        
        throw new Exception("Redirection limit exceeded");
    }

try(CloseableHttpClient httpClient = buildHttpClientNotCheckSsl(archiveQuery.getTimeOutMillis())) {
        
        HttpRequestBase httpOperation = null;
        if (archiveQuery.getHttpRequestType().equals(HttpRequestTypeEnum.GET)) {
            httpOperation = new HttpGet(archiveQuery.getUrl());
        } else {
            HttpPost httpPost = new HttpPost(archiveQuery.getUrl());
            httpPost.setEntity( new StringEntity(archiveQuery.getQueryPayload()));
            httpOperation = httpPost;
        }
        
        for (Map.Entry<String,String> currentHeader : archiveQuery.getHttpHeader().entrySet()) {
            httpOperation.setHeader(currentHeader.getKey(),currentHeader.getValue());
        }
        
        try (CloseableHttpResponse response = httpClient.execute(httpOperation)) {

public static CloseableHttpClient buildHttpClientNotCheckSsl(int timeoutMillis) throws Exception {
     
    RequestConfig requestConfig = RequestConfig.custom().
            setConnectTimeout(timeoutMillis).setConnectionRequestTimeout(timeoutMillis).setSocketTimeout(timeoutMillis).
            build();

    final SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(null,(x509CertChain,authType) -> true)
            .build();

    return HttpClientBuilder.create()
            .setSSLContext(sslContext)
            .setConnectionManager(
                    new PoolingHttpClientConnectionManager(
                            RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http",PlainConnectionSocketFactory.INSTANCE)
                            .register("https",new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE))
                            .build()
                            ))
            .setDefaultRequestConfig(requestConfig)
            .build();
}

它只给了我第二个调用,它没有显示我在导航器的网络开发资源管理器中看到的所有“文档”调用。为什么?有没有办法用apache httpClient?

解决方法

我找到了解决方案。需要在调用中禁用重定向...

public static void main(String[] args) throws IOException {

    HttpGet request = new HttpGet("https://cddis.nasa.gov/archive/products/iers/finals2000A.data");

    try (CloseableHttpClient httpClient = HttpClientBuilder.create().disableRedirectHandling().build();
         CloseableHttpResponse response = httpClient.execute(request)) {

        // Get HttpResponse Status
        System.out.println(response.getProtocolVersion());              // HTTP/1.1
        System.out.println(response.getStatusLine().getStatusCode());   // 301
        System.out.println(response.getStatusLine().getReasonPhrase()); // Moved Permanently
        System.out.println(response.getStatusLine().toString());        // HTTP/1.1 301 Moved Permanently

        HttpEntity entity = response.getEntity();
        if (entity != null) {
            // return it as a String
            String result = EntityUtils.toString(entity);
            System.out.println(result);
        }

    }

}