use crate::api::{Context, Result};
use std::{future::IntoFuture, net::SocketAddr};
use tokio::{net::TcpListener, task::JoinHandle};
use tokio_util::sync::CancellationToken;
use super::routes;
use axum::{
http::{HeaderValue, Method},
routing::get,
Router,
};
use tower_http::cors::CorsLayer;
pub struct Api {
pub(crate) info: SocketAddr,
pub(crate) listener: Option<TcpListener>,
pub(crate) state: Context,
}
impl Api {
pub async fn build(addr: SocketAddr, state: Context) -> Result<Self> {
let tcp = TcpListener::bind(addr).await?;
let info = tcp.local_addr()?;
Ok(Self {
info,
listener: Some(tcp),
state,
})
}
pub fn run(&mut self, cancel_token: CancellationToken) -> Result<JoinHandle<Result<()>>> {
let listener = self.listener.take();
if let Some(listener) = listener {
let app = Router::new()
.route("/livez", get(routes::livez))
.route("/readyz", get(routes::readyz))
.route(
"/banned",
get(routes::get_banned).post(routes::remove_banned),
)
.layer(
CorsLayer::new()
.allow_origin("*".parse::<HeaderValue>().unwrap())
.allow_methods([Method::GET]),
)
.with_state(self.state.clone());
let handle = tokio::spawn(async move {
let server = axum::serve(listener, app.into_make_service()).into_future();
tokio::select! {
biased;
() = cancel_token.cancelled() => {},
result = server => {
result?;
},
}
Ok(())
});
Ok(handle)
} else {
todo!()
}
}
pub(crate) fn listen_address(&self) -> SocketAddr {
self.info
}
}