Expand description

Axum Starter

Why axum-starter

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

Quick Start

The following example using axum-starter starting a web server which server on http://127.0.0.1:8080

It can do

  1. show info before launch
  2. using simple_logger and adding TraceLayer as logger middleware
  3. request http://127.0.0.1:8080/{name} will respond greet with your name
  4. using ctrl + c can graceful stop the server

use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};

use axum::{extract::Path, routing::get};
use axum_starter::{
    graceful::SetGraceful, prepare, router::Route, PreparedEffect, Provider, ServeAddress,
    ServerEffect, ServerPrepare,
};
use futures::FutureExt;
use tokio::sync::oneshot;
use tower_http::trace::TraceLayer;

/// configure for server starter
#[derive(Debug, Provider)]
struct Configure {
    #[provider(ref, transparent)]
    foo: String,
    #[provider(skip)]
    bar: SocketAddr,

    foo_bar: (i32, i32),
}

impl ServeAddress for Configure {
    type Address = SocketAddr;

    fn get_address(&self) -> Self::Address {
        self.bar
    }
}

impl ServerEffect 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

/// using `#[prepare]`
#[prepare(Logger)]
fn start_logger() -> Result<(), log::SetLoggerError> {
    simple_logger::init()
}

/// if need ref args ,adding a lifetime
#[prepare(ShowFoo 'arg)]
fn show_foo(foo: &'arg String) {
    println!("this is Foo {foo}")
}
#[prepare(EchoRouter)]
fn echo() -> impl PreparedEffect {
    Route::new(
        "/:echo",
        get(|Path(echo): Path<String>| async move { format!("Welcome ! {echo}") }),
    )
}

async fn show(FooBar((x, y)): FooBar) {
    println!("the foo bar is local at ({x}, {y})")
}

/// function style prepare
async fn graceful_shutdown() -> impl PreparedEffect {
    let (tx, rx) = oneshot::channel();
    tokio::spawn(async move {
        match tokio::signal::ctrl_c().await {
            _ => {
                println!("recv ctrl c");
                tx.send(())
            }
        }
    });
    tokio::task::yield_now().await;

    SetGraceful::new(rx.map(|_| ()))
}

#[tokio::main]
async fn main() {
    start().await
}

async fn start() {
    ServerPrepare::with_config(Configure::new())
        .append(Logger)
        .append(ShowFoo)
        .append_fn(show)
        .append_fn(graceful_shutdown)
        .append(EchoRouter)
        .with_global_middleware(TraceLayer::new_for_http())
        .prepare_start()
        .await
        .expect("Prepare for starting server failure")
        .launch()
        .await
        .expect("Server Error")
}

Prepare trait

the trait define how to apply the prepare task, after prepare down, it return a PreparedEffect

PreparedEffect trait

the trait will apply multiply effect on the server. include the following

  • Router
  • Extension
  • GracefulShutdown
  • setting the internal hyper::Server

Modules

help type for apply effect on adding extension
help type for apply effect on graceful shutdown
help types for apply effect on Router
help types for apply effect on Builder

Structs

A help type for adding extension
wrapping for function-style Prepare
type for prepare starting

Enums

all prepare task are done , the server is ready for launch

Traits

fallible prepare effect
Preparing before server launch
make the func-style Prepare can be used
side effect after a Prepare
the Config that can provide config info T the T can be either returning Ownership or Reference
get the address this server are going to bind with
change the server configure, this operate can overwrite PrepareEffect

Functions

help function for wrap function into PrepareHandler

Type Definitions

boxed Future which return a Result, with boxed PreparedEffect and Error

Attribute Macros

make a function can apply as a Prepare

Derive Macros

implement Provider<T> for each field of the struct