Skip to main content

Routing

Advanced routing techniques and guards.

Actix 4.9+ 6 min read

# Advanced Routing

Actix Web features a powerful routing engine. Beyond basic path matching, you can use Guards to filter requests based on headers, query parameters, or complex custom logic.

##Routing Resolution

When a request arrives, Actix Web evaluates routes in the order they were registered. It stops at the first route that matches both the path and all applied guards.

code_blocksrust
App::new()
    .route("/path", web::get().to(handler_a)) // Evaluated first
    .route("/path", web::post().to(handler_b)) // Evaluated second

##Using Guards

Guards allow you to attach conditions to a route. A route is only executed if the path matches AND all guards return true.

Actix Web provides built-in guards in actix_web::guard: - Get(), Post(), etc. (Filter by HTTP Method) - Header("key", "value") - Host("www.rust-lang.org")

code_blocksrust
use actix_web::{guard, web, App, HttpResponse, Responder};

async fn secret_handler() -> impl Responder {
    "You provided the secret header!"
}

App::new().route(
    "/secret",
    web::get()
        .guard(guard::Header("X-Secret-Token", "supersecret"))
        .to(secret_handler)
)

##Custom Guards

You can implement your own guards by implementing the guard::Guard trait, or simply passing a closure that takes a &guard::GuardContext and returns a bool.

code_blocksrust
use actix_web::guard::GuardContext;

fn custom_guard(ctx: &GuardContext<'_>) -> bool {
    // Check something complex
    ctx.head().uri.query().unwrap_or("").contains("allow=true")
}

App::new().route(
    "/custom",
    web::get().guard(actix_web::guard::fn_guard(custom_guard)).to(|| async { "Allowed!" })
)

##Normalizing Paths

Sometimes clients request /resource/ with a trailing slash, and sometimes /resource without. By default, Actix Web treats these as strictly different. You can use middleware to normalize paths:

code_blocksrust
use actix_web::middleware::NormalizePath;

App::new()
    .wrap(NormalizePath::trim())
    // Now both /test and /test/ will route to /test

Was this page helpful?

Reference Implementation

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

src/main.rs
1use actix_web::{guard, web, App, HttpServer, Responder};
2
3async fn admin_panel() -> impl Responder {
4 "Admin Content"
5}
6
7#[actix_web::main]
8async fn main() -> std::io::Result<()> {
9 HttpServer::new(|| {
10 App::new().route(
11 "/admin",
12 web::get()
13 .guard(guard::Host("admin.local"))
14 .to(admin_panel)
15 )
16 })
17 .bind("127.0.0.1:8080")?
18 .run()
19 .await
20}
Was this page helpful?