use axum::response::IntoResponse; use axum::{ async_trait, extract::{FromRequest, RequestParts}, prelude::*, }; use http::Response; use http::StatusCode; use std::net::SocketAddr; #[tokio::main] async fn main() { // build our application with some routes let app = route("/:version/foo", get(handler)); // run it let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); tracing::debug!("listening on {}", addr); hyper::Server::bind(&addr) .serve(app.into_make_service()) .await .unwrap(); } async fn handler(version: Version) { println!("received request with version {:?}", version); } #[derive(Debug)] enum Version { V1, V2, V3, } #[async_trait] impl FromRequest for Version where B: Send, { type Rejection = Response; async fn from_request(req: &mut RequestParts) -> Result { let params = extract::UrlParamsMap::from_request(req) .await .map_err(IntoResponse::into_response)?; let version = params .get("version") .ok_or_else(|| (StatusCode::NOT_FOUND, "version param missing").into_response())?; match version { "v1" => Ok(Version::V1), "v2" => Ok(Version::V2), "v3" => Ok(Version::V3), _ => Err((StatusCode::NOT_FOUND, "unknown version").into_response()), } } }