Rocket是一個使用Rust程式語言的Web框架,在伺服器端運行,任何人都可以用它來輕易地開發出高彈性、高可用性以及擁有型別安全特性的Web應用程式。這個系列文章將會帶您一步步了解Rocket框架的使用方法。



注意,Rocket框架和其它多個Web框架都正在被axum框架取代!如果您想學一個好用的Rust的Web框架,axum框架才是首選。

Rocket框架

Rocket這個英文單字的意思就是火箭,可能是因為框架的作者任職於SpaceX這間美國航太科技公司,所以才如此命名,還挺酷的。Rocket的目標在於提供一個快速、簡單、彈性且安全的Web框架,而且開發起來會感到愉快,因為它應用了Rust程式語言的「程序式巨集」,來自動產生那些複雜且繁瑣的程式碼。

在您繼續閱讀本系列文章之前,如果您還不熟悉Rust程式語言,請先參考筆者先前撰寫的《Rust學習之路》系列文章,並且詳讀最後一章:建立多執行緒的Web伺服器。另外還有《用「async / .await」撰寫 Rust 並發程式》一文。如此一來在閱讀本系列文章時,就能更加感到用Rocket來開發Web伺服器是有多麼地輕鬆愉快~

Rocket框架使用純Rust程式語言來打造,不需相依於第三方動態函式庫,可以很容易地移植到各個平台上運行。在性能上,它是Rust家族中雖然表現普通,但與JavaScript的Web框架相比已是快了不少。

Rocket框架有以下三大宗旨:

  1. 安全、正確、重視開發者體驗。
  2. 所有要交給開發者處理的請求(request)都會被自動型別化,不需要撰寫額外的轉換程式。且每個請求在處理時都是各別獨立的,沒有全域的狀態。
  3. 不會強制一定得使用Rocket提供的模板引擎、序列化、會話(session)等非與處理HTTP協定直接相關的套件,這些套件都是可選的。

Hello World

學習一個Web框架,跟學一個程式語言一樣,依照慣例,第一支程式都會是「Hello World」。現在,我們就來從無到有,一步步地從開新的Cargo程式專案開始,一直到能夠在網頁瀏覽器上印出Hello, world!這幾個字吧!

建立專案目錄

首先,執行以下指令,用Cargo建立出名叫hello_rocket的應用程式專案。

cargo new --bin hello_rocket

rocket-introduction

Cargo.toml設定檔中加入Rocket

接著編輯Cargo.toml設定檔,在[dependencies]區塊中加入Rocket。我們可以在crates.io上找到Rocket專案。在此以Rocket的v0.5.0版本為例,Cargo.toml設定檔的寫法如下:

[package]
name = "hello_rocket"
version = "0.1.0"
edition = "2021"

[dependencies]
rocket = "0.5.0"

撰寫程式碼

接著編輯src/main.rs原始碼,內容如下:

#[macro_use]
extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![index])
}

以上程式,我們先用#[macro_use]屬性和extern crate關鍵字來引用rocket這個crate公開出來的所有巨集。在程式第4行,我們使用了Rocket提供的程序式巨集,使得其後的第5行到第7行的index函數成為當HTTP請求的方法(method)是GET時,且請求路徑是/時的路由(routing)處理程序(handler)。

rocket函數必須搭配rocket提供的launch程序式巨集來使用,且必須回傳一個Rocket結構實體。在rocket函數中,使用rocket這個crate提供的build函數,來快速地產生出一個預設(設定值可透過環境變數或設定檔來讀入)的Rocket結構實體,接著再使用Rocket結構實體的mount方法,將index這個路由處理程序註冊在/根目錄下。也就是說,當有來自客戶端的請求是想要用HTTP的GET來請求「根目錄下的根目錄」(也就是根目錄)時,Rocket就會呼叫index這個路由處理程序來處理該請求。這個mount方法需與rocketroutes!巨集互相搭配使用。

Rocket結構實體的mount方法會取得結構實體的擁有權,並且在執行後又將Rocket結構實體回傳出來。在rocket函數的最後回傳Rocket結構實體。

編譯並執行專案

當程式撰寫完成之後,就可以用以下指令來編譯並執行專案:

cargo run

rocket-introduction

rocket-introduction

檢查成果

在網頁瀏覽器上開啟http://localhost:8000,來看看是否有出現Hello, world!這幾個字!

rocket-introduction

程式進入點

Rocket幫提供了極為簡易的方式處理程式進入點,也就是上面介紹的#[launch]屬性和rocket函數,但如果我們想要替我們的程式製作命令列介面(CLI)的話,就得自行實作傳統main函數作為程式進入點了。

要在main函數中執行Rocket,main函數可以這樣寫:

#[macro_use]
extern crate rocket;

use std::error::Error;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

#[rocket::main]
async fn main() -> Result<(), Box<dyn Error>> {
    rocket::build().mount("/", routes![index]).launch().await?;

    Ok(())
}

我們必須自行使用Rocket結構實體的launch方法來啟動Rocket伺服器。

如果我們不想要一開始就使用非同步的main函數,還可以將以上程式改寫如下:

#[macro_use]
extern crate rocket;

use std::error::Error;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

fn main() -> Result<(), Box<dyn Error>> {
    let app = rocket::build().mount("/", routes![index]);

    rocket::execute(async move { app.launch().await })?;

    Ok(())
}

呼叫rocket自帶的execute函數可以建立Rocket專用的非同步執行環境。

總結

在這一章節中,我們對Rocket這個Web框架有了粗淺的認識,也學會了從無到有,用Rocket來製作出Hello World網頁的方式。

在下一章節中,我們會更深入地探討Rocket的路由和處理請求的方式。

下一章:路由(Routing)與請求(Request)的處理