域名 AXUM.RS 将于 2025 年 10 月到期。我们无意再对其进行续费,如果你有意接续这个域名,请与我们取得联系。
  • AXUM.RS 现仅需人民币 3000 元(大写:叁仟元整。接受适度议价
  • 按照行业规则,AXUM.RS 到期后,大概率会进入长时间的赎回期,该期间内,如果你想拥有该域名,将要付出高额的费用
  • 我们已启用 AXUM.EU.ORG 域名,并将持续运营
  • 仅接受微信或支付宝交易
如果你对 AXUM.RS 有兴趣,请和我们进行联系:

项目初始化及配置

创建项目

本专题包含两个项目:用于开发后端的 Rust 项目和用于开发前端的 React 项目。

首先,我们创建本专题的根目录:

进入到该目录后,分别创建两个项目:

# 创建后端项目
cargo new domain-distribution

# 创建前端项目
yarn create vite domain-distribution-ui  --template react-ts

最终的目录结构是:

domain-distribution
├── domain-distribution
└── domain-distribution-ui

初始化后端项目

抛开前端不看,我们先初始话后端项目。

项目依赖

很明显,我们第一步就是把所需的依赖加进来:

[dependencies]
tokio = { version = "1", features = ["full"] }
axum = { version = "0.7" }
serde = { version = "1", features = ["derive"] }
chrono = { version = "0.4", features = ["serde"] }
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "chrono"] }
bcrypt = "0.16"
config = { version = "0.14", features = ["toml"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
reqwest = { version = "0.12", features = ["json"] }
serde_json = "1"
validator = { version = "0.19", features = ["derive"] }
tower-http = { version = "0.6", features = ["cors"] }
xid = "1"
anyhow = "1"
rand = "0.8"
lettre = { version = "0.11", features = ["tokio1-native-tls"] }
utf8_slice = "1"

使用 lib.rs

创建一个空的 src/lib.rs 文件。我们还是使用 lib 方式来组织代码。

配置

创建 src/config.rs 文件,并在 src/lib.rs 加上 pub mod config;

该文件的内容如下:

注释很详细了,不再进行特别说明了。

封装错误和项目专属Result<T>

创建 src/err.rs,并将其添加到 src/lib.rs 中。

use axum::response::IntoResponse;

#[derive(Debug)]
pub struct Error(anyhow::Error);

impl Error {
    pub fn new(msg: &str) -> Self {
        Self(anyhow::anyhow!("{}", msg))
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self.0)
    }
}

impl<E> From<E> for Error
where
    E: Into<anyhow::Error>,
{
    fn from(e: E) -> Self {
        Self(e.into())
    }
}

impl IntoResponse for Error {
    fn into_response(self) -> axum::response::Response {
        self.0.to_string().into_response()
    }
}

我们使用 anyhow 来简化错误处理。

本章最终的 lib.rs

pub mod config;
mod err;

pub use err::Error;

pub type Result<T> = std::result::Result<T, crate::Error>;

说明:本章代码只是当前状态,后续章节可能会对配置、数据库定义、模型定义、结构体定义、函数定义等进行修改,请留意。

要查看完整内容,请先登录