路由属性 #

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自动计算优先级:

  1. 静态路径最高优先级
  2. 动态参数次之
  3. 通配参数最低

自定义优先级 #

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