変更
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用のレスポンスとして読み込まれる。
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に変更する。
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(折りたたんでいます)
# 省略
[dependencies]
tide = "0.13"
# htmlの生成に使用
tinytemplate = "1.1"
serde = "1.0"
[dependencies.async-std]
version = "1.6"
features = ["attributes"]
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)
}
最後に
Web周りの知識がほとんどないので、間違っているところも多いと思います。
間違っている部分があれば、ご連絡いただけると幸いです。
参考文献
curl コマンド 使い方メモ
MDN Web Docs MIME タイプ (IANA メディアタイプ)
Don't Repeat Yourself tide 0.7.0 を試してみる
DOCS.RS tide