【问题标题】:Apache HttpComponents. Get response for CONNECT requestApache Http 组件。获取 CONNECT 请求的响应
【发布时间】:2016-05-26 12:29:33
【问题描述】:

我正在使用 Apache HtppComponents(版本 - 4.5.2),我正在尝试通过代理服务器请求 HTTPS 页面。

编辑:

我的主要问题是我需要知道如何区分代理服务器的故障和请求的 URI 的故障(对于 HTTP 和 HTTPS)。我有很多代理,它们不是 100% 可靠的,所以如果代理失败,我需要使用不同的代理服务器重试请求。

例如(在 HTTPS 的情况下),NoHttpResponseException 可以在两种情况下返回,即代理失败或目标 URL 失败时。我怎样才能知道问题的根源? NoHttpResponseException 是从哪里来的?来自目标 URI 的代理?

我想我可以尝试读取对代理服务器的CONNECT 请求的响应,如果它是200,那么我这意味着代理是好的,下一个NoHttpResponseException 来自目标URL。但是如果我立即得到NoHttpResponseException(在代理返回给我CONNECT 的200 状态代码之前),这意味着代理本身存在问题,我需要使用不同的代理服务器重试请求。但我找不到任何文档如何访问代理服务器返回的CONNECT 请求的响应。

另外,有时我会收到HttpHostConnectExceptionConnectTimeoutException。我将此异常视为代理问题(对于 HTTP 和 HTTPS) - 是正确的方式吗?或者即使对于目标 URL 也会发生这 2 个异常?

【问题讨论】:

  • 为什么首先要访问 CONNECT 响应消息?
  • @oleg Oleg,我的问题的根源是我需要知道如何区分代理服务器的故障和请求的 URI 的故障。例如,NoHttpResponseException 在这两种情况下都可以返回。所以我想读取代理在 CONNECT 请求的响应中返回的一些标头(如果有一些标头 - 这意味着代理很好并且目标 URI 有问题,如果代理服务器没有标头 - 这意味着在连接到代理期间发生了 NoHttpResponseException )
  • @oleg 如果您对如何区分代理服务器失败和请求的 URI 失败(特别是与 NoHttpResponseException 相关)有任何其他建议,请帮助我。谢谢
  • 代理失败是指代理服务器无法处理任何请求或仅处理特定请求。如果它是第一个,那么您可以在代理服务器中托管一个简单页面,并在发生任何故障时尝试检索该页面,如果无法检索该简单页面,则代理已关闭。除此之外,您可以尝试托管多个具有相同配置的代理服务器,如果它们都失败,那么很可能远程服务器(而不是代理)已经失败。
  • 我稍微编辑了我的问题,现在应该更容易理解我想要什么

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


【解决方案1】:

它不会很漂亮,但它应该可以解决问题

HttpHost myproxy = new HttpHost("myproxy", 8080)
CloseableHttpClient client = HttpClientBuilder.create()
        .setProxy(myproxy)
        .setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy() {

            @Override
            public boolean isAuthenticationRequested(HttpHost authhost, HttpResponse response, HttpContext context) {

                if (myproxy.equals(authhost)) {
                    context.setAttribute("proxy.status", response.getStatusLine());
                }
                return super.isAuthenticationRequested(authhost, response, context);
            }
        })
        .build();

HttpClientContext context = HttpClientContext.create();
HttpGet get = new HttpGet("https://httpbin.org/");
try (CloseableHttpResponse response = client.execute(get, context)) {
    EntityUtils.consume(response.getEntity());
}
StatusLine proxyStatus = context.getAttribute("proxy.status", StatusLine.class);
System.out.println("Proxy said " + proxyStatus);

PS:HttpHostConnectExceptionConnectTimeoutException 异常只能在第一跳抛出,也就是连接代理的时候。如果代理由于某种原因未能连接到目标服务器,它可能会以 5xx 状态响应 CONNECT 方法。

【讨论】:

  • 非常感谢,这应该会有所帮助!您能否回答我问题的最后一段(关于HttpHostConnectExceptionConnectTimeoutException)?我需要知道这种异常是否只发生在代理服务器或两种情况下。
  • 试过这段代码,但HttpResponse 对象包含来自请求的 URI 的信息,而不是来自代理对CONNECT 请求的回复。 IE。与直接使用response.getStatusLine() 相同。在日志中,我看到代理返回此状态行:HTTP/1.1 200 Connection established,但context.getAttribute("proxy.status", StatusLine.class) 返回HTTP/1.1 200 OK。 - IE。它是来自远程服务器的响应,而不是来自代理。为了证明这一点,我什至尝试获取标头而不是状态行 - 它仍然是来自远程服务器的标头,而不是来自代理。
  • 根据日志我知道这个方法被调用了两次。第一次来自代理的响应,第二次来自远程服务器的实际响应。所以"proxy.status" 在第二次调用中被覆盖。
  • 解决这个问题很简单,不是吗?我用最直接的解决方案更新了我的代码。
  • authhost 始终是代理服务器,但响应可以来自目标 URL 或代理。我使用了像这样的守卫` if (context.getAttribute("proxy.response") == null )` { //set proxy response }`
猜你喜欢
  • 2020-01-04
  • 1970-01-01
  • 2020-02-01
  • 1970-01-01
  • 2020-11-26
  • 2016-09-14
  • 1970-01-01
  • 2020-11-06
  • 1970-01-01
相关资源
最近更新 更多