【问题标题】:HttpClient 4.3 changed argument (query) handling?HttpClient 4.3 更改参数(查询)处理?
【发布时间】:2014-05-10 14:35:54
【问题描述】:

我确定我遗漏了一些东西,但在我看来,HttpClient 发送请求的行为在参数方面有所不同。

问题是,任何带有参数的请求都会导致状态码 501。 在 4.2 版本中,这些请求得到了正确处理。

棘手的部分是,当参数是通过 URIBuilder 构建时,参数没有任何空间,问题也是原告,如下所述: http://hc.apache.org/httpcomponents-client-4.3.x/tutorial/html/fundamentals.html

我想我需要一种方法来放置 params:BasicHttpsParams 集合,而不是将它们与普通 uri 连接 - 因为它们接缝不会被 HttpGet 以这种方式识别。此时在 4.2 和 4.3 之间有什么变化吗?

这里是我们的get方法是如何实现的代码:

private static CloseableHttpClient httpAgent = initializeCloseableHttpClient(connectionManager);

private static CloseableHttpClient initializeCloseableHttpClient(PoolingHttpClientConnectionManager connectionManager) {
    RequestConfig requestConfig = RequestConfig.custom()
                               .setConnectTimeout(500)
                               .setConnectionRequestTimeout(DEFAULT_CONNECTION_TIMEOUT)
                               .setSocketTimeout(DEFAULT_SOCKET_TIMEOUT)
                               .build();

    ConnectionConfig connectionConfig = ConnectionConfig.custom()
                               .setCharset(StandardCharsets.UTF_8)
                               .build();

    CloseableHttpClient httpClient = HttpClients.custom()
                               .setConnectionManager(connectionManager)
                               .setDefaultRequestConfig(requestConfig)
                               .setDefaultConnectionConfig(connectionConfig)
                               .build();
     return httpClient;
}

public static String get(String url, Map<String, String> arguments) {
    String argumentString = getArgumentString(arguments == null ? EMPTY_COLLECTION : arguments.entrySet());
    HttpGet getMethod = new HttpGet(url + argumentString);
    return request(getMethod, null);
}

private static String request(HttpUriRequest method, AuthenticationDetails authenticationDetails) {
    InputStreamProcessor processor = new CopyToStringInputStreamProcessor();
    processStream(method, authenticationDetails, processor);
    return (String) processor.getResult();
}

 private static void processStream(HttpUriRequest method, AuthenticationDetails authenticationDetails, InputStreamProcessor processor) {
    try {
        HttpClientContext context = null;
        if (authenticationDetails != null) {

            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(authenticationDetails.getUsername(), authenticationDetails.getPassword());
            credsProvider.setCredentials(new AuthScope(method.getURI().getHost(), method.getURI().getPort()), credentials);

            // Create AuthCache instance
            AuthCache authCache = new BasicAuthCache();
            // Generate BASIC scheme object and add it to the local auth cache
            BasicScheme basicAuth = new BasicScheme();
            HttpHost targetHost = new HttpHost(method.getURI().getHost(), method.getURI().getPort(), method.getURI().getScheme());
            authCache.put(targetHost, basicAuth);

            // Add AuthCache to the execution context
            context = HttpClientContext.create();
            context.setCredentialsProvider(credsProvider);
            context.setAuthCache(authCache);
        }

        for (int i = 0; i < 3; i++) {
            CloseableHttpResponse response = httpAgent.execute(method, context);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200 && statusCode != 302) { // redirect is also ok
                throw new HttpClientException(String.format("A http request responds with failure code: %d (%s), requested uri: %s", statusCode, response.getStatusLine().getReasonPhrase(), method.getRequestLine().getUri()));
            }

            try {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    try (InputStream responseStream = entity.getContent()) {
                        processor.process(responseStream);
                        EntityUtils.consume(entity);
                    }
                    catch (IOException ex) {
                        throw ex; // In case of an IOException the connection will be released back to the connection manager automatically
                    }
                    catch (RuntimeException ex) {
                        method.abort(); // In case of an unexpected exception you may want to abort the HTTP request in order to shut down the underlying connection and release it back to the connection manager.
                        throw ex;
                    }
                }
            } finally {
                response.close();
            }
        }
    }
    catch (IOException e) {
        throw new HttpClientException(String.format("IO exception while processing http request on url: %s. Message: %s", method.getRequestLine().getUri(), e.getMessage()), e);
    }
    catch (Exception e) {
        throw new HttpClientException(String.format("Exception while processing http request on on url: %s. Message: %s", method.getRequestLine().getUri(), e.getMessage()), e);
    }
}

非常感谢任何可能出错的建议。

谢谢

【问题讨论】:

  • 打印您的请求和响应标头,可能会有用。
  • 头组在两种情况下都是空的(迁移前后)
  • 以上对请求有效。响应标头如下所示:HttpClient 2.5:[日期:星期一,2014 年 3 月 31 日 13:08:40 GMT,服务器:LocalTestServer/1.1,内容长度:8,内容类型:文本/纯文本; charset=UTF-8, Connection: Keep-Alive] HttpClient 3.3: [日期: Mon, 31 Mar 2014 13:12:43 GMT, Content-Length: 0, Connection: Close]

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


【解决方案1】:

5xx 是服务器错误。在查看服务器日志之前,没有理由假设客户端出现任何问题。如果您无权访问服务器日志,请检查响应文本,其中可能会显示服务器发生故障的原因。

【讨论】:

  • 我会按照你的设想去做,但奇怪的是同一个(测试服务器)实例使用 HttpClient 4.2 完成了她的工作
  • 很可能在 4.3.x 中发生了一些变化,导致服务器失败。但找出什么是从服务器开始诊断的最佳方法。
  • 两个会话(4.2 和 4.3)的连线日志也可能对 hc.apache.org/httpcomponents-client-4.3.x/logging.html 有所帮助
  • 感谢您的评论,但我已经在使用调试器,所以我可以跟踪每一步,直到请求被执行和响应到达之后。服务器可能在这里提供更多信息 - 但据我所知,它只说没有参数。
  • “4.3 版本系列的主题是精简组件配置和弃用基于 HttpParams 的旧配置 API,转而支持基于构造函数的依赖注入和配置参数的普通对象。”来自apache.org/dist/httpcomponents/httpcore/RELEASE_NOTES-4.3.x.txt。如果您确定服务器返回 501 实际上是一个错误的请求 (400),然后比较日志以确认请求不同并相应地更新您的客户端。
【解决方案2】:

问题在于以下循环:

for (int i = 0; i < 3; i++) {...}

我不知道它是什么时候进入代码的,虽然它有它的原因为什么请求是 sendet 3 次,但发现它在删除它之前和之后都不存在,一切都开始正常工作.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-08
    • 2020-09-13
    • 2018-01-10
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 2021-06-27
    相关资源
    最近更新 更多