Axum is one of the best web frameworks in the Rust community. It is a sub-project based on hyper maintained by Tokio. Axum provides web routing, declarative HTTP request parsing, HTTP response serialization, and can be combined with the middleware in the tower ecosystem.
Dependencies
= { = "<version>" }
optional features:
http2: http2multipart: file uploadws: websocketsocket_io: SocketIO supportopenapi: OpenAPI documentationopenapi-redoc: Redoc documentation interfaceopenapi-scalar: Scalar documentation interfaceopenapi-swagger: Swagger documentation interface
Configuration items
[]
= "172.20.10.4" # IP address of the network interface to bind, default 0.0.0.0
= 8000 # Port number to bind, default 8080
= false # Whether to use client connection information, default false
= true # Whether to enable graceful shutdown, default false
= "api" # Global prefix for all routes, default empty
# Web middleware configuration
[]
= { = true } # Enable compression middleware
= { = true } # Capture panic generated by handler
= { = true, = "info" } # Enable log middleware
= { = true, = "5MB" } # Limit request body size
= { = true, = 60000 } # Request timeout 60s
# Cross-domain configuration
= { = true, = [
"https://spring-rs.github.io",
], = [
"Authentication",
], = [
"GET",
"POST",
], = 60 }
# Static resource configuration
= { = true, = "/static", = "static", = true, = "index.html" }
NOTE: The above middleware configuration can integrate the middleware provided in the tower ecosystem. Of course, if you are very familiar with the tower ecosystem, you can also configure it yourself by writing code without enabling these middleware. The following are relevant document links:
API interface
App implements the WebConfigurator feature, which can be used to specify routing configuration:
use spring::App;
use spring_web::{get, get_api};
use spring_web::{WebPlugin, WebConfigurator, Router, axum::response::IntoResponse, handler::TypeRouter};
use spring_sqlx::SqlxPlugin;
#[tokio::main]
async fn main() {
App::new()
.add_plugin(SqlxPlugin)
.add_plugin(WebPlugin)
.add_router(router())
.run()
.await
}
fn router() -> Router {
Router::new().typed_route(hello_word)
}
#[get("/")]
async fn hello_word() -> impl IntoResponse {
"hello word"
}
/// # The API summary title must use the head-1 in Markdown format.
/// description
/// description support multi line
/// The get_api macro automatically collects the request parameters and response schema.
/// @tag api_tag
#[get_api("/api")]
async fn hello_api() -> String {
"hello api".to_string()
}
You can also use the auto_config macro to implement automatic configuration. This process macro will automatically register the routes marked by the Procedural Macro into the app:
+#[auto_config(WebConfigurator)]
#[tokio::main]
async fn main() {
App::new()
.add_plugin(SqlxPlugin)
.add_plugin(WebPlugin)
- .add_router(router())
.run()
.await
}
-fn router() -> Router {
- Router::new().typed_route(hello_word)
-}
Attribute macro
In the example above, get is an attribute macro. spring-web provides procedural macros for eight standard HTTP methods: get, post, patch, put, delete, head, trace, and options. It also provides eight macros for generating OpenAPI documentation, such as get_api and post_api.
You can also use the route or api_route macros to bind multiple methods simultaneously:
use route;
use IntoResponse;
async
In addition, spring also supports binding multiple routes to a handler, which requires the routes attribute macro:
use ;
use IntoResponse;
async
Extract the Component registered by the plugin
In the above example, the SqlxPlugin plugin automatically registers a Sqlx connection pool component for us. We can use Component to extract this connection pool from State. Component is an axum extractor.
use Context;
use get;
use ;
use ;
async
Axum also provides other extractors, which are reexported under spring_web::extractor.
Read configuration
You can use Config to extract the configuration in the toml file.
use get;
use ;
use Configurable;
use Deserialize;
async
Add the corresponding configuration to your configuration file:
[]
= 1
= true
Complete code reference web-example
Use Extractor in Middleware
You can also use Extractor in middleware, but please note that you need to follow the rules of axum.
use ;
/// you can apply this middleware to your routes using the `middlewares` macro:
This middleware will:
- Intercept all responses from routes in the module
Complete code reference web-middleware-example
spring-web is a thin wrapper around axum, adding some macros to simplify development. The examples of axum can be run in spring-web.
SocketIO support
You can enable the socket_io feature of spring-web to use a integration with socketioxide.
SocketIO is a implementation of WebSocket with more definitions.
- Named events (like
chat message,user joined, etc.) instead of just plain messages - Automatic reconnection if the connection is lost
- Heartbeat mechanism to detect dead connections
- Rooms / Namespaces to group clients
- Fallbacks to other transports if WebSocket isn't available
You can refer to the socketio-example for a example of using SocketIO in spring-web.
We can share components registered by plugins in SocketIO handlers, just like in normal HTTP handlers, for example, using the Sqlx connection pool component registered by the SqlxPlugin plugin.
OpenAPI support
You can enable the openapi feature of spring-web to use OpenAPI documentation generation. You can refer to the openapi-example for more information.
Besides you need to enable one of the documentation interface features: openapi-redoc, openapi-scalar or openapi-swagger to generate the corresponding documentation interface.
/// Always return error
///
/// This endpoint is annotated with status_codes for Errors::B and Errors::C
/// @tag error
/// @status_codes Errors::B, Errors::C, Errors::SqlxError, Errors::TeaPod
async
To generate OpenAPI documentation, you can use the get_api, post_api, etc. macros to define your API endpoints. These macros will automatically collect request parameters and response schemas to generate OpenAPI documentation.
The comments above the API function are used to provide additional information for the OpenAPI documentation, such as tags and status codes.
The status_codes annotation specifies the possible error types that the API may return. This information will be included in the OpenAPI documentation, allowing users to understand the potential error responses when calling this API.
In case of want to define custom error types, you must implement the HttpStatusCode trait for your error type, which is used to map the error to an HTTP status code in the OpenAPI documentation.
We can use the derive macro ProblemDetails to automatically implement both the HttpStatusCode and ToProblemDetails traits for our custom error type.
In this case we are implementing thiserror::Error for better error handling, but it's not mandatory.
use ProblemDetails;
use StatusCode;
Simplified Error Handling with Automatic Problem Details
The ProblemDetails derive macro automatically generates both HttpStatusCode and ToProblemDetails implementations, eliminating the need for manual mapping:
use ProblemDetails;
// Only need ProblemDetails derive - HttpStatusCode and ToProblemDetails are generated automatically!
The macro automatically maps common HTTP status codes to appropriate Problem Details:
400→ProblemDetails::validation_error()(usesabout:blank)401→ProblemDetails::authentication_error()(usesabout:blank)403→ProblemDetails::authorization_error()(usesabout:blank)404→ProblemDetails::not_found()(usesabout:blank)500→ProblemDetails::internal_server_error()(usesabout:blank)503→ProblemDetails::service_unavailable()(usesabout:blank)- Other codes → Uses
about:blankas problem type
Advanced Problem Details with Custom Attributes
The ProblemDetails derive macro supports additional attributes for fine-grained control over the generated Problem Details:
use ProblemDetails;
Supported Attributes
#[status_code(code)]- Required: HTTP status code#[problem_type("uri")]- Optional: Custom problem type URI#[title("title")]- Optional: Custom problem title#[detail("detail")]- Optional: Custom problem detail message#[instance("uri")]- Optional: Problem instance URI
Title Compatibility
The title field can be automatically derived from the #[error("...")] attribute if no explicit #[title("...")] is provided. This provides compatibility with thiserror::Error and reduces duplication:
Generated Response Examples
BasicValidation (auto-generated):
InsufficientPermissions (fully customized):
async
Then implement error handling:
use ProblemDetails;
// Implement Problem Details conversion
The Problem Details response will be formatted as:
Automatic Instance URI Capture
Problem Details automatically captures the current request URI and includes it in the instance field. This feature is enabled by default and requires no additional configuration:
// No middleware configuration needed - it's automatic!
async
This will automatically generate responses with the request URI: