2017-01-12 112 views
3

以下是通过代理到达HTTPS站点的尝试:如何通过Hyper的代理服务器访问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` 

这里有货的依赖:

[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) 
       ) 
      ) 
     } 
    } 
} 

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

+0

并非所有这些错误都是由于您试图在调试模式下打印“响应”而不执行“调试”? – ljedrz

+0

即使我不打印任何东西,我也会得到相同的错误 – Tshepang

+1

['hyper_native_tls'](https://docs.rs/hyper-native-tls/0.2.0/hyper_native_tls/)上的结构似乎都不是'Debug',所以在代码中看到的行为是正确的。请确保你没有执行任何'fmt()'并用你的发现来更新这个问题。 –

回答

4

有大约箱子hyper_native_tls和​​一些未经检验的冲突。

目前,SslClient对于NativeTlsClient的实施有一个限制,其需要T: Debugcode)。该问题中的代码无法编译,因为TlsStream未实现调试,无论其参数类型如何。

首先可以考虑去掉上述约束条件。但是,在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

了修复该特定问题提供DebugTlsStream

#[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的客户端代理(编辑:it's done and fixed!)。

+0

https://github.com/sfackler/hyper-native-tls/commit/30e9d1574774aa9267ca8d4770f9af21f04edb13 – Tshepang

+0

@Tshepang干得好。 ;) –

相关问题