Rustに入門してIron触ってみた。

この記事は[WHITEPLUS Advent Calendar](http://qiita.com/advent-calendar/2017/whiteplus "") 2017 16日目になります。


株式会社ホワイトプラス、エンジニアインターンの @shamisonn です。

業務ではPython,Goを書き、
趣味ではJava,Javascriptを書いているRust初学者が、
RustのWebフレームワークIronを使ってみたログのような記事です。

エンジニアの方々と雑談していたら興味が湧いたのでRust入門してみます :)

# 目標

Rust言語初心者が、
RustのWebフレームワークであるironを用いて
Get/Postのhttpリクエストを行えるような
サーバーを立ててみる。

# チュートリアル

Rustを始めるにあたって以下を読みました。

- [プログラミング言語Rust](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/)

丁寧に翻訳されていて、
英語に疎い私でもサクサクと読むことができました :D

## 環境構築

私の環境はMacなのでbrewを使いました。

```
$ brew install rust
$ rustc --version
rustc 1.22.1
```

Rustをインストールすると一緒に
パッケージマネージャである`cargo`も一緒に入ってくれました。

```
$ cargo --version
cargo 0.22.0
```

新規プロジェクト開始していきます。

```
$ cargo new iron_learning --bin
```

`--bin`をつけない場合、
ライブラリ作成用のプロジェクトが生成されます。

中身は以下。

```
$ cd iron_learning
$ tree -a
.
├── .git
│   └──(略)
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs
```

パッケージのデフォルトの設定は`Cargo.toml`にかかれています。

```
$ cat Cargo.toml
[package]
name = "iron_learning"
version = "0.1.0"
authors = ["shamisonn <hoge@mail.com>"]

[dependencies]
```

`authors`には自動的にgitconfigに登録してる情報が入るようです。
モダンですね。

## Webフレームワークironのインストール

iron とはRustで書かれた拡張性と並行性に焦点をあてたフレームワークだそうです。

- github: https://github.com/iron/iron

執筆時現在、RustのWebフレームワークの中でも多くのgithubのスターを
獲得しているようですね。（4671個）

インストールには`Cargo.toml`に追記を行います。

```toml
[package]
name = "iron_learning"
version = "0.1.0"
authors = ["shamisonn <hoge@mail.com>"]

[dependencies]
iron = "0.6.0" # <- 追記
```

終わりです！
実行する際には

```
$ cargo run
```

とすれば勝手にクレート（いわゆるライブラリ）を取ってきて実行してくれます。
簡単ですね。

# ironでのhello world

```rust
extern crate iron;

use iron::prelude::*;
use iron::status;

fn main() {
    Iron::new(|_: &mut Request| {
        Ok(Response::with((status::Ok, "Hello World!")))
    }).http("localhost:3000").unwrap();
}
```
公式のexampleにて紹介されていた`hello world`です。
`localhost:3000`にアクセスすると`Hello World!`が返ってきてくれます。

詳しい構造に関してはこちらが参考になりました。
- [RustでWebプログラミング No.1 ~ IronのインストールとHello World~ - Let's write β](http://poketo7878-dev.hatenablog.com/entry/2016/09/22/202953)

# ルーティング

ironのミドルウェアをとして`router`が用意されています。
`[dependencies]`に対して

```
router = "0.6.0"
```

と追記します。

これを用いて先程のhello worldを書き換えてみます。

```rust
extern crate iron;
extern crate router;

use iron::prelude::*;
use iron::status;
use router::Router;

fn main() {
    let mut router = Router::new();
    router.get("/", hello, "helloworld");

    Iron::new(router).http("localhost:3000").unwrap();

    fn hello(_: &mut Request) -> IronResult<Response> {
        Ok(Response::with((status::Ok, "Hello World!")))
    }
}
```

余談ですがrouterの設定部分に別の文法が用意されているようです。
例えば以下のように設定されている場合

```rust
let mut router = Router::new();
router.get("/", hello, "helloworld");
router.get("/hoge", fuga, "piyo");
```

```rust
let router = router!(helloworld: get "/" => hello,
                     piyo: get "/hoge" => fuga);
```

上記は等価のようです。

# 簡単にGet/Postをしてみる。

routerに対しては、

```
router.get
router.post
router.put
router.delete
```

などのMethodが用意されているようです

したがって以下のように実装しました。

```rust
extern crate iron;
extern crate router;

use std::io::Read;

use iron::prelude::*;
use iron::status;
use router::Router;

fn main() {
    let mut router = Router::new();
    router.get("/", hello, "hello");
    router.post("/", hello_prefix, "hello_prefix");

    Iron::new(router).http("localhost:3000").unwrap();

    fn hello(_: &mut Request) -> IronResult<Response> {
        Ok(Response::with((status::Ok, "Hello World!")))
    }

    fn hello_prefix(req: &mut Request) -> IronResult<Response> {
        let mut body = String::new();
        req.body.read_to_string(&mut body)
            .expect("Failed to read line");

        let res = "Hello ".to_string() + &body + &"!".to_string();
        Ok(Response::with((status::Ok, res)))
    }
}
```

実行結果は以下

```
$ curl http://localhost:3000/
Hello World!

$ curl -X POST http://localhost:3000/ -d 'Rust'
Hello Rust!
```

できました〜。

# まとめ

非常に親切なドキュメントとパッケージ管理システムのおかげで、
サクッと実装することができました。（といっても非常に簡単なことしかやっていませんが）

Rustの特徴的な部分に関して紹介するまでに至れず、ちょっと残念な気持ちもありますが、
これをきっかけに新しいことにどんどんチャレンジしてみたいと思います。
もっとRustをやりたい！

# 参考にしたもの
- [プログラミング言語Rust](https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/)
- [iron/examples at master · iron/iron](https://github.com/iron/iron/tree/master/examples)
- [router/examples at master · iron/router](https://github.com/iron/router/tree/master/examples)
- [RustでWebプログラミング No.1 ~ IronのインストールとHello World~ - Let's write β](http://poketo7878-dev.hatenablog.com/entry/2016/09/22/202953)
- [Rustの文字列操作 - Qiita](https://qiita.com/aflc/items/f2be832f9612064b12c6)
- [Rustのクエスチョンマーク - 簡潔なQ](http://qnighy.hatenablog.com/entry/2017/03/14/130743)
- [IronでWebサービスを作るために必要だったもの - Qiita](https://qiita.com/nacika_ins/items/fa1a8a72d78398dc4661)
- [Rust の色々な Struct の返し方 - Qiita](https://qiita.com/propella/items/784daa12e6f6faef854e)