daoyi_cloud_common/
lib.rs

1pub use salvo::catcher::Catcher;
2pub use salvo::conn::rustls::{Keycert, RustlsConfig};
3pub use salvo::prelude::*;
4pub use salvo::server::ServerHandle;
5pub use serde::Serialize;
6pub use tokio::signal;
7pub use tracing::info;
8pub use tokio;
9
10pub mod config;
11pub mod db;
12pub mod models;
13pub mod utils;
14pub mod hoops;
15pub mod routers;
16
17pub mod error;
18pub use error::AppError;
19
20pub type AppResult<T> = Result<T, AppError>;
21pub type JsonResult<T> = Result<Json<T>, AppError>;
22pub type EmptyResult = Result<Json<Empty>, AppError>;
23
24pub fn json_ok<T>(data: T) -> JsonResult<T> {
25    Ok(Json(data))
26}
27#[derive(Serialize, ToSchema, Clone, Copy, Debug)]
28pub struct Empty {}
29pub fn empty_ok() -> JsonResult<Empty> {
30    Ok(Json(Empty {}))
31}
32
33// #[tokio::main]
34// async fn main() {
35//     crate::config::init();
36//     let config = crate::config::get();
37//     crate::db::init(&config.db).await;
38//
39//     let _guard = config.log.guard();
40//     tracing::info!("log level: {}", &config.log.filter_level);
41//
42//     let service = Service::new(routers::root())
43//         .catcher(Catcher::default().hoop(hoops::error_404))
44//         .hoop(hoops::cors_hoop());
45//     println!("🔄 在以下位置监听 {}", &config.listen_addr);
46//     //Acme 支持,自动从 Let's Encrypt 获取 TLS 证书。例子请看 https://github.com/salvo-rs/salvo/blob/main/examples/acme-http01-quinn/src/main.rs
47//     if let Some(tls) = &config.tls {
48//         let listen_addr = &config.listen_addr;
49//         println!(
50//             "📖 Open API Page: https://{}/scalar",
51//             listen_addr.replace("0.0.0.0", "127.0.0.1")
52//         );
53//         println!(
54//             "🔑 Login Page: https://{}/login",
55//             listen_addr.replace("0.0.0.0", "127.0.0.1")
56//         );
57//         let config = RustlsConfig::new(Keycert::new().cert(tls.cert.clone()).key(tls.key.clone()));
58//         let acceptor = TcpListener::new(listen_addr).rustls(config).bind().await;
59//         let server = Server::new(acceptor);
60//         tokio::spawn(shutdown_signal(server.handle()));
61//         server.serve(service).await;
62//     } else {
63//         println!(
64//             "📖 Open API 页面: http://{}/scalar",
65//             config.listen_addr.replace("0.0.0.0", "127.0.0.1")
66//         );
67//         println!(
68//             "🔑 Login Page: http://{}/login",
69//             config.listen_addr.replace("0.0.0.0", "127.0.0.1")
70//         );
71//         let acceptor = TcpListener::new(&config.listen_addr).bind().await;
72//         let server = Server::new(acceptor);
73//         tokio::spawn(shutdown_signal(server.handle()));
74//         server.serve(service).await;
75//     }
76// }
77
78pub async fn shutdown_signal(handle: ServerHandle) {
79    let ctrl_c = async {
80        signal::ctrl_c()
81            .await
82            .expect("failed to install Ctrl+C handler");
83    };
84
85    #[cfg(unix)]
86    let terminate = async {
87        signal::unix::signal(signal::unix::SignalKind::terminate())
88            .expect("failed to install signal handler")
89            .recv()
90            .await;
91    };
92
93    #[cfg(not(unix))]
94    let terminate = std::future::pending::<()>();
95
96    tokio::select! {
97        _ = ctrl_c => info!("ctrl_c signal received"),
98        _ = terminate => info!("terminate signal received"),
99    }
100    handle.stop_graceful(std::time::Duration::from_secs(60));
101}
102
103#[cfg(test)]
104mod tests {
105    use salvo::prelude::*;
106    use salvo::test::{ResponseExt, TestClient};
107
108    use crate::config;
109
110    #[tokio::test]
111    async fn test_hello_world() {
112        config::init();
113
114        let service = Service::new(crate::routers::root());
115
116        let content = TestClient::get(format!(
117            "http://{}",
118            config::get().listen_addr.replace("0.0.0.0", "127.0.0.1")
119        ))
120        .send(&service)
121        .await
122        .take_string()
123        .await
124        .unwrap();
125        assert_eq!(content, "Hello World from salvo");
126    }
127}