用 Rust 構(gòu)建 API 系列教程:第一部分
今天給大家?guī)硪粋€系列:使用 Rust 構(gòu)建 API。
在這個系列教程中,我將向你展示如何在 Rust 中構(gòu)建一個簡單的 API。由于我自己也是 Rust 的初學(xué)者,還有很多東西我需要學(xué)習(xí)。所以其中有不對的地方,歡迎批評指正。
這個系列一共分三部分。
第一部分將介紹基礎(chǔ)知識,我將解釋如何設(shè)置項目,并創(chuàng)建一個端點,返回一個 Hello World!信息。
在第二部分中,我將把 API 連接到 MongoDB,并添加兩個端點來從數(shù)據(jù)庫中創(chuàng)建和檢索文檔。
在第三部分也是最后一部分,我將向你展示如何構(gòu)建身份驗證中間件來保護其中一個端點。
Web 框架
我決定使用 tide[1] 作為 Web 框架。雖然比不上 actix[2] 流行(目前最流行的),但是我對 tide 更有感覺,在我看來它更簡單。
項目設(shè)置
讓我們開始設(shè)置這個項目。
首先,確保你已經(jīng)安裝了 Rust 和 Cargo[3]。
鍵入以下命令,使用 cargo 創(chuàng)建一個新項目:
cargo new rust-api-example-part-1
開始準(zhǔn)備些代碼,選擇一個你最喜歡的編輯器開始。
如果你使用 VS Code,建議你安裝以下擴展:
rust-analyzer,之前有介紹過,這個比官方的更好用; TOML Language Support,支持 TOML 文件格式語法高亮,支持 TOML 格式化,還計劃支持 JSON 等格式和 TOML 轉(zhuǎn)換;裝這個插件,是因為 Cargo 的配置文件是這種格式。這也是我比較喜歡的格式,比太喜歡 YAML。
安裝依賴項
在開始編碼之前,我們需要安裝依賴項。在這個階段,我們只需要其中的三個:tide, async-std 和 serde。
正如我前面解釋的,tide 是我們用來構(gòu)建 API 的 Web 框架。
async-std 是異步運行時。默認情況下 Rust 不提供異步運行時,所以我們需要安裝一個。目前有兩種流行的選擇:tokio 和 async-std。
這有點煩人,因為這意味著你需要確保將在項目中使用的所有異步庫都必須與你選擇的異步運行時兼容。
tide 要求我們使用 async-std,所以我們將安裝這個運行時。
serde 是一個序列化和反序列化數(shù)據(jù)的框架(例如將 JSON 對象轉(zhuǎn)換為 Rust 結(jié)構(gòu))。
打開 Cargo.toml 文件,并在 [dependencies] 下添加以下內(nèi)容:
tide = "0.16"
async-std = { version = "1", features = ["attributes"] }
serde = { version = "1.0", features = ["derive"] }
你可以像我為 async-std 所做的那樣指定額外的特性,這里,我們將需要 attributes 特性。
確保它能運行
默認情況下,在使用 cargo 創(chuàng)建項目時,應(yīng)該有一個包含示例函數(shù)的默認 src/main.rs 文件。確保它能運行:
cargo run
第一次運行會比較慢。
在最后應(yīng)該會打印:Hello,world!
接下來就是正式寫代碼的時候了。
開始編碼
在 src/main.rs 文件中,添加如下代碼:
#[async_std::main]
async fn main() -> tide::Result<()> {
let app = tide::new();
app.listen("127.0.0.1:8080").await?;
return Ok(());
}
main 現(xiàn)在是異步的,因為我們在前面添加了 async 關(guān)鍵字。為了能正確工作,我們需要添加一個運行時,這正是 #[async_std::main] 所做的。它是一個 "attribute" 宏,只是將我們的 main 函數(shù)包裝在一個異步運行時中。
這個函數(shù)返回 tide::Result<()>,這意味著它要么什么也不返回 (Ok(())) ,要么返回一個 Tide 錯誤。
在函數(shù)內(nèi)部,我們創(chuàng)建一個新的 Tide 實例,然后調(diào)用函數(shù) listen 啟動端口 8080 上的本地服務(wù)器。
如果你現(xiàn)在嘗試訪問 API,你會得到一個 404,因為我們還沒有定義任何路由。
讓我們創(chuàng)建第一個控制器(controller),在 src/main.rs 中的 main 函數(shù)上面添加以下內(nèi)容:
use tide::Request;
#[derive(Clone, Debug)]
struct State {}
async fn hello(_req: Request<State>) -> tide::Result {
return Ok("Hello world!".into());
}
hello 控制器是異步的,只有一個參數(shù)。因為我們實際上并沒有使用這個參數(shù),所以我們可以在每個約定中添加一個前導(dǎo)下劃線。_req 參數(shù)的類型是 Request (從 tide 導(dǎo)入) ,它需要一個 State ,這就是為什么我定義了一個空的 State 結(jié)構(gòu)體。
State 結(jié)構(gòu)體需要實現(xiàn) Clone 特性(trait),因此我們使用從 serde 派生(derive)的宏(marco)來實現(xiàn)它。
控制器返回類型得是 tide::Result。
至于實現(xiàn),我們只是返回 &str 類型值,并使用 .into() 函數(shù)將其轉(zhuǎn)換為 tide::Result 。
這就是我們的控制器。現(xiàn)在我們需要對 main 函數(shù)做一些修改。改為下面的代碼:
#[async_std::main]
async fn main() -> tide::Result<()> {
let mut app = tide::with_state(State {});
app.at("/hello").get(hello);
app.listen("127.0.0.1:8080").await?;
return Ok(());
}
我已經(jīng)修改了我們應(yīng)用程序的初始化,使其通過一個空 State。稍后當(dāng)我們需要傳遞數(shù)據(jù)庫連接時,這將非常有用。
然后我添加了端點 GET /hello。
現(xiàn)在,如果你運行這個應(yīng)用程序,然后在瀏覽器訪問 http://localhost:8080/hello,你應(yīng)該能看到 Hello world!。

結(jié)尾
這就是該系列的第一部分,希望它對你有所幫助。
關(guān)于 Tide,可以訪問倉庫首頁了解更多詳細內(nèi)容。
參考資料
tide: https://github.com/http-rs/tide
[2]actix: https://github.com/actix/actix
[3]Rust 和 Cargo: https://www.rust-lang.org/tools/install
推薦閱讀
覺得不錯,點個贊吧
掃碼關(guān)注「Rust編程指北」
