Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Extractors

Controller extractors turn HTTP request data into typed method arguments. Their behavior is shared by Actix and Axum; applications do not use backend extractor types in controller signatures.

AttributeAccepted Rust typeFeature
#[param]any Serde-deserializable scalar, tuple, or structruntime
#[query]any Serde-deserializable typeruntime
#[body]any Serde-deserializable DTOruntime; uploads for multipart
#[user]a cloneable concrete type stored in RequestContextruntime
#[cookie("name")]String or Option<String>runtime
#[file]UploadedFile or Option<UploadedFile>uploads
#[files]Vec<UploadedFile>uploads
#[multipart]MultipartFormuploads
#[validate]a value implementing validator::Validatevalidator

Arguments must be simple identifiers. Each extracted parameter has exactly one extractor marker; #[validate] is an additional marker on a decoded value.

#![allow(unused)]
fn main() {
#[post("/{account_id}")]
async fn update(
    &self,
    #[param] account_id: i64,
    #[query] options: UpdateOptions,
    #[body] #[validate] input: UpdateAccount,
    #[user] actor: CurrentUser,
    #[cookie("session")] session: String,
) -> Result<Response<Account>> {
    self.accounts.update(account_id, options, input, actor, session).await
}
}

Path and query types use Serde conversion. A body accepts JSON when Content-Type is application/json or omitted. With uploads, it also accepts multipart text fields using Serde form semantics. #[user] clones a typed value previously inserted by a guard or interceptor. A missing user returns 401 Unauthorized with Not authenticated.

Cookie extraction is described fully in Cookies and Sessions. A required cookie is String; an optional cookie is Option<String>.

Upload combinations

#[body] may be combined with #[file] or #[files]. A required file makes multipart mandatory. If every file is optional, JSON remains valid and supplies None. Vec<UploadedFile> collects repeated parts and requires multipart. #[multipart] MultipartForm owns the complete form and cannot be combined with #[body], #[file], or #[files].

File checks run in request order: declared size, declared or detected MIME type, then the async controller validator named by validate = method. DTO #[validate] runs after successful decoding. See Multipart Uploads for file types, lifecycle, and #[upload(limit = bytes)].

Failure normalization and order

Extraction finishes before the controller method runs. Caelix normalizes failures:

  • 400 Bad Request: malformed path/query/body/multipart data, missing required cookie or file, duplicate single-file parts, validation failure, or rejected MIME.
  • 401 Unauthorized: missing #[user] context value.
  • 413 Payload Too Large: application/route body limit or file-size violation.
  • 415 Unsupported Media Type: a declared content type the route cannot accept.

Malformed input cannot reach validation because no typed value exists. After decoding, DTO validation and then file validation complete before method invocation. A failed multipart request drops all staged files.

With openapi, body, path, query, file, and cookie declarations contribute their corresponding operation parameters or request body. Runtime errors keep the standard error response shape.