Rust のウェブフレームワーク「Iron」とたわむれてみた。 

## 諸注意

- Rust超初心者です。お手柔らかにお願いします。
- いつもはpythonとC++を使うことが多いですが、Rust書いてみたかったので触ってみました。

## やったこと

- とりあえずいろんなパターンのAPIエンドポイントを書いてみました。（pythonのflaskみたいにかけるのか調べてみたかった。）
- そして、それを呼ぶ簡単な呼び出しコードを、reqwestを使って書いてみました(pythonのrequestsみたいな)。

##rustの環境
```bash
$ rustc --version
rustc 1.40.0-nightly (1423bec54 2019-11-05)
```
## 感想
- Ironは本家gitのexampleが充実してないような気がしました。
- formからパラメータを貰うところができずに詰んで、とりあえず一旦終了しました。
- Rocketというフレームワークをあるのを知って、そっちの方が簡単に見えるのでそっちも試してみることにした（＜＝今ここ）
 
とりあえず、チュートリアルの段階で詰まるのが一番きついと思うので、しょうもない記事ですが誰かの役に立てばいいと思ってます。
動かしてみて動いたコードだけを貼っていきます。

もっと勉強してRust記事更新していきます。
「いいね」や「コメント」お待ちしております！！


## Cargo.toml
```rust

[package]
.....


[dependencies]
rustc-serialize="*"
router = "0.6.0"
handlebars-iron = "0.27"
staticfile = "*"
mount = "*"
handlebars = "0.20.5"
urlencoded = "0.5.0"
params="*"

[dependencies.iron]
version="0.6"
```

## src/main.rs
最初のインポートの部分

```rust
extern crate iron;
extern crate router;
extern crate staticfile;
extern crate mount;
extern crate params;
extern crate urlencoded;

use std::io::Read;
use iron::prelude::*;
use iron::status;
use router::Router;
use router::url_for;
// use staticfile::Static;
// use mount::Mount;
use std::error::Error;
use rustc_serialize::json;
use iron::headers::ContentType;
use handlebars_iron as hbs;
use hbs::{DirectorySource, HandlebarsEngine, Template};
use std::collections::HashMap;
// use std::path::Path;
// use urlencoded::UrlEncodedBody;
// use params::Params;
```

## main.rs

```rust

fn main() {

    //ルーティングは、Router クラスのオブジェクトを呼び出して、.get()メソッドなどで追加できる。
    // 引数の１つ目はエンドポイント、２つ目は呼ばれる関数、３つ目はurl_for()とかで呼ばれる名前。
    let mut router = Router::new();

    //hello world のストリングを返すエンドポイント
    router.get("/hello", hello, "hello");

    //postでストリングをもらって、 Hello "なんとか"と返すエンドポイント
    router.post("/hello_prefix", hello_prefix, "hello_prefix");

    //決められたjsonを返すエンドポイント
    router.get("/json", json, "json");

    //もらったストリングからjsonを返すエンドポイント
    router.post("/json_custom", json_custom, "json_custom");

     //template テンプレートを表示するエンドポイント
    router.get("/template_test", template_test, "template_test");

    //結局エラーが解決できなかったエンドポイント
    // router.get("/form", top_handler, "index");
    // router.post("/greet", greet_handler, "greeting");


    // 下のIron::new()のところで、Iron::new(router) としても良いけど、テンプレートを使うときはchainクラスで
    // router とHandlebarsEngineをラップしたものを渡す。
    let mut chain = Chain::new(router);

    // それぞれのテンプレートディレクトリたちをIronに教える。
    let mut hbse = HandlebarsEngine::new();
    hbse.add(Box::new(DirectorySource::new("./templates/", ".html")));
    hbse.add(Box::new(DirectorySource::new("./static/js/", ".js")));
    hbse.add(Box::new(DirectorySource::new("./static/css/", ".css")));
    if let Err(r) = hbse.reload() {
        panic!("{}", r.description());
    }


    chain.link_after(hbse);

    //ホストを決めて、Ironフレームワークを起動する。
    let host = "localhost:8080";
    println!("binding on {}", host);
    Iron::new(chain).http(host).unwrap();

    //辞書型みたいなものを作るデフォ関数
    fn create_default_data() -> HashMap<String, String> {
        HashMap::new()
    }

    //hello エンドポイントで呼ばれる関数
    fn hello(_: &mut Request) -> IronResult<Response> {
        Ok(Response::with((status::Ok, "Hello World!")))
    }

    //hello_prefix エンドポイントで呼ばれる関数
    //ちなみに.to_string()はストリングを静的から動的にする関数。
    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)))
    }

    //json エンドポイントで呼ばれる関数
    fn json(_: &mut Request) -> IronResult<Response>{
        let letter = Letter{
            title: "PPAP".to_string(),
            message: "i have a pen, i have an apple.".to_string()
        };
        let payload = json::encode(&letter).unwrap();
        Ok(Response::with((ContentType::json().0, status::Ok, payload)))
    }

    //json_custom エンドポイントで呼ばれる関数
    fn json_custom(req: &mut Request) -> IronResult<Response> {

        let mut body = String::new();
        req.body.read_to_string(&mut body).expect("failed to read line");

        let letter = Letter{
            title: body,
            message: "i got this".to_string()
        };
        let payload = json::encode(&letter).unwrap();
        Ok(Response::with((ContentType::json().0, status::Ok, payload)))

    }


    //template_test エンドポイントで呼ばれる関数
    fn template_test(_: &mut Request) -> IronResult<Response> {
        let mut resp = Response::new();
        let data = create_default_data();
        resp.set_mut(Template::new("index", data)).set_mut(status::Ok);
        Ok(resp)
        
    }

}

// htmlのフォームをpostした時にそれを受け取りたかったが、Paramsのgit(https://github.com/iron/params)に載っている
// example コード（下）を実行すると、のようなエラーが出て、解決できなかった。
// 引き続き調査中。

// fn main(){
//     let mut mount = Mount::new();

//     mount.mount("/", Static::new(Path::new("static/index.html")));
//     // mount.mount("/index.js", Static::new(Path::new("static/index.js")));

//     Iron::new(mount).http("localhost:3000").unwrap();
// }

```


## reqwest を使ってリクエストを送ってみる。
## Cargo.toml
```rust

[dependencies]
reqwest="*"
```


## main.rs
```rust
extern crate reqwest;
use std::io;
use std::collections::HashMap;



fn main() {

    //クライアントオブジェクトを作る。
    let client = reqwest::Client::new();

    //#####################################################################
    // hello エンドポイントにリクエスト送信してみる。
    let mut resp = reqwest::get("http://localhost:8080/hello").unwrap();
    if resp.status().is_success() {
        println!("success!");
    } else if resp.status().is_server_error() {
        println!("server error!");
    } else {
        println!("Something else happened. Status: {:?}", resp.status());
    }

    resp.copy_to(&mut io::stdout()).unwrap();
    println!("\n");


    //#####################################################################
    // hello_prefix エンドポイントにリクエスト送信してみる。
    let mut res = client.post("http://localhost:8080/hello_prefix")
        .body("waiwaiwaiwai".to_string())
        .send().unwrap();

    if res.status().is_success() {
        println!("success!");
    } else if res.status().is_server_error() {
        println!("server error!");
    } else {
        println!("Something else happened. Status: {:?}", res.status());
    }

    res.copy_to(&mut io::stdout()).unwrap();
    println!("\n");


    //#####################################################################
    // json_custom エンドポイントにリクエスト送信してみる。
    let mut map = HashMap::new();
    map.insert("lang", "rust");
    map.insert("body", "json");
    let mut res = client.post("http://localhost:8080/json_custom")
        .json(&map)
        .send().unwrap();

    if res.status().is_success() {
        println!("success!");
    } else if res.status().is_server_error() {
        println!("server error!");
    } else {
        println!("Something else happened. Status: {:?}", res.status());
    }

    res.copy_to(&mut io::stdout()).unwrap();
    println!("\n");
    
}
```