2017-01-12 113 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幹得好。 ;) –

相關問題