With the growing of the server functions, the code which prepare multiply infrastructures for the server in the main become more and more complex.
For example, I need connect to Mysql
and Redis
, start MessageQuery
, start GracefulShutdown and so on.
In other to simplify the start up code with my server project, there comes the axum-starter
The following example using axum-starter
starting a web server which
server on http://127.0.0.1:8080
It can do
simple_logger
and adding TraceLayer as logger middlewarehttp://127.0.0.1:8080/{name}
will respond greet with your namectrl + c
can graceful stop the server```rust
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use axum::{ extract::{OriginalUri, Path}, handler::Handler, routing::get, Router, }; use axum_starter::{ graceful::SetGraceful, prepare, router::{Fallback, Nest, Route}, ConfigureServerEffect, EffectsCollector, LoggerInitialization, PreparedEffect, Provider, ServeAddress, ServerPrepare, }; use futures::FutureExt;
use tower_http::trace::TraceLayer;
/// configure for server starter
struct Configure { #[provider(ref, transparent)] #[provider(mapto(ty = "&'s str", by = "String::asstr", lifetime = "'s"))] #[provider(map_to(ty = "String", by = "Clone::clone"))] foo: String, #[provider(skip)] bar: SocketAddr,
foo_bar: (i32, i32),
}
impl LoggerInitialization for Configure { type Error = log::SetLoggerError;
fn init_logger(&self) -> Result<(), Self::Error> {
simple_logger::init()
}
}
impl ServeAddress for Configure { type Address = SocketAddr;
fn get_address(&self) -> Self::Address {
self.bar
}
}
impl ConfigureServerEffect for Configure {}
impl Configure { pub fn new() -> Self { Self { foo: "Foo".into(), bar: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 8080)), foo_bar: (1, 2), } } } // prepares
/// if need ref args ,adding a lifetime
fn show_foo(f: &'arg String) {
println!("this is Foo {f}")
}
/// using #[prepare]
fn echo() -> impl PreparedEffect {
Route::new(
"/:echo",
get(|Path(echo): Path
fn routers() -> impl PreparedEffect { EffectsCollector::new() .withroute(Nest::new( "/aac/b", Router::new().route( "/a", get(|OriginalUri(uri): OriginalUri| async move { format!("welcome {uri}") }), ), )) .withroute(Fallback::new(Handler::intoservice(|| async { "oops" }))) .withserver(axumstarter::service::ConfigServer::new(|s| { s.http1only(true) })) }
async fn show(FooBar((x, y)): FooBar) { println!("the foo bar is local at ({x}, {y})") }
/// function style prepare async fn gracefulshutdown() -> impl PreparedEffect { SetGraceful::new( tokio::signal::ctrlc() .map(|| println!("recv Exit msg")) .map(|| ()), ) }
async fn main() { start().await }
async fn start() { ServerPrepare::withconfig(Configure::new()) .initlogger() .expect("Init Logger Failure") .append(ShowFoo) .append(C) .appendfn(show) .appendfn(gracefulshutdown) .append(EchoRouter) .withglobalmiddleware(TraceLayer::newforhttp()) .preparestart() .await .expect("Prepare for starting server failure ") .launch() .await .expect("Server Error") }
```
Prepare
traitthe trait define how to apply the prepare task,
after prepare down, it return a PreparedEffect
PreparedEffect
traitthe trait will apply multiply effect on the server. include the following
hyper::Server