Help us understand the problem. What is going on with this article?

[Rust]tide0.13.0でHTMLを表示するサンプル

変更

2020/6/8

tide: 0.10.0にて、静的htmlをレスポンスとして返すメソッドが追加されました。
これに伴い、記事の内容を

  • 静的htmlをレスポンスとして返すサンプル
  • htmlテンプレートを使ってレスポンスを作成するサンプル

に変更します。

注意

tideは2020/6/8時点で開発中です。
プロダクトでの使用はおすすめしません。
tidev0.13.0で公式リポジトリから注意文が消えました。

環境

  • OS: Windows10 2004
  • Rust:
    • Toolchain: stable-x86_64-pc-windows-msvc unchanged
    • rustup: 1.22.1
    • rustc: 1.45.2
    • cargo: 1.45.1
  • tide: 0.13.0

サンプル

静的htmlファイル

静的なhtmlファイルはBody::from_file("*.html")でhtml用のレスポンスとして読み込まれる。

static_html
let mut res = tide::Response::new(StatusCode::Ok);
let body = Body::from_file("filename.html").await?;
res.set_body(body);

htmlテンプレートエンジン

(大体のhtmlテンプレートエンジンで文字列型を返すと思うので)
レスポンスのボディーを Body::from_string() で作って、メディアタイプをhtmlに変更する。

template
let mut res = tide::Response::new(StatusCode::Ok);

// generate_html()は自作の関数です。
// htmlテンプレートエンジンからhtmlをString型で返す関数として読み替えてください。
let html_body = generate_html("param").unwrap();
let body = Body::from_string(html_body);
res.set_body(body);

// Body::from_string()だと、レスポンスがプレーンテキストとして認識されるので、
// mime::HTMLを設定しなおさなければならない。
res.set_content_type(mime::HTML);

メディアタイプについては、以下を参照
https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types

コード

cargo.toml(折りたたんでいます)
cargo.toml
# 省略

[dependencies]
tide = "0.13"

# htmlの生成に使用
tinytemplate = "1.1"
serde = "1.0"

[dependencies.async-std]
version = "1.6"
features = ["attributes"]

main.rs(折りたたんでいます)
main.rs
use tide::http::{mime, StatusCode};
use tide::Body;

#[async_std::main]
async fn main() -> Result<(), std::io::Error> {
    let mut app = tide::new();

    app.at("/").get(hello);
    app.at("/hello_html").get(hello_html);
    app.at("/html_template/:name").get(hello_html_from_template);
    app.at("/*").get(not_found);
    app.listen("127.0.0.1:8080").await?;
    Ok(())
}

async fn hello(_req: tide::Request<()>) -> Result<String, tide::Error> {
    Ok("hello".to_string())
}

async fn hello_html(_req: tide::Request<()>) -> Result<tide::Response, tide::Error> {
    let mut res = tide::Response::new(StatusCode::Ok);

    // hello.htmlを作成してプロジェクトルートにおいてください。
    // githubからクローンしている場合には、そのままで問題ありません。
    let body = Body::from_file("hello.html").await?;
    res.set_body(body);
    Ok(res)
}

async fn not_found(_req: tide::Request<()>) -> Result<tide::Response, tide::Error> {
    let mut res = tide::Response::new(StatusCode::NotFound);
    let body = Body::from_string("Not Found".to_string());
    res.set_body(body);
    Ok(res)
}

async fn hello_html_from_template(req: tide::Request<()>) -> Result<tide::Response, tide::Error> {
    let mut res = tide::Response::new(StatusCode::Ok);

    // 'tide::Server.at(*/:name)'の形でルーティングしている場合に、:nameの値を取得する
    let name = req.param::<String>("name")?;

    let html_body = generate_html(name).unwrap();
    let body = Body::from_string(html_body);
    res.set_body(body);
    res.set_content_type(mime::HTML);
    Ok(res)
}


// htmlをテンプレートエンジンで生成します。
use serde::Serialize;
use std::error::Error;
use tinytemplate::TinyTemplate;

#[derive(Serialize)]
struct Context {
    name: String,
}

const HTML_TEMPLATE: &'static str = "<!DOCTYPE html>
    <html lang=\"en\">
        <head>
            <meta charset=\"UTF-8\">
            <title>Hello!</title>
        </head>
        <body>
            <h1>Hello!</h1>
            <p>Hi {name} from Rust</p>
        </body>
    </html>";

pub fn generate_html(name: String) -> Result<String, Box<dyn Error>> {
    let mut template = TinyTemplate::new();
    template.add_template("hello_rust_template", HTML_TEMPLATE)?;

    let context = Context { name };

    let rendered = template.render("hello_rust_template", &context)?;
    Ok(rendered)
}

Githubリポジトリ

最後に

Web周りの知識がほとんどないので、間違っているところも多いと思います。
間違っている部分があれば、ご連絡いただけると幸いです。

参考文献

curl コマンド 使い方メモ
MDN Web Docs MIME タイプ (IANA メディアタイプ)
Don't Repeat Yourself tide 0.7.0 を試してみる
DOCS.RS tide

yusuke-ota
ミーハーなので、話題のテクノロジーにすぐ飛びつきます。(習得できるとは言ってない) はまりポイントで時間を溶かすのが得意です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした