1use std::net::SocketAddr;
2use std::sync::Arc;
3
4use axum::routing::get;
5use axum::Router;
6use crate::core::RuestApplication;
7use crate::di::Container;
8use tower_http::cors::{Any, CorsLayer};
9use tower_http::trace::TraceLayer;
10
11use super::error::HttpError;
12use super::middleware::LoggerMiddleware;
13
14pub async fn serve(app: RuestApplication, router: Router) -> Result<(), HttpError> {
16 let built = finalize_router(app, router)?;
17 let addr: SocketAddr = format!("{}:{}", built.host, built.port)
18 .parse()
19 .map_err(|e: std::net::AddrParseError| HttpError::Message(e.to_string()))?;
20
21 tracing::info!("RUEST listening on http://{addr}");
22
23 let listener = tokio::net::TcpListener::bind(addr)
24 .await
25 .map_err(|e: std::io::Error| HttpError::Message(e.to_string()))?;
26
27 axum::serve(listener, built.router)
28 .await
29 .map_err(|e: std::io::Error| HttpError::Message(e.to_string()))?;
30
31 Ok(())
32}
33
34struct BuiltRouter {
35 router: Router,
36 host: String,
37 port: u16,
38}
39
40fn finalize_router(app: RuestApplication, router: Router) -> Result<BuiltRouter, HttpError> {
41 let container = Arc::new(app.container);
42
43 let router = router
44 .route("/health", get(|| async { "ok" }))
45 .layer(TraceLayer::new_for_http())
46 .layer(CorsLayer::new().allow_origin(Any).allow_methods(Any))
47 .layer(LoggerMiddleware)
48 .layer(axum::Extension(ContainerExtension(Arc::clone(&container))));
49
50 Ok(BuiltRouter {
51 router,
52 host: app.host,
53 port: app.port,
54 })
55}
56
57#[derive(Clone)]
59pub struct ContainerExtension(pub Arc<Container>);