Rocket.rs 初探 - 安裝與起步
因為工作的原因需要學一個以 Rust 為基礎的 web framework, 也因為自己對於編譯式語言其實情有獨衷,所以想要學 Rust 很久了, 趁著這次有時間跟機會可以接觸到 Rocket.rs 就順便把 Rocket.rs 跟 Rust 一併學了, 然後寫成筆記。
事前工作
安裝 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 移到其他檔案中了。