[rust] zero2prod 實做紀錄 03 - Health Check

Shubham Dhage

zero2prod是一個webapi專案,書上建議從actix-web這個框架著手。在rust的世界裡有很多的web framework,而actix只是其中一種,身為C#入門的工程師,這點真的很不習慣。.Net的世界裡大家基本上就是follow微軟的腳步,有一個老大哥建議程式要怎麼寫,尤其.Net core發布後大行其道。rust除了actix-web以外也有很多其他框架,不過這邊就不詳談了。

actix_web::main

把cargo專案設置好後,先直接把main.rs的部份換掉,書上用的actix-web是4.0.0版的,在這邊我直接換成4.3.0

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(||{
        App::new()
        .route("/health_check", web::get().to(health_check))
    })
    .bind(("127.0.0.1",8080))?
    .run()
    .await
}

async fn health_check(_req: HttpRequest) -> impl Responder{
    HttpResponse::Ok()
}

先從內部往外看,||{}這個看起來很詭異的東西就是一個lambda表達式,翻譯成C#就是()=>{},是一個不接受任何參數的方法,並且回傳App這個結構的實例。我們可以在App上面設定route,第一個就是範例中給的透過.route()來設定路由,將health_check綁定成get。另一種則是透過.service()

// App instance
App::new()
.service(health_check)

// health_check handler
#[get("/")]
async fn health_check(_req: HttpRequest) -> impl Responder{
    HttpResponse::Ok()
}

看一下health_check的回傳是Responder,在rust中使用的是trait,類似於其他語言中的interface,表示要回傳值需要實作Responder trait。另外一個可以介紹的是用於設定handler的.to():

pub fn to<F, Args>(handler: F) -> Route
where
    F: Handler<Args>,
    Args: FromRequest + 'static,
    F::Output: Responder + 'static,

這邊只是想提到rust的生命週期,'static表示這個變數生命週期在整個應用程式的執行期間,但在這邊其實有細微的不同,可以參考這一篇介紹,簡單來說這邊指的是Args這個型別生命週期在一次request作用內都需要是可用的。 App instance被用來建構HttpServer後,後面的方法鏈就可以來建構middelware。 最後看到main被掛上#[actix_web::main]後就需要回傳Result型別,這是一個enum,在rust以及函數式語言中,都會顯式表達方法會回傳一個結果,或者是執行失敗。因為將方法改為非同步後,就需要考慮例外狀況,而Result裡面的()有人稱為unit,表示沒有結果,因為方法內容執行成功後不需要特別回傳結果,所以這邊的回傳值就是Result<()>

小結

終於寫完第一篇,總覺的因為對rust不熟,某些認知應該是錯的,就留到以後慢慢改學習改進吧!