Skip to content

Request Handling & Validation

WebR provides multiple request data extractors with automatic serialization and validation.

Extractors overview

ExtractorData sourceUse case
Json<T>Request body (JSON)REST API request body
Query<T>URL query parametersGET request parameters
Path<T>URL path parameters/users/{id}
Form<T>Request body (form)application/x-www-form-urlencoded
Header<T>Request headersCustom header extraction
HeaderMapRaw request headersArbitrary header reading
MultipartRequest body (multipart)File uploads

Json

Parses Content-Type: application/json request body:

rust
#[derive(Deserialize)]
pub struct CreateUser {
    pub name: String,
    pub email: String,
    pub age: u8,
}

#[post("/users")]
async fn create(&self, Json(body): Json<CreateUser>) -> Json<User> {
    // body is already deserialized
    Json(user_service.create(body).await)
}

Query

Parses URL query parameters ?page=1&size=10:

rust
#[derive(Deserialize)]
pub struct PageQuery {
    pub page: u32,
    pub size: u32,
}

#[get("/items")]
async fn list(&self, Query(q): Query<PageQuery>) -> Json<Vec<Item>> {
    // q.page, q.size
    todo!()
}

Path

Extracts URL path parameters {id}:

rust
#[get("/users/{id}")]
async fn get_user(&self, Path(id): Path<i64>) -> Json<User> {
    // id = i64 value extracted from path
    todo!()
}

// Multiple path parameters
#[get("/users/{user_id}/posts/{post_id}")]
async fn get_post(&self, Path((user_id, post_id)): Path<(i64, i64)>) -> Json<Post> {
    todo!()
}

Form

Parses application/x-www-form-urlencoded forms:

rust
#[derive(Deserialize)]
pub struct LoginForm {
    pub username: String,
    pub password: String,
}

#[post("/login")]
async fn login(&self, Form(form): Form<LoginForm>) -> Json<Token> {
    todo!()
}

Extracts request headers, header keys auto-converted to snake_case to match field names:

rust
#[derive(Deserialize)]
pub struct AuthHeaders {
    pub authorization: String,
    #[serde(rename = "x-request-id")]
    pub request_id: Option<String>,
}

#[get("/me")]
async fn me(&self, Header(h): Header<AuthHeaders>) -> Json<User> {
    // h.authorization, h.request_id
    todo!()
}

HeaderMap

Directly access raw request headers:

rust
use webr::HeaderMapExt;

async fn handler(headers: HeaderMap) -> String {
    let token = headers.get_str("authorization").unwrap_or("");
    let page: i32 = headers.get_parsed("x-page").unwrap_or(1);
    format!("token: {token}, page: {page}")
}

Request body validation

Derive Validate on DTOs, extractors automatically run validation:

rust
#[derive(Deserialize, Validate)]
pub struct CreateUserDto {
    #[validate(length(min = 1, max = 50))]
    pub name: String,

    #[validate(email)]
    pub email: String,

    #[validate(range(min = 18, max = 150))]
    pub age: u8,
}

#[post("/users")]
async fn create(&self, Json(dto): Json<CreateUserDto>) -> Json<User> {
    // dto has passed validation, otherwise returns 422 Unprocessable Entity
    todo!()
}

Validation failures automatically return 422 Unprocessable Entity, with error details for each field in the response body.