Build method to AppBuilder that returns a Router of all settings.

Updated router! to allow for generic types
This commit is contained in:
Martin Berg Alstad 2024-08-26 17:14:39 +02:00
parent eeab1257e3
commit 93fe1e0cda
2 changed files with 54 additions and 16 deletions

View File

@ -44,6 +44,13 @@ impl AppBuilder {
Self::default()
}
pub fn from_router(router: Router) -> Self {
Self {
router,
..Self::default()
}
}
pub fn route(mut self, route: Router) -> Self {
self.router = self.router.merge(route);
self
@ -106,6 +113,23 @@ impl AppBuilder {
self
}
/// Creates the app with the given options.
/// This method is useful for testing purposes.
/// Options used for configuring the listener will be lost.
pub fn build(self) -> Router {
let mut app = self.router;
if let Some(cors) = self.cors {
app = app.layer(cors);
}
app.layer(
self.tracing.unwrap_or(
TraceLayer::new_for_http()
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
.on_response(trace::DefaultOnResponse::new().level(Level::INFO)),
),
)
}
/// Build the app and start the server
/// # Default Options
/// - IP == 0.0.0.0
@ -118,10 +142,10 @@ impl AppBuilder {
let listener = self.listener().await?;
if self.normalize_path.unwrap_or(true) {
let app = NormalizePathLayer::trim_trailing_slash().layer(self.create_app());
let app = NormalizePathLayer::trim_trailing_slash().layer(self.build());
axum::serve(listener, ServiceExt::<Request>::into_make_service(app)).await?;
} else {
let app = self.create_app();
let app = self.build();
axum::serve(listener, app.into_make_service()).await?;
};
Ok(())
@ -132,20 +156,6 @@ impl AppBuilder {
info!("Initializing server on: {addr}");
TcpListener::bind(&addr).await
}
fn create_app(self) -> Router {
let mut app = self.router;
if let Some(cors) = self.cors {
app = app.layer(cors);
}
app.layer(
self.tracing.unwrap_or(
TraceLayer::new_for_http()
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
.on_response(trace::DefaultOnResponse::new().level(Level::INFO)),
),
)
}
}
fn fmt_trace() -> Result<(), String> {

View File

@ -29,12 +29,28 @@ macro_rules! router {
$body
}
};
($body:expr; $state:ident: $($bound:tt),*) => {
pub fn router<$state: $($bound+)* 'static>() -> axum::Router<$state> {
$body
}
};
($body:expr; $generic:ident: $($bound:tt),* -> $state:ty) => {
pub fn router<$generic: $($bound+)* 'static>() -> axum::Router<$state<$generic>> {
$body
}
};
($route:expr, $router:expr) => {
router!(axum::Router::new().nest($route, $router));
};
($route:expr, $router:expr, $state:ty) => {
router!(axum::Router::new().nest($route, $router); $state);
};
($route:expr, $router:expr, $state:ident: $($bound:tt),*) => {
router!(axum::Router::new().nest($route, $router); $state: $($bound),*);
};
($route:expr, $router:expr, $generic:ident: $($bound:tt),* -> $state:ty) => {
router!(axum::Router::new().nest($route, $router); $generic: $($bound),* -> $state);
};
($($method:ident $route:expr => $func:expr),* $(,)?) => {
router!($crate::routes!($($method $route => $func),*));
};
@ -112,6 +128,18 @@ mod tests {
);
}
#[test]
fn test_nested_router_with_generic_state() {
router!(
"/simplify",
routes!(
get "/:exp" => || async {},
get "/table/:exp" => |_state: State<T>| async {}
),
T: Clone, Send, Sync
);
}
#[test]
fn test_routes() {
let _router: Router = routes!(