Skip to main content

Module handler

Module handler 

Source
Expand description

Typed handlers (18.28.0, #86): extractors as function arguments, any IntoResponse as the return value, the route’s method and pattern taken from the #[get]/#[post]/… attribute.

ⓘ
use rust_web_server::app::App;
use rust_web_server::error::AppError;
use rust_web_server::get;
use rust_web_server::handler::{Json, Path, State};

struct Db;

#[get("/posts/{id}")]
fn show_post(Path(id): Path<u64>, State(db): State<Db>) -> Result<Json<String>, AppError> {
    let _ = db;
    Ok(Json(format!("post {id}")))
}

let app = App::with_state(Db).route(show_post);

The attribute turns show_post into a unit struct implementing Handler (and AsyncHandler); the function as written stays callable as show_post::call(…). Registration — AppWithState::route, Router::route, AsyncAppWithState::route — reads the method and pattern from RouteSpec, so the pattern the macro checked is the one that’s served.

The macro checks at compile time that the pattern’s parameters and the Path argument agree: a route with parameters needs a Path (or &PathParams) argument, a Path needs parameters, a tuple has one element per parameter, names bound as Path(id) / Path((id, slug)) are parameters of the route, and a #[derive(FromPath)] struct’s fields are exactly its parameters.

Each argument is extracted in order; the first that fails answers the request with its rejection (problem details, like rws’s own errors):

ArgumentRejection
Path<T>400 when a parameter doesn’t parse
Query<T> (serde)400 when the query string doesn’t fit T
Form<T> (serde)415 without an urlencoded Content-Type, 400 for a body that isn’t UTF-8, 422 when the fields don’t fit T
Json<T> (serde)400 (as json::Json’s FromRequest)
BodyText400 for a body that isn’t UTF-8
State<S>, &S, Body, RequestHeaders, RequestId, &Request, &ConnectionInfo, &PathParamsnever
any other FromRequest type (Validated<T>, your own)its own

Classic handlers — fn(&Request, &PathParams, &ConnectionInfo[, &S]) — keep the old behaviour: the attribute only adds a doc comment and they are registered with .get(pattern, handler) as before.

Structs§

Body
Raw request body bytes.
BodyText
Request body decoded as UTF-8 text.
Form
An application/x-www-form-urlencoded body deserialized into T: Form(signup): Form<Signup>. Same field types as Query.
Json
A JSON extractor and responder backed by serde_json.
Path
The route’s parameters, parsed: Path(id): Path<u64> for one, Path((id, slug)): Path<(u64, String)> for several, or a #[derive(FromPath)] struct whose fields are named after them.
Query
The query string deserialized into T: Query(page): Query<Page>.
RequestHeaders
Clone of all request headers.
RequestId
The request’s correlation ID (the X-Request-Id header, RequestIdLayer’s default — request_id::DEFAULT_HEADER), for handlers that want it without reaching for RequestHeaders directly.
RequestParts
What an extractor sees: the request, the route’s parameters, the connection and the app’s state.
State
The app’s shared state (App::with_state(state)): a clone of its Arc.

Traits§

AsyncHandler
A typed handler for AsyncAppWithState (http2): the route macros make one from an async fn, and from every sync typed handler too.
FromPath
A type Path can build from route parameters.
FromRequestParts
A typed handler argument: built from the RequestParts, or a ready-to-send rejection.
Handler
A typed handler for apps with state S, made by the route macros from a function whose arguments are extractors. Register it with .route(h).
IntoResponse
Implemented by any type that can be turned into an HTTP Response.
RouteSpec
A route’s method and pattern, generated by #[get("/path")] & co.

Type Aliases§

HandlerFuture
The future an AsyncHandler returns.