LoginSignup
5
2

More than 3 years have passed since last update.

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

Posted at

諸注意

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

やったこと

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

rustの環境

$ rustc --version
rustc 1.40.0-nightly (1423bec54 2019-11-05)

感想

  • Ironは本家gitのexampleが充実してないような気がしました。
  • formからパラメータを貰うところができずに詰んで、とりあえず一旦終了しました。
  • Rocketというフレームワークをあるのを知って、そっちの方が簡単に見えるのでそっちも試してみることにした(<=今ここ)

とりあえず、チュートリアルの段階で詰まるのが一番きついと思うので、しょうもない記事ですが誰かの役に立てばいいと思ってます。
動かしてみて動いたコードだけを貼っていきます。

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

Cargo.toml


[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

最初のインポートの部分

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


fn main() {

    //ルーティングは、Router クラスのオブジェクトを呼び出して、.get()メソッドなどで追加できる。
    // 引数の1つ目はエンドポイント、2つ目は呼ばれる関数、3つ目は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


[dependencies]
reqwest="*"

main.rs

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");

}
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2