事前工作

安裝 rustup

# 也可以使用官方推薦的 
# ~$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 見:https://www.rust-lang.org/zh-TW/tools/install
~$ sudo snap install rustup
~$ rustup default nightly

開新專案

專案設定

~$ cargo new rocket-start
~$ cd rocket-start
~$ vim Cargo.toml

# 在專案的 Cargo.toml 中的 dependencies 加入 rocket 的相依
[dependencies]
rocket = "0.4.5"

Hello World

// src/main.rs

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;

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

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}

接著嘗試運行

~$ cargo run
🔧  Configured for development.
    => address: localhost
    => port: 8000
    => log: normal
    => workers: [logical cores * 2]
    => secret key: generated
    => limits: forms = 32KiB
    => keep-alive: 5s
    => tls: disabled
🛰  Mounting '/':
    => GET / (index)
🚀  Rocket has launched from http://localhost:8000

接著就可以透過瀏覽器訪問 http://localhost:8000 能夠成功顯示Hello, world!字樣就代表已經成功了。

Hot reload

這個 Hello World 程式撰寫完之後,你可以試著更動你的程式碼並且儲存,就會發現並沒有立即更新而是需要重新運行cargo run,但是這樣對於開發者來說其實並不是很方便,因為需要不斷的去重起伺服器才可以看到更新,因此我們用這個套件來實現這個功能:

# 安裝 cargo-watch 套件
~$ cargo install cargo-watch
# 這個指令的意思是說監控文件的變化並且在檢測到更新後執行 cargo run --release
~$ cargo watch -x "run --release"

這個指令執行完畢之後就會開始編譯並執行,開始執行之後就可以試著更動程式碼,更動後就會立即被編譯並且執行。

路由

一個網路應用程式最重要的就是路由,回頭看一下 hello world 中的/route的定義:

// src/main.rs

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;

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

#[get("/hello/world")]
fn helloWorld() -> &'static str {
    "hello"
}

fn main() {
    // 這樣 index() 跟 hello() 兩個 Route 就會被註冊到應用程式中
    // 並且 / -> index()
    // /hello -> hell()
    // 並且透過 launch() 來告訴 Rocket 應用程式到這裡可以開始監聽 Request 了
    rocket::ignite().mount("/", routes![index, helloWorld]).launch();
}

除此之外,Route 也可以放在用 prefix 包起來,上面的main()以及helloWorld()可以改寫成:

#[get("/world")]
fn helloWorld() -> &'static str {
    "hello"
}

fn main() {
    rocket::ignite()
    	.mount("/", routes![index]) // mount / -> index()
    	.mount("/hello", routes![helloWorld]) // mount /hello/world -> helloWorld()
    	.launch();
}

Namespace

在大部分的應用場景中,我們都會將程式碼分檔案放在不同地方,在這裡我想要把helloWorld()放到hello的模組之中,並實現world()函數:

首先我們先創建src/hello.rs檔案,創建完之後src/資料夾會長得像這樣:

src/
├── hello.rs
└── main.rs

接著我們在hello.rs中撰寫一個world()函數:

// src/hello.rs
#[get("/world")]
pub fn world() -> &'static str
{
    return "Hello World";
}

然後我們回到src/main.rs

// 引入 hello 模組
mod hello;

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

fn main() {
    rocket::ignite()
        .mount("/", routes![index])
    	// 在這裡 Rocket.rs 的文件有特別提到如果寫成
    	// use hello::world;
    	// .mount("/hello", routes![world])
    	// 將會觸發錯誤,詳細原因可以參照這裡:https://rocket.rs/v0.4/guide/overview/#namespacing
        .mount("/hello", routes![hello::world]).launch();
}

這樣就可以將不同的 route 移到其他檔案中了。