Rust の hyper で https アクセスする際に少しハマったので、解決方法を共有します。
環境は:
- rust 1.15.1
- hyper 0.10.4
Invalid scheme for Http???
rust の hyper を使って https サイトにアクセスすると、Invalid scheme for Http
というエラーが発生します。
次のようなプログラムを作成して実行すると:
main.rs
extern crate hyper;
use hyper::Client;
fn main() {
let client = Client::new();
let resp = client.get("https://www.google.co.jp/").send().unwrap();
println!("status={}", resp.status);
}
コンソールには次のようなエラーが:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Io(Error { repr: Custom(Custom { kind: InvalidInput, error: StringError("Invalid scheme for Http") }) })', /Users/rustbuild/src/rust-buildbot/slave/stable-dist-rustc-mac/build/src/libcore/result.rs:837
note: Run with `RUST_BACKTRACE=1` for a backtrace.
http が無効なスキーマ?https でアクセスしているのに http?とエラーの意味が全くわかりません。
hyper の tls ライブラリ
hyper は好みの tls ライブラリと組み合わせて使うスタイルのようで、次の tls ライブラリが使えます。
-
native_tls
-
rustls
-
openssl
crates.io では native_tls が一番人気、rustls が二番人気のようです。
openssl とリンクしてしまうと Windows では動作しないので、openssl は敬遠されているような印象。
hyper + native_tls の使い方
一番人気の native_tls の使い方です。
Cargo.toml
[package]
name = "native_tls"
version = "0.1.0"
authors = ["Example <example@example.jp>"]
[dependencies]
hyper = "*"
hyper-native-tls = "*"
main.rs
extern crate hyper;
extern crate hyper_native_tls;
use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
fn main() {
let tls = NativeTlsClient::new().unwrap();
let connector = HttpsConnector::new(tls);
let client = Client::with_connector(connector);
let resp = client.get("https://www.google.co.jp/").send().unwrap();
println!("status={}", resp.status);
}
$ cargo run
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/native_tls`
status=200 OK
hyper + rustls の使い方
二番人気の native_tls の使い方です。
Cargo.toml
[package]
name = "rustls"
version = "0.1.0"
authors = ["Example <example@example.jp>"]
[dependencies]
hyper = "*"
hyper-rustls = "*"
main.rs
extern crate hyper;
extern crate hyper_rustls;
use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_rustls::TlsClient;
fn main() {
let tls = TlsClient::new();
let connector = HttpsConnector::new(tls);
let client = Client::with_connector(connector);
let resp = client.get("https://www.google.co.jp/").send().unwrap();
println!("status={}", resp.status);
}
$ cargo run
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/rustls`
status=200 OK
hyper + openssl の使い方
三番人気の openssl の使い方です。
Cargo.toml
[package]
name = "openssl"
version = "0.1.0"
authors = ["Example <example@example.jp>"]
[dependencies]
hyper = "*"
hyper-openssl = "*"
main.rs
extern crate hyper;
extern crate hyper_openssl;
use hyper::Client;
use hyper::net::HttpsConnector;
use hyper_openssl::OpensslClient;
fn main() {
let ssl = OpensslClient::new().unwrap();
let connector = HttpsConnector::new(ssl);
let client = Client::with_connector(connector);
let resp = client.get("https://www.google.co.jp/").send().unwrap();
println!("status={}", resp.status);
}
$ cargo run
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/openssl`
status=200 OK