ちょっと煽ってみました
誰も書いていなかったのでreqwest
について書きます。
TL;DR
HTTP系crateのデファクトスタンダードであったhyper
は0.11.0
からtokio
とfutures
を採用した複雑なAPIに変わりました。
simpleでstableなHTTP clientが使いたければhyper
の作者でもあるseanmonstar氏のreqwest
を使うのがいいです。
もちろん、reqwest
にデフォルトでついてくる機能がいらない場合や、高次元なcrateを自作したい場合はhyper
を使うのが正しいです。
現在のhyper
clientの公式exampleがこことここに載っています。
かなり単純な形でも以下のようになりますね。
extern crate futures;
extern crate hyper;
extern crate tokio_core;
use std::io::{self, Write};
use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;
let mut core = Core::new().unwrap();
let client = Client::new(&core.handle());
let uri = "http://httpbin.org/ip".parse().unwrap();
let work = client.get(uri).and_then(|res| {
println!("Response: {}", res.status());
res.body().for_each(|chunk| {
io::stdout()
.write_all(&chunk)
.map_err(From::from)
})
});
core.run(work).unwrap();
これだとGET Requestを送って結果を書き出すだけにしてはoverkillな気がします。
- extern crateが3つ必要
- この場合Asynchronousである必要がない
- リダイレクトを追うとか、Cookie、TLSなどを扱うとしたらもっと複雑になる
Reqwest
そこで、reqwest
です。
# Cargo.toml
[depenencies]
reqwest = "*"
extern crate reqwest;
use std::io;
let mut res = reqwest::get("http://httpbin.org/ip").unwrap();
res.copy_to(&mut io::stdout()).unwrap();
文字数がかなり減りました。
POST form data
let client = reqwest::Client::new();
let res = client.post("url")
.form(&[ ("foo", "bar"), ("baz", "quux") ])
.send().unwrap();
JSONで
form()
をjson()
で置き換えればできます。Serialize
をimplしていればなんでもokです。
背景
なんでこうなったの?についてはseanmonstarさん本人のブログ記事、Introducing Reqwestが詳しい。
要約すると、
- リダイレクトの処理、Cookie,コネクションプーリング、JSONペイロードなど、ほとんどのユーザがデフォルトとして望むものをまとめたライブラリが欲しかった
-
hyper
がnon-blocking I/Oを採用するので、blockingでもいいほとんどの人はこっちを使ってほしい(AsyncClient
のようなものも後からreqwest
に実装するつもり) - 同時に
hyper
のAPIががっつり変わるので、その前にstableなものを提供するという位置づけ
redditで本人がまとめていますが、他の言語と比較するとこのような感じになります
Rust | nodejs | python | Java |
---|---|---|---|
hyper | http | urllib2 | URLConnection |
reqwest | request | requests | OkHttpなど |
まとめ
初心者がhyper
でつまずかないように書きました。Event loopやfutureについて知るのも大事ですが、まずはreqwest
から入って自由にリクエストを投げまくってほしい