Skip to main content

Extractors

Parsing data from requests.

Actix 4.9+ 7 min read

# Extractors

Extractors are Actix Web's mechanism for cleanly and safely parsing data out of incoming HTTP requests. They utilize Rust's type system to define exactly what your handler expects. If the incoming request doesn't match the expected format, Actix Web automatically returns a 400 Bad Request without your handler even executing!

##Common Extractors

Actix Web provides several built-in extractors:

#1. `web::Path`

Used to extract dynamic segments from the URL path.

code_blocksrust
use actix_web::{get, web, Responder};

#[get("/users/{user_id}/{friend_name}")] // <- matches path segments
async fn get_friend(path: web::Path<(u32, String)>) -> impl Responder {
    let (user_id, friend_name) = path.into_inner();
    format!("User {} is friends with {}", user_id, friend_name)
}

You can also use a serde::Deserialize struct instead of a tuple for named variables.

#2. `web::Query`

Used to extract URL query parameters (e.g., ?page=2&limit=50).

code_blocksrust
use serde::Deserialize;

#[derive(Deserialize)]
struct Pagination {
    page: u32,
    limit: u32,
}

#[get("/items")]
async fn items(info: web::Query<Pagination>) -> impl Responder {
    format!("Page {} with limit {}", info.page, info.limit)
}

#3. `web::Json`

Used to parse a JSON payload from the request body. Actix handles the deserialization via serde_json.

code_blocksrust
#[derive(Deserialize)]
struct CreateUser {
    username: String,
}

#[actix_web::post("/users")]
async fn create_user(user: web::Json<CreateUser>) -> impl Responder {
    format!("Created user: {}", user.username)
}

Note: The request must have a `Content-Type: application/json` header.

#4. `web::Data`

Used to extract shared application state (configured via App::app_data).

code_blocksrust
use std::sync::Mutex;

struct AppState {
    count: Mutex<u32>,
}

async fn increment(data: web::Data<AppState>) -> impl Responder {
    let mut count = data.count.lock().unwrap();
    *count += 1;
    format!("Request count: {}", count)
}

##Customizing Extractor Errors

By default, an extractor failure returns a generic 400 response. You can configure this behavior globally or per-extractor by providing an error handler.

code_blocksrust
let json_config = web::JsonConfig::default()
    .limit(4096) // Limit payload to 4kb
    .error_handler(|err, _req| {
        // Create a custom error response
        actix_web::error::InternalError::from_response(
            err,
            actix_web::HttpResponse::Conflict().finish(),
        )
        .into()
    });

App::new()
    .app_data(json_config) // Apply config

Extractors are arguably the most powerful feature of Actix Web. By enforcing strong types on HTTP inputs, you eliminate vast categories of runtime bugs.

Was this page helpful?

Reference Implementation

The following code snippet demonstrates the authoritative pattern for this documentation.

src/main.rs
1use actix_web::{get, web, App, HttpServer, Responder};
2use serde::Deserialize;
3
4#[derive(Deserialize)]
5struct Info {
6 username: String,
7}
8
9#[get("/{username}")]
10async fn greet(path: web::Path<Info>) -> impl Responder {
11 format!("Hello {}!", path.username)
12}
13
14#[actix_web::main]
15async fn main() -> std::io::Result<()> {
16 HttpServer::new(|| {
17 App::new().service(greet)
18 })
19 .bind("127.0.0.1:8080")?
20 .run()
21 .await
22}
Was this page helpful?