Rust の hyper で https アクセス

Rust の hyper で https アクセスする際に少しハマったので、解決方法を共有します。
環境は:

- rust 1.15.1
- hyper 0.10.4

## Invalid scheme for Http？？？

rust の hyper を使って https サイトにアクセスすると、`Invalid scheme for Http` というエラーが発生します。

次のようなプログラムを作成して実行すると:

```rust: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](https://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 = "*"
```

```rust: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 = "*"
```

```rust: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 = "*"
```

```rust: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
```