Rocket 使用
Rocket is web framework for Rust (nightly) with a focus on ease-of-use, expressibility, and speed.
Overview
安装 Rust
需要最新的 Rust 支持。
1curl https://sh.rustup.rs -sSf | sh 2rustup default nightly 3# or 4rustup override set nightly
升级 Rust
rustup update && cargo update
运行自带例子 hello_world
1git clone https://github.com/SergioBenitez/rocket 2cd rocket/examples/hello_world 3cargo run
运行成功后,访问:http://localhost:8000/
自己编写 hello, world
-
创建项目
cargo new hello-rocket --bin cd hello-rocket
-
配置 Cargo.toml
[package] name = "hello-rocket" version = "0.1.0" authors = ["dreamsxin dreamsxin@126.com"]
[dependencies] rocket = "0.2.8" rocket_codegen = "0.2.8"
-
编写 main.rs
#![feature(plugin)] #![plugin(rocket_codegen)]
extern crate rocket;
#[get("/")] fn index() -> &'static str { "Hello, world!" }
fn main() { rocket::ignite().mount("/", routes![index]).launch(); }
生命周期 Lifecycle
Rocket 的主要任务是监听 web 请求,然后将请求交由应用程序处理以及输出响应给客户端。从请求到响应这个过程成为一个生命周期。 生命周期分为以下几个步骤:
-
路由 Routing 将 HTTP 请求解析为本地数据结构,然后根据声明的路由属性进行匹配,来决定调用哪个请求处理程序。
-
验证 Validation 验证 HTTP 请求类型,以及请求数据。如果验证失败,则将请求转发到下一个匹配路由或调用错误处理程序。
-
处理 Processing 调用与路径关联的处理程序。这是应用程序的主要业务逻辑。处理完成后返回
Response。 -
响应 Response 处理返回的
Response。生成适当的 HTTP 响应并将其发送给客户端。这就完成了一个生命周期。继续侦听下一个请求,重新开启每个传入的请求。
路由 Routing
Rocket 应用程序以路由 routers 和处理程序 handlers 为中心。 处理程序 handler 只是一个具有任意数量参数并返回任意类型的函数。路由 route 是一种结合:
- 匹配请求参数。
- 调用处理程序以及返回响应
匹配的参数包括静态路径、动态路径、路径片段、表单、请求的字符串、请求的格式说明符和请求的 body 数据。 Rocket 使用属性以及定义一个匿名函数(即处理程序)来声明路由,并使用参数集来匹配。完整的路线声明如下:
1#[get("/world")] // <- route attribute 2fn world() -> &'static str { // <- request handler 3 "Hello, world!" 4}
绑定 Mounting
通过 Rocket 实例上的 mount 方法来绑定路由。
1rocket::ignite() // 创建实例 2 .mount("/hello", routes![world]);
请求 /hello/world 将会定向到 world 函数。
mount 使用了两个参数:
- 参数1,路径
- 参数2,路由处理程序列表,通过宏
routes!将 Rocket 的代码生成与应用程序联系起来。
命名空间
当在根之外的模块中声明路径时,会发生错误:
1mod other { 2 #[get("/world")] 3 pub fn world() -> &'static str { 4 "Hello, world!" 5 } 6} 7 8use other::world; 9 10fn main() { 11 // error[E0425]: cannot find value `static_rocket_route_info_for_world` in this scope 12 rocket::ignite().mount("/hello", routes![world]) 13}
这是因为 routes! 宏隐式地将路由的名称转换为由 Rocket 代码生成所生成的结构名称,解决方案是用模块路径命名:
rocket::ignite().mount("/hello", routes![other::world])
Launching
Rocket 知道了路由之后,就可以通过 launch 方法启动接受请求了。该方法启动服务器并等待请求的传入。 当请求到达时,Rocket 将会找到匹配的路径,并将请求分派给路由的处理程序。
1#![feature(plugin)] 2#![plugin(rocket_codegen)] 3 4extern crate rocket; 5 6#[get("/world")] 7fn world() -> &'static str { 8 "Hello, world!" 9} 10 11fn main() { 12 rocket::ignite() 13 .mount("/hello", routes![world]) 14 .launch(); 15}
请注意!这里增加了
#![feature(plugin)]和#![plugin(rocket_codegen)],告诉 Rust 我们将使用 Rocket 的代码生成插件。
启动:
cargo run
输出:
1 Compiling hello-rocket v0.1.0 (file:///home/develop/workspace/example/rust/code/hello-rocket) 2 Finished dev [unoptimized + debuginfo] target(s) in 5.44 secs 3 Running `target/debug/hello-rocket` 4🔧 Configured for development. 5 => address: localhost 6 => port: 8000 7 => log: normal 8 => workers: 4 9🛰 Mounting '/hello': 10 => GET /hello/world 11🚀 Rocket has launched from http://localhost:8000...
配置 Configuration
配置环境:
- development (short: dev)
- staging (short: stage)
- production (short: prod)
运行时加上:
ROCKET_ENV=stage cargo run
也可以写入配置文件 Rocket.toml:
1[development] 2address = "localhost" 3port = 8000 4workers = max(number_of_cpus, 2) 5log = "normal" 6 7[staging] 8address = "0.0.0.0" 9port = 80 10workers = max(number_of_cpus, 2) 11log = "normal" 12 13[production] 14address = "0.0.0.0" 15port = 80 16workers = max(number_of_cpus, 2) 17log = "critical"
我们可以使用 global 全局覆盖配置:
1[global] 2address = "1.2.3.4" 3 4[development] 5address = "localhost" 6 7[production] 8address = "0.0.0.0"
-
Extras
[development] template_dir = "dev_templates/"
[production] template_dir = "prod_templates/"
-
环境变量 Environment Variables
所有的配置参数,包括 Extras 都会被环境变量覆盖,配置参数为{NAME},使用环境变量ROCKET_{PARAM}进行覆盖:
ROCKET_PORT=3721 cargo run