Route
Route Registration
Route handlers can be created using get, post and other functions.
The corresponding functions can be imported in the volo_http::route package, e.g, get via volo_http::route::get.
First, we need a simple handler: volo_http::route::get.
async fn foo_handler() -> &'static str {
    "Hello, World!\n"
}
Each route requires a relative path and a method.
Let’s take the GET method for routing to the “/foo” path as an example,
which can be created by using the route method after creating a Router in the following way.
use volo_http::server::route::{get, Router};
pub fn test_router() -> Router {
    Router::new().route("/foo", get(foo_handler))
}
You can chain calls to MethodRouter from get to set handlers for other methods.
use volo_http::server::route::{get, Router};
pub fn test_router() -> Router {
    Router::new()
        .route("/foo", get(foo_handoer).post(foo_handler))
}
Routing rules can also be created by chaining calls to Router:
use volo_http::server::route::{get, Router};
pub fn test_router() -> Router {
    Router::new()
        .route("/foo", get(foo_handler))
        .route("/bar", post(bar_handler))
}
Once created, the route can be merged into the main route:
use std::net::SocketAddr;
use std::time::Duration;
use volo::net::Address;
use volo_http::{Router, Server};
#[volo::main]
async fn main() {
    let app = Router::new()
        .merge(example_router())
        .merge(test_router())
        .layer(TimeoutLayer::new(Duration::from_secs(1), timeout_handler));
    let addr = "[::]:8080".parse::<SocketAddr>().unwarp();
    let addr = Address::from(addr);
    Server::new(app).run(addr).await.unwarp();
}
Routing methods
Use a method such as use volo_http::server::route::get to import a route as a GET.
Currently supported routing methods are:
optionsgetpostputdeleteheadtraceconnecttrace
Route Types
Volo-HTTP supports rich route types for complex route matching, including static routes, dynamic routes (named parameter, wildcard).
Priority of routes: static routes > named parameter routes > wildcard routes.
Static route
use volo_http::server::route::{get, Router};
async fn index_handler() -> &'static str {
    "Hello, World"
}
async fn index_router() -> Router {
    Router::new().route("/", get(index));
}
Named Parameter Route
Volo-HTTP supports routing with named parameters like {id}, and the named parameters only match a single path segment.
If you set up a /user/{id} route, the match will be as follows.
| Route | Matched | Param Value | 
|---|---|---|
/user/100 | 
          Yes | 100 | 
/user/101/profile | 
          No | - | 
/user/ | 
          No | - | 
Volo-HTTP also supports multiple named parameters, e.g. /{platform}/user/{id}.
Example:
use volo::FastStr;
use volo_http::server::{
    param::PathParamsMap,
    route::{get, Router},
};
async fn param_handler(map: PathParamsMap) -> FastStr {
    // Note: The `unwarp` method is not recommended for production environments.
    // It is used here for tutorial purposes only.
    map.get("id").unwarp().clone()
}
async fn param_router() -> Router {
    Router::new().route("/user/{id}", get(param_handler))
}
Wildcard Route
Volo-HTTP supports the use of *path as a wildcard parameter for routes, and the wildcard parameter matches everything.
**Note: The wildcard parameter must be placed at the end of the route. **Note: Wildcards should be placed at the end of the route.
If we set up a /src/{*path} route, it will match as follows:
| Route | Matched | Param Value | 
|---|---|---|
/src/ | 
          Yes | - | 
/src/somefile.rs | 
          No | somefile.rs | 
/src/subdir/somefile.rs | 
          No | subdir/somefile.rs | 
Example:
use volo::FastStr;
use volo_http::server::{
    param::PathParamsMap,
    route::{get, Router},
};
async fn param_handler(map: PathParamsMap) -> FastStr {
    // Note: The `unwarp` method is not recommended for production environments.
    // It is used here for tutorial purposes only.
    map.get("path").unwarp().clone()
}
async fn param_router() -> Router {
    Router::new().route("/src/{*path}", get(param_handler))
}
Routing parameter values extraction
- 
PathParamsMapProvide a routing parameter
AHashmapuse volo_http::param::PathParamsMap; async fn param_handler(map: PathParamsMap) -> FastStr { // Note: The `unwarp` method is not recommended for production environments. // It is used here for tutorial purposes only. map.get("id").unwarp().clone() } - 
PathParamsUser-definable routing parameter values using pattern matching features
use volo_http::param::PathParams; async fn param_handler(PathParams(id): PathParams<String>) -> String { id } 
Route Group
Volo-HTTP provides the ability to route nests, which are used to support route grouping.
impl<B, E> Router<B, E> {
    /*...*/
    pub fn nest<U>(self, uri: U, router: Router<B, E>) -> Self
    where
        U: AsRef<str>,
    {
        self.nest_route(uri.as_ref().to_owned(), Route::new(router))
    }
}
We can use the given url prefix path as the route prefix for a given route, and then merge it into the current route
use volo_http::server::{
    param::PathParams,
    route::{get, Router},
};
async fn hello_world() -> &'static str {
    "Hello, World"
}
async fn get_tid(PathParams(tid): PathParams<String>) -> String {
    tid
}
async fn get_uid_and_tid(PathParams((uid, tid)): PathParams<(String, String)>) -> String {
    format!("uid: {uid}, tid: {tid}")
}
async fn user_router() -> Router {
    Router::new()
        .route("/name", get(hello_world))
        .route("/post/{tid}", get(get_uid_and_tid));
}
async fn post_router() -> Router {
    Router::new()
        .route("/name", get(hello_world))
        .route("/{tid}", get(get_tid));
}
async fn router() -> Router {
    Router::new()
        .nest("/user/{uid}", user_router())
        .nest("/post", post_router())
    // The routing paths here are as follows.
    // /user/{uid}/name
    // /user/{uid}/post/{tid}
    // /post/name
    // /post/{tid}
}
Fallback
Volo-HTTP provides a fallback function to handle request url or method mismatches, default fallback will return status code 404 Not Found.
Note:
- 
Since there is no way to determine which router fallback to override in a route in a call to the
mergemethod, only one router fallback can be set, or else a panic will be generated in the call to themergemethod; - 
The
nestmethod is called without overriding thefallback. 
url
Example:
async fn index_handler() -> &'static str {
    "Hello, World"
}
async fn fallback_handler() -> (http::StatusCode, &'static str) {
  (http::StatusCode::NOT_FOUND, "404 Not Found")
}
async fn router() -> Router {
    Router::new()
        .route("/", get(index_handler))
        .fallback(fallback_handler)
}
method
async fn index_handler() -> &'static str {
    "Hello, World"
}
async fn fallback_handler() -> (http::StatusCode, &'static str) {
  (http::StatusCode::METHOD_NOT_ALLOWED, "method not matched")
    
}
async fn router() -> Router {
    Router::new()
        .route("/", get(index_handler).fallback(fallback_handler))
}
Using Service as a Route
Routes can be implemented using a traditional Service, and the handler approach mentioned above will also work as a Service,
but you need to create a route for the GET method via get_service:
use std::convert::Infallible;
use volo_http::{
    context::ServerContext,
    request::ServerRequest,
    response::ServerResponse,
    server::{
        route::{get_service, Router},
        IntoResponse,
    },
};
use motore::Service;
#[derive(Clone)]
pub struct JsonGetService;
impl Service<ServerContext, ServerRequest> for JsonGetService {
    type Response = ServerResponse;
    type Error = Infallible;
    async fn call(
        &self,
        _cx: &mut ServerContext,
        _req: ServerRequest,
    ) -> Result<Self::Response, Self::Error> {
        Ok(json_get().await.into_response())
    }
}
pub fn json_test_router() -> Router {
    Router::new()
        /* ...... */
        .route(
            "/json/get_srv",
            get_service(JsonGetService),
        )
}
For this simpler Service, it is also possible to implement it directly using a function via service_fn without defining a structure:
use std::convert::Infallible;
use volo_http::{
    context::ServerContext,
    json::Json,
    request::ServerRequest,
    response::ServerResponse,
    server::{
        route::{post_service, Router},
        IntoResponse,
    },
};
use motore::{service::service_fn, Service};
async fn json_post_srv(
    cx: &mut ServerContext,
    req: ServerRequest,
) -> Result<ServerResponse, Infallible> {
    let (parts, body) = req.into_parts();
    let data = match Json::<Person>::from_request(cx, parts, body).await {
        Ok(data) => data,
        Err(_) => {
            return Ok("Invalid data!".into_response());
        }
    };
    Ok(json_post(Some(data)).await.into_response())
}
pub fn json_test_router() -> Router {
    Router::new()
        /* ...... */
        .route(
            "/json/post_srv",
            post_service(service_fn(json_post_srv)),
        )
}
The final run is expected to be consistent with json_get and json_post.