framework_web_axum/
server.rs1use crate::{AxumContext, AxumCors, AxumCorsFn, WebRouteWrapper, WebRouter, build_router_with};
2use anyhow::{Context, Result, anyhow};
3use framework_web::WebContext;
4use std::net::SocketAddr;
5use std::sync::{Arc, Mutex, OnceLock};
6use tokio::net::TcpListener;
7
8pub fn axum_builder(bind_address: impl Into<String>, bind_port: i32) -> AxumBuilder {
10 AxumBuilder {
11 bind_address: bind_address.into(),
12 bind_port: u16::try_from(bind_port).unwrap_or_default(),
13 cors: default_cors(),
14 }
15}
16
17pub struct AxumBuilder {
19 bind_address: String,
20 bind_port: u16,
21 cors: AxumCorsFn,
22}
23
24impl AxumBuilder {
25 pub fn with_cors<F>(mut self, cors: F) -> Self
27 where
28 F: Fn(&WebContext) -> AxumCors + Send + Sync + 'static,
29 {
30 self.cors = Arc::new(cors);
31 self
32 }
33
34 pub async fn bind(self) -> Result<AxumServer> {
36 let address = format!("{}:{}", self.bind_address, self.bind_port);
37 let listener = TcpListener::bind(&address)
38 .await
39 .with_context(|| format!("监听地址 {address} 失败"))?;
40 let local = listener
41 .local_addr()
42 .with_context(|| format!("读取监听地址 {address} 失败"))?;
43 Ok(AxumServer {
44 listener: Mutex::new(Some(listener)),
45 context: AxumContext::new(self.bind_address, local.port()),
46 cors: self.cors,
47 router: OnceLock::new(),
48 })
49 }
50}
51
52pub struct AxumServer {
54 listener: Mutex<Option<TcpListener>>,
55 context: AxumContext,
56 cors: AxumCorsFn,
57 router: OnceLock<Arc<WebRouter>>,
58}
59
60impl AxumServer {
61 pub fn context(&self) -> &AxumContext {
63 &self.context
64 }
65
66 pub fn router(&self) -> Option<Arc<WebRouter>> {
68 self.router.get().cloned()
69 }
70
71 pub async fn run(&self, wrapper: Option<WebRouteWrapper>) -> Result<()> {
73 let listener = self
74 .listener
75 .lock()
76 .map_err(|error| anyhow!("Axum 监听器锁定失败:{error}"))?
77 .take()
78 .ok_or_else(|| anyhow!("Axum 服务已启动"))?;
79 let router = Arc::new(WebRouter::new(wrapper));
80 let app = build_router_with(
81 Arc::clone(&router),
82 self.context.clone(),
83 Arc::clone(&self.cors),
84 );
85 let _ = self.router.set(router);
86 axum::serve(
87 listener,
88 app.into_make_service_with_connect_info::<SocketAddr>(),
89 )
90 .await
91 .context("Axum 服务运行失败")
92 }
93}
94
95fn default_cors() -> AxumCorsFn {
96 Arc::new(|_| AxumCors::fixed().clone())
97}