登录表单
提供 HTML 页面
到目前为止,我们已经避开了浏览器和网页的复杂性——这有助于我们减少在学习初期需要学习的新概念数量。
现在,我们已经积累了足够的专业知识来完成这一步——我们将处理 HTML 页面和登录表单的有效负载提交。
让我们从基础开始: 如何从 API 返回 HTML 页面? 我们可以从添加一个虚拟主页端点开始。
//! src/routes.rs
// [...]
mod home;
pub use home::*;
//! src/routes/home.rs
use actix_web::HttpResponse;
pub async fn home() -> HttpResponse {
HttpResponse::Ok().finish()
}
//! src/startup.rs
use crate::routes::home;
// [...]
pub fn run(
// [...]
) -> Result</*[...]*/> {
// [...]
let server = HttpServer::new(move || {
App::new()
// [...]
.route("/", web::get().to(home))
// [...]
})
// [...]
}
这里没什么可看的——我们只是返回了一个 200 OK 状态码,没有正文。
让我们添加一个非常简单的 HTML 落地页:
<!-- src/routes/home/home.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
</head>
<body>
<p>Welcome to our newsletter!</p>
</body>
</html>
我们希望读取此文件并将其作为 GET / 端点的主体返回。
我们可以使用 include_str!, 这是 Rust 标准库中的一个宏: 它读取给定路径下的文件并将其内容作为 &'static str 返回。
这是可能的,因为 include_str! 在编译时运行 - 文件内容存储为应用程序二进制文件的一部分,因此确保指向其内容的指针 (&str) 保持有效无限期 ('static)
//! src/routes/home.rs
// [...]
pub async fn home() -> HttpResponse {
HttpResponse::Ok().body(include_str!("home/home.html"))
}
如果你使用 cargo run 启动你的应用程序,并在浏览器中访问 http://localhost:8000,你应该会看到“欢迎阅读我们的新闻通讯!”的消息。
不过,浏览器并不完全满意——如果你打开浏览器的 console ,你应该会看到一条警告。
在 Firefox 93.0 上:
HTML 文档的字符编码未声明。 如果文档包含 US-ASCII 范围之外的字符,则在某些浏览器配置下,文档将呈现乱码。 页面的字符编码必须在文档或传输协议中声明。
换句话说,浏览器已经推断出我们返回的是 HTML 内容,但它 更希望得到明确的提示。
我们有两个选择:
- 在文档中添加一个特殊的 HTML 元标记;
- 设置 Content-Type HTTP 标头(“传输协议”)。
最好两者兼顾。
将信息嵌入文档内部对浏览器和机器人爬虫(例如 Googlebot)来说效果很好,而 Content-Type HTTP 标头不仅能被浏览器识别,还能被所有 HTTP 客户端识别。
返回 HTML 页面时,内容类型应设置为 text/html; charset=utf-8。
让我们添加它:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- This is equivalent to a HTTP header -->
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Home</title>
</head>
<!-- [...] -->
</html>
//! src/routes/home.rs
// [...]
pub async fn home() -> HttpResponse {
HttpResponse::Ok()
.content_type(ContentType::html())
.body(include_str!("home/home.html"))
}
警告应该已经从浏览器控制台中消失了。
恭喜,您刚刚提供了第一个格式正确的网页!