登录表单

提供 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"))
}

警告应该已经从浏览器控制台中消失了。

恭喜,您刚刚提供了第一个格式正确的网页!