debt-pirate/api/src/requests/mod.rs

81 lines
1.8 KiB
Rust
Raw Normal View History

mod user;
use std::time::Duration;
use axum::{
extract::{MatchedPath, Request},
response::Response,
Router,
};
use tokio::net::TcpListener;
use tower_http::trace::TraceLayer;
use tracing::{error, info, info_span, warn, Span};
2024-08-24 13:22:51 -04:00
use crate::{
db::DbPool,
models::{AppError, Environment},
};
#[derive(Clone)]
pub struct AppState {
pool: DbPool,
env: Environment,
}
impl AppState {
pub fn new(pool: DbPool, env: Environment) -> Self {
Self { pool, env }
}
pub fn pool(&self) -> &DbPool {
&self.pool
}
pub fn env(&self) -> &Environment {
&self.env
}
}
pub async fn start_app(pool: DbPool, env: Environment) -> Result<(), AppError> {
2024-08-22 17:29:24 -04:00
let address = env.hostname();
let port = env.port();
2024-09-30 00:15:19 -04:00
info!("Listening on {address}:{port}...");
let listener = TcpListener::bind(format!("{address}:{port}"))
.await
.unwrap();
let logging_layer = TraceLayer::new_for_http()
.make_span_with(|request: &Request| {
let request_path = request
.extensions()
.get::<MatchedPath>()
.map(MatchedPath::as_str).unwrap();
info_span!("http_request", method = %request.method(), path = %request_path, status = tracing::field::Empty)
})
.on_response(|response: &Response, _duration: Duration, _span: &Span| {
let status = response.status();
_span.record("status", status.to_string());
match status.as_u16() {
w if (300..400).contains(&w) => warn!(""),
e if e >= 400 => error!(""),
_ => info!("")
}
});
let app_state = AppState::new(pool, env);
let app = Router::new()
.merge(user::requests(app_state.clone()))
.layer(logging_layer);
2024-09-30 00:15:19 -04:00
info!("API started successfully.");
axum::serve(listener, app)
.await
.map_err(AppError::app_startup)?;
Ok(())
}