使用Hyper通过代理访问HTTPS网站的方法是什么?

4
以下是通过代理访问HTTPS网站的尝试:
extern crate hyper;
extern crate hyper_native_tls;

use hyper::net::HttpsConnector;
use hyper::client::{Client, ProxyConfig};
use hyper_native_tls::NativeTlsClient;

fn main() {
    let ssl = NativeTlsClient::new().unwrap();
    let connector = HttpsConnector::new(ssl);

    let client = Client::with_proxy_config(
        ProxyConfig::new(
            "http", "localhost", 3128, connector, ssl
        )
    );

    let response = client.get("https://httpbin.org").send().unwrap();
    println!("{}", response.headers);
}

我遇到了这个错误:

error[E0277]: the trait bound `hyper_native_tls::TlsStream<hyper::net::HttpStream>: std::fmt::Debug` is not satisfied
  --> src/main.rs:13:9
   |
13 |         ProxyConfig::new(
   |         ^^^^^^^^^^^^^^^^ the trait `std::fmt::Debug` is not implemented for `hyper_native_tls::TlsStream<hyper::net::HttpStream>`
   |
   = note: `hyper_native_tls::TlsStream<hyper::net::HttpStream>` cannot be formatted using `:?`; if it is defined in your crate, add `#[derive(Debug)]` or manually implement it
   = note: required because of the requirements on the impl of `std::fmt::Debug` for `hyper::net::HttpsStream<hyper_native_tls::TlsStream<hyper::net::HttpStream>>`
   = note: required because of the requirements on the impl of `hyper::net::SslClient<hyper::net::HttpsStream<hyper_native_tls::TlsStream<hyper::net::HttpStream>>>` for `hyper_native_tls::NativeTlsClient`
   = note: required by `<hyper::client::ProxyConfig<C, S>>::new`

error[E0277]: the trait bound `hyper_native_tls::TlsStream<hyper::net::HttpStream>: std::fmt::Debug` is not satisfied
  --> src/main.rs:13:9
   |
13 |           ProxyConfig::new(
   |  _________^ starting here...
14 | |             "http", "localhost", 3128, connector, ssl
15 | |         )
   | |_________^ ...ending here: the trait `std::fmt::Debug` is not implemented for `hyper_native_tls::TlsStream<hyper::net::HttpStream>`
   |
   = note: `hyper_native_tls::TlsStream<hyper::net::HttpStream>` cannot be formatted using `:?`; if it is defined in your crate, add `#[derive(Debug)]` or manually implement it
   = note: required because of the requirements on the impl of `std::fmt::Debug` for `hyper::net::HttpsStream<hyper_native_tls::TlsStream<hyper::net::HttpStream>>`
   = note: required because of the requirements on the impl of `hyper::net::SslClient<hyper::net::HttpsStream<hyper_native_tls::TlsStream<hyper::net::HttpStream>>>` for `hyper_native_tls::NativeTlsClient`
   = note: required by `hyper::client::ProxyConfig`

error[E0277]: the trait bound `hyper_native_tls::TlsStream<hyper::net::HttpStream>: std::fmt::Debug` is not satisfied
  --> src/main.rs:12:18
   |
12 |     let client = Client::with_proxy_config(
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::fmt::Debug` is not implemented for `hyper_native_tls::TlsStream<hyper::net::HttpStream>`
   |
   = note: `hyper_native_tls::TlsStream<hyper::net::HttpStream>` cannot be formatted using `:?`; if it is defined in your crate, add `#[derive(Debug)]` or manually implement it
   = note: required because of the requirements on the impl of `std::fmt::Debug` for `hyper::net::HttpsStream<hyper_native_tls::TlsStream<hyper::net::HttpStream>>`
   = note: required because of the requirements on the impl of `hyper::net::SslClient<hyper::net::HttpsStream<hyper_native_tls::TlsStream<hyper::net::HttpStream>>>` for `hyper_native_tls::NativeTlsClient`
   = note: required by `hyper::Client::with_proxy_config`

以下是 Cargo 依赖关系:

[dependencies]
hyper = "0.10"
hyper-native-tls = "0.2"

使用以下依赖项可以使事情变得更好:

[dependencies]
hyper = "0.10"
hyper-openssl = "0.2"

以下是该代码:

extern crate hyper;
extern crate hyper_openssl;

use hyper::net::HttpsConnector;
use hyper::client::{Client, ProxyConfig};
use hyper_openssl::OpensslClient as TlsClient;

fn main() {
    let ssl = TlsClient::new().unwrap();
    let connector = HttpsConnector::new(ssl.clone());

    let client = Client::with_proxy_config(
        ProxyConfig::new(
            "http", "localhost", 3128, connector, ssl
        )
    );

    let response = client.get("https://httpbin.org").send().unwrap();
    println!("{:#?}", response);
}

输出:

Response {
    status: Ok,
    headers: Headers { Server: nginx, Date: Thu, 12 Jan 2017 15:05:13 GMT, Content-Type: text/html; charset=utf-8, Content-Length: 12150, Connection: keep-alive, Access-Control-Allow-Origin: *, Access-Control-Allow-Credentials: true, },
    version: Http11,
    url: "https://httpbin.org/",
    status_raw: RawStatus(
        200,
        "OK"
    ),
    message: Http11Message {
        is_proxied: false,
        method: None,
        stream: Wrapper {
            obj: Some(
                Reading(
                    SizedReader(remaining=12150)
                )
            )
        }
    }
}

没有构建失败,但它不通过代理。


1
hyper_native_tls 上的任何结构似乎都没有实现 Debug,因此该代码上看到的行为是正确的。请确保您没有执行任何 fmt() 操作,并使用您的发现更新问题。 - E net4
@E_net4:应该是一个答案。我检查了ProxyConfigClient,两者都不需要Debug,所以似乎OP自己给自己惹麻烦了...而且错误信息也不太好。或者他没有使用最新版本的hyper(0.10.0),因此我参考的文档可能不太好。 - Matthieu M.
1
@MatthieuM。某种程度上来说,这是正确的。另一方面,这个问题质量很差,根本没有在措辞中提到使用“Debug”格式化输出。我宁愿让它被改进或删除。我也想知道是否有适当的重复内容。 - E net4
我已经更新了问题 @E_net4。 - tshepang
@ljedrz 是的,同样的错误。 - tshepang
显示剩余3条评论
1个回答

4
有关 hyper_native_tlsnative_tls 的未经测试的冲突。
目前,对于 NativeTlsClientSslClient 实现有一个限制,需要 T: Debug (代码)。问题中的代码无法编译,因为不管其参数类型如何,TlsStream 都没有实现 Debug。
首先,可以考虑删除上述约束,但这会引发 hyper_native_tls 中的其他几个错误:
error[E0277]: the trait bound `T: std::fmt::Debug` is not satisfied
   --> src/lib.rs:129:45
    |
129 |             Err(e) => Err(hyper::Error::Ssl(Box::new(e))),
    |                                             ^^^^^^^^^^^ the trait `std::fmt::Debug` is not implemented for `T`
    |
    = help: consider adding a `where T: std::fmt::Debug` bound
    = note: required because of the requirements on the impl of `std::error::Error` for `native_tls::HandshakeError<T>`
    = note: required for the cast to the object type `std::error::Error + std::marker::Sync + std::marker::Send + 'static`

深入进入这个问题,我们发现native_tls::HandshakeError包含了一个参数类型S,代表在该特定错误发生时被中断的流。这变成了另一个问题,因为该类型只实现了Debug,其中S: Debug,而根据Error特性,错误类型必须始终实现Debug

解决此特定问题的方法是为TlsStream提供Debug

#[derive(Debug, Clone)]
pub struct TlsStream<S>(Arc<Mutex<native_tls::TlsStream<S>>>);

第一个代码片段仍无法编译,因为在移动后仍使用了“ssl”,这里不容忍复制。第二个代码片段工作是通过克隆对象完成的,不幸的是,“NativeTlsClient”并没有实现这一点。我们也不能推导出这个实现,因为“native_tls::TlsConnector”也没有实现“Clone”。就这样,这个兔子洞应该就到这里结束了,以免成为调试报告。
我不太确定在这里还能做什么(除了根本不使用原生TLS),但我的建议是在“hyper_native_tls_client”中提出问题,解释它与Hyper的客户端代理不兼容(编辑:已经处理并修复!)。

https://github.com/sfackler/hyper-native-tls/commit/30e9d1574774aa9267ca8d4770f9af21f04edb13 - tshepang
@Tshepang 干得好。;) - E net4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接