原本預計要介紹router的細部設定和middleware,但我決定改從專案的第一個 API 開始。
選擇用health check當作開始是因為它足夠簡單,通常我們需要一些方法來確保應用程式正常運行,例如定期對網頁應用進行健康檢查,今天要做的事情是:
/health_check
的API。所以我們把昨天hello world的範例改一下
use axum::{http::StatusCode, routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/health_check", get(health_check));
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
pub async fn health_check() -> StatusCode {
StatusCode::OK
}
存檔後在terminal中使用cargo run
指令,等待編譯過後程式運行
❯ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.14s
Running `target/debug/zero_to_production`
這時候在測試 http://localhost:3000/health_check 理論上就可以收到200的回覆了。
跟昨天的程式碼相比,可以看到一開始的參考多了http::StatusCode
,這是因為health_check
處理函數的回應會使用到StatusCode
這個 Enum,我們把焦點放到health_check
方法上:
pub async fn health_check() -> StatusCode {
StatusCode::OK
}
這是一個非常簡單的處理函數,只需回應StatusCode::OK
,這代表 HTTP 200 OK。當我們訪問/health_check
時,只需確認服務正在運行,因此這樣的回應就足夠了。
在Rust中,Enum是一個常見的概念,就像其他語言中的Enum一樣,它用於列舉一組可能的值,C#中也有這樣一個Enum用來表示Http Status的各種不同狀態。但是Rust的Enum與其他語言有所不同,因為在Rust中,Enum的每個項目都可以具備不同的資料型態。更多關於Enum的內容將在後續介紹錯誤處理的章節中進行深入討論。
一個Handler的回傳型別必須實現IntoResponse
trait,這個trait定義了如何將值轉換為HTTP回應。trait是rust中的一種抽象概念,這邊先不仔細探究,先把它當成C#中的interface
即可。trait定義的了一組方法,通常情況下只定義了方法簽章而不包含實做細節,以下是IntoResponse
的定義:
pub trait IntoResponse {
// Required method
fn into_response(self) -> Response<UnsyncBoxBody<Bytes, Error>>;
}
實作了IntoResponse
的型別就具備了一個方法。在上述定義中,self
表示這是一個關聯方法,也就是實作細節可能與型別本身的資料有關。該方法的返回值是一個Response
結構,其他細節在此先忽略。通常情況下,實作這個 trait並沒有看起來的那麼複雜,因為Axum已經為一些常見的Response型別提供了實作,所以在實際使用時,只需定義如何轉換為內建的 Response 即可。
如同上面的程式碼,我們已經知道StatusCode
有實做IntoResponse
:
//// 定義自己的Response
struct MyResponse(String);
//// 為MyResponse實做IntoResponse trait
impl IntoResponse for MyResponse {
fn into_response(self) -> axum::response::Response {
if self.0 == "Hello, World!" {
//// 這邊直接調用StatusCode的into_response即可
StatusCode::OK.into_response()
} else {
StatusCode::BAD_REQUEST.into_response()
}
}
}
Axum中已經為多種型別實作了IntoResponse
,包括String
、Vec<u8>
、Json<T>
、Html<&'static str>
等。此外,Handler也可以直接回傳實作了IntoResponse
的trait物件,還可以使用tuple包裝多個回應值,或者使用Rust常用於處裡錯誤的Result
。更多細節可以參考文件,至於詳細使用方式就留到後面完成更多功能的時候細細體會吧!
今天通過health_check
接觸到了第一個trait,並說明如何簡單的實作IntoResponse
,不過在rust中trait的概念還是太抽象了,所以明天在重新看一次這個流程深入了解