torrust_index_backend/web/api/
server.rs1use std::net::SocketAddr;
2use std::sync::Arc;
3
4use futures::Future;
5use log::info;
6use tokio::sync::oneshot::{self, Sender};
7
8use super::v1::routes::router;
9use super::{Running, ServerStartedMessage};
10use crate::common::AppData;
11
12pub async fn start(app_data: Arc<AppData>, net_ip: &str, net_port: u16) -> Running {
18 let config_socket_addr: SocketAddr = format!("{net_ip}:{net_port}")
19 .parse()
20 .expect("API server socket address to be valid.");
21
22 let (tx, rx) = oneshot::channel::<ServerStartedMessage>();
23
24 let join_handle = tokio::spawn(async move {
26 info!("Starting API server with net config: {} ...", config_socket_addr);
27
28 let handle = start_server(config_socket_addr, app_data.clone(), tx);
29
30 if let Ok(()) = handle.await {
31 info!("API server stopped");
32 }
33
34 Ok(())
35 });
36
37 let bound_addr = match rx.await {
39 Ok(msg) => msg.socket_addr,
40 Err(e) => panic!("API server start. The API server was dropped: {e}"),
41 };
42
43 Running {
44 socket_addr: bound_addr,
45 api_server: Some(join_handle),
46 }
47}
48
49fn start_server(
50 config_socket_addr: SocketAddr,
51 app_data: Arc<AppData>,
52 tx: Sender<ServerStartedMessage>,
53) -> impl Future<Output = hyper::Result<()>> {
54 let tcp_listener = std::net::TcpListener::bind(config_socket_addr).expect("tcp listener to bind to a socket address");
55
56 let bound_addr = tcp_listener
57 .local_addr()
58 .expect("tcp listener to be bound to a socket address.");
59
60 info!("API server listening on http://{}", bound_addr);
61
62 let app = router(app_data);
63
64 let server = axum::Server::from_tcp(tcp_listener)
65 .expect("a new server from the previously created tcp listener.")
66 .serve(app.into_make_service_with_connect_info::<SocketAddr>());
67
68 tx.send(ServerStartedMessage { socket_addr: bound_addr })
69 .expect("the API server should not be dropped");
70
71 server.with_graceful_shutdown(async move {
72 tokio::signal::ctrl_c().await.expect("Failed to listen to shutdown signal.");
73 info!("Stopping API server on http://{} ...", bound_addr);
74 })
75}