路由属性 #
Rocket的路由属性提供了丰富的配置选项,可以精确控制路由的匹配条件、数据格式和参数处理。
属性概述 #
路由属性支持以下配置:
| 属性 | 说明 | 示例 |
|---|---|---|
| 路径 | URL路径模板 | #[get("/users")] |
| format | 请求内容类型 | format = "json" |
| data | 请求体数据 | data = "<user>" |
| rank | 路由优先级 | rank = 2 |
format属性 #
format 属性用于指定请求的内容类型(Content-Type)。
JSON格式 #
rust
use rocket::serde::json::Json;
#[post("/users", format = "json", data = "<user>")]
fn create_user(user: Json<User>) -> Json<User> {
user
}
只有当请求头 Content-Type: application/json 时才会匹配此路由。
表单格式 #
rust
use rocket::form::Form;
#[post("/login", format = "form", data = "<form>")]
fn login(form: Form<LoginForm>) -> &'static str {
"Login success"
}
支持的格式 #
| 格式 | MIME类型 | 说明 |
|---|---|---|
| json | application/json | JSON数据 |
| form | application/x-www-form-urlencoded | 表单数据 |
| msgpack | application/msgpack | MessagePack |
| html | text/html | HTML内容 |
| xml | application/xml | XML数据 |
| plain | text/plain | 纯文本 |
| binary | application/octet-stream | 二进制数据 |
自定义MIME类型 #
rust
use rocket::http::ContentType;
#[post("/upload", format = "application/pdf", data = "<data>")]
fn upload_pdf(data: Vec<u8>) -> &'static str {
"PDF uploaded"
}
data属性 #
data 属性用于绑定请求体数据到函数参数。
基本用法 #
rust
#[derive(rocket::FromForm)]
struct UserForm {
name: String,
email: String,
}
#[post("/users", data = "<form>")]
fn create_user(form: Form<UserForm>) -> String {
format!("Created user: {}", form.name)
}
JSON数据 #
rust
use rocket::serde::{Deserialize, Serialize};
use rocket::serde::json::Json;
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct User {
name: String,
email: String,
}
#[post("/users", format = "json", data = "<user>")]
fn create_user(user: Json<User>) -> Json<User> {
user
}
字符串数据 #
rust
#[post("/echo", data = "<text>")]
fn echo(text: String) -> String {
text
}
字节数据 #
rust
#[post("/upload", data = "<data>")]
fn upload(data: Vec<u8>) -> String {
format!("Received {} bytes", data.len())
}
可选数据 #
rust
#[post("/optional", data = "<data>")]
fn optional_data(data: Option<String>) -> String {
data.unwrap_or_else(|| "No data".to_string())
}
查询参数 #
基本查询参数 #
rust
#[get("/search?q=<query>")]
fn search(query: &str) -> String {
format!("Searching for: {}", query)
}
多个查询参数 #
rust
#[get("/search?q=<query>&page=<page>")]
fn search_with_page(query: &str, page: u32) -> String {
format!("Searching '{}' on page {}", query, page)
}
结构化查询参数 #
rust
use rocket::request::Query;
use rocket::FromForm;
#[derive(FromForm)]
struct SearchParams {
q: String,
page: Option<usize>,
per_page: Option<usize>,
}
#[get("/search?<params..>")]
fn search(params: Query<SearchParams>) -> String {
let page = params.page.unwrap_or(1);
let per_page = params.per_page.unwrap_or(10);
format!("Search '{}' - Page {} ({} per page)", params.q, page, per_page)
}
可选查询参数 #
rust
#[derive(FromForm)]
struct FilterParams {
category: Option<String>,
min_price: Option<f64>,
max_price: Option<f64>,
}
#[get("/products?<filter..>")]
fn filter_products(filter: Query<FilterParams>) -> String {
format!("Filter: {:?}", filter.category)
}
rank属性 #
rank 属性用于设置路由优先级,数值越小优先级越高。
默认优先级 #
Rocket自动计算优先级:
- 静态路径最高优先级
- 动态参数次之
- 通配参数最低
自定义优先级 #
rust
#[get("/user/<id>", rank = 2)]
fn user_by_id(id: u32) -> String {
format!("User by ID: {}", id)
}
#[get("/user/<name>", rank = 1)]
fn user_by_name(name: &str) -> String {
format!("User by name: {}", name)
}
优先级规则 #
rust
#[get("/foo/bar", rank = 1)]
fn foo_bar() -> &'static str {
"Static path"
}
#[get("/foo/<_>", rank = 2)]
fn foo_dynamic(_: &str) -> &'static str {
"Dynamic path"
}
#[get("/<_>/bar", rank = 3)]
fn dynamic_bar(_: &str) -> &'static str {
"Dynamic prefix"
}
#[get("/<_>/<_>", rank = 4)]
fn both_dynamic(_: &str, _: &str) -> &'static str {
"Both dynamic"
}
组合属性 #
完整示例 #
rust
use rocket::serde::json::Json;
use rocket::form::Form;
use rocket::FromForm;
use rocket::serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, FromForm)]
#[serde(crate = "rocket::serde")]
struct User {
name: String,
email: String,
age: Option<u32>,
}
#[derive(FromForm)]
struct SearchQuery {
q: String,
limit: Option<usize>,
}
#[get("/users?<query..>")]
fn list_users(query: Query<SearchQuery>) -> String {
let limit = query.limit.unwrap_or(10);
format!("Search '{}' with limit {}", query.q, limit)
}
#[post("/users", format = "json", data = "<user>")]
fn create_user_json(user: Json<User>) -> Json<User> {
user
}
#[post("/users", format = "form", data = "<user>", rank = 2)]
fn create_user_form(user: Form<User>) -> String {
format!("Created user from form: {}", user.name)
}
#[put("/users/<id>", format = "json", data = "<user>")]
fn update_user(id: u32, user: Json<User>) -> Json<User> {
user
}
#[delete("/users/<id>")]
fn delete_user(id: u32) -> String {
format!("Deleted user {}", id)
}
路由属性最佳实践 #
1. 明确指定格式 #
rust
#[post("/api/users", format = "json", data = "<user>")]
fn create_user(user: Json<User>) -> Json<User> {
user
}
2. 使用结构化参数 #
rust
#[derive(FromForm)]
struct Pagination {
page: usize,
per_page: usize,
}
#[get("/items?<pagination..>")]
fn list_items(pagination: Query<Pagination>) -> String {
format!("Page {} with {} items", pagination.page, pagination.per_page)
}
3. 合理设置优先级 #
rust
#[get("/users/new")]
fn new_user_form() -> &'static str {
"New user form"
}
#[get("/users/<id>", rank = 2)]
fn get_user(id: u32) -> String {
format!("User {}", id)
}
4. 使用类型安全的参数 #
rust
#[get("/user/<id>")]
fn get_user(id: u32) -> String {
format!("User ID: {}", id)
}
下一步 #
掌握了路由属性后,让我们继续学习 动态路由,深入了解参数解析和路径匹配。
最后更新:2026-03-28