1use super::App;
2use crate::error::Result;
3use crate::handler::BoxFuture;
4use crate::request::Request;
5use crate::response::Response;
6use crate::router::{compile_router, CompiledRouter};
7use crate::service::BoxedService;
8use crate::state::StateMap;
9use crate::upgrade::UpgradeBudget;
10use bytes::Bytes;
11use http::Method;
12use std::sync::Arc;
13use std::time::Duration;
14use tokio::sync::Semaphore;
15
16pub(crate) type StartupHook =
17 Arc<dyn Fn(Arc<StateMap>) -> BoxFuture<Result<()>> + Send + Sync>;
18pub(crate) type ShutdownHook = Arc<dyn Fn() -> BoxFuture<()> + Send + Sync>;
19
20#[derive(Clone)]
22pub struct Server {
23 pub(crate) inner: Arc<AppInner>,
24 pub(crate) startups: Vec<StartupHook>,
25 pub(crate) shutdowns: Vec<ShutdownHook>,
26}
27
28impl Server {
29 pub fn state(&self) -> Arc<StateMap> {
31 self.inner.state()
32 }
33
34 #[cfg(any(test, feature = "testing"))]
36 pub async fn run_startup(&self) -> Result<Arc<StateMap>> {
37 let state = self.state();
38 for hook in &self.startups {
39 hook(Arc::clone(&state)).await?;
40 }
41 Ok(state)
42 }
43
44 #[cfg(any(test, feature = "testing"))]
46 pub async fn run_shutdown(&self) {
47 for hook in &self.shutdowns {
48 hook().await;
49 }
50 }
51
52 pub async fn handle(&self, mut req: Request) -> Response {
54 req.state = Arc::clone(&self.inner.compiled.state);
55 self.inner.compiled.dispatch(req).await
56 }
57
58 pub async fn handle_request(&self, method: Method, path: &str, body: &str) -> Response {
61 let req = Request::builder()
62 .method(method)
63 .path(path)
64 .body(Bytes::from(body.to_string()))
65 .build();
66 self.handle(req).await
67 }
68}
69
70pub(crate) struct ListenParts {
71 pub(crate) inner: AppInner,
72 pub(crate) startups: Vec<StartupHook>,
73 pub(crate) shutdowns: Vec<ShutdownHook>,
74 pub(crate) services: Vec<BoxedService>,
75 pub(crate) start_services: bool,
77}
78
79impl App {
80 fn validate_plugin_requires(&self) -> Result<()> {
81 if let Some((plugin, dep)) = self.missing_plugin_requires.first().copied() {
82 return Err(crate::error::Error::Internal(format!(
83 "plugin `{plugin}` requires `{dep}`; install `{dep}` before `{plugin}`"
84 )));
85 }
86 if let Some(msg) = self.plugin_sdk_errors.first() {
87 return Err(crate::error::Error::Internal(msg.clone()));
88 }
89 Ok(())
90 }
91
92 pub fn build(&self) -> Result<Server> {
94 self.validate_plugin_requires()?;
95 let router = self.router.clone_for_compile();
96 router
97 .check_route_values(&self.router.state, &self.installed_plugins)
98 .map_err(crate::error::Error::Internal)?;
99 let explain = router.explain();
100 let route_count = router.route_entries().len();
101 let compiled = Arc::new(compile_router(router)?);
102 Ok(Server {
103 inner: Arc::new(AppInner::from_settings(
104 compiled,
105 route_count,
106 explain,
107 AppSettings::from(self),
108 )),
109 startups: self.on_startup.clone(),
110 shutdowns: self.on_shutdown.clone(),
111 })
112 }
113
114 pub(crate) fn into_listen_parts(mut self) -> Result<ListenParts> {
115 self.validate_plugin_requires()?;
116 let services = std::mem::take(&mut self.services);
117 let startups = self.on_startup.clone();
118 let shutdowns = self.on_shutdown.clone();
119 let start_services = !self.cli_mode || self.service_in_cli;
120
121 self.router
122 .check_route_values(&self.router.state, &self.installed_plugins)
123 .map_err(crate::error::Error::Internal)?;
124 let explain = self.router.explain();
125 let route_count = self.router.route_entries().len();
126 let settings = AppSettings::from(&self);
127 let router = self.router;
128 let compiled = Arc::new(compile_router(router)?);
129
130 Ok(ListenParts {
131 inner: AppInner::from_settings(compiled, route_count, explain, settings),
132 startups,
133 shutdowns,
134 services,
135 start_services,
136 })
137 }
138}
139
140pub(crate) struct AppSettings {
141 pub max_body_size: usize,
142 pub max_connections: usize,
143 pub max_upgraded_connections: usize,
144 pub max_concurrent_streams: usize,
145 pub max_headers: usize,
146 pub max_buf_size: Option<usize>,
147 pub request_timeout: Option<Duration>,
148 pub header_read_timeout: Duration,
149 pub idle_timeout: Duration,
150 pub drain_timeout: Duration,
151 pub keep_alive: bool,
152 pub trust_proxy: bool,
153 pub reuseport: bool,
154 pub hsts: bool,
155 pub alt_svc: Option<String>,
156}
157
158impl From<&App> for AppSettings {
159 fn from(app: &App) -> Self {
160 Self {
161 max_body_size: app.max_body_size,
162 max_connections: app.max_connections,
163 max_upgraded_connections: app.max_upgraded_connections,
164 max_concurrent_streams: app.max_concurrent_streams,
165 max_headers: app.max_headers,
166 max_buf_size: app.max_buf_size,
167 request_timeout: app.request_timeout,
168 header_read_timeout: app.header_read_timeout,
169 idle_timeout: app.idle_timeout,
170 drain_timeout: app.drain_timeout,
171 keep_alive: app.keep_alive,
172 trust_proxy: app.trust_proxy,
173 reuseport: app.reuseport,
174 hsts: app.hsts,
175 alt_svc: app.alt_svc.clone(),
176 }
177 }
178}
179
180pub(crate) struct AppInner {
181 pub(crate) compiled: Arc<CompiledRouter>,
182 pub(crate) max_body_size: usize,
183 pub(crate) max_connections: usize,
184 pub(crate) max_upgraded: UpgradeBudget,
185 pub(crate) max_concurrent_streams: usize,
186 pub(crate) max_headers: usize,
187 pub(crate) max_buf_size: Option<usize>,
188 pub(crate) request_timeout: Option<Duration>,
189 pub(crate) header_read_timeout: Duration,
190 pub(crate) idle_timeout: Duration,
191 pub(crate) drain_timeout: Duration,
192 pub(crate) keep_alive: bool,
193 pub(crate) trust_proxy: bool,
194 pub(crate) reuseport: bool,
195 pub(crate) hsts: bool,
196 pub(crate) alt_svc: Option<String>,
197 pub(crate) route_count: usize,
198 pub(crate) explain: String,
199}
200
201impl AppInner {
202 fn from_settings(
203 compiled: Arc<CompiledRouter>,
204 route_count: usize,
205 explain: String,
206 s: AppSettings,
207 ) -> Self {
208 Self {
209 compiled,
210 max_body_size: s.max_body_size,
211 max_connections: s.max_connections,
212 max_upgraded: UpgradeBudget(Arc::new(Semaphore::new(s.max_upgraded_connections))),
213 max_concurrent_streams: s.max_concurrent_streams,
214 max_headers: s.max_headers,
215 max_buf_size: s.max_buf_size,
216 request_timeout: s.request_timeout,
217 header_read_timeout: s.header_read_timeout,
218 idle_timeout: s.idle_timeout,
219 drain_timeout: s.drain_timeout,
220 keep_alive: s.keep_alive,
221 trust_proxy: s.trust_proxy,
222 reuseport: s.reuseport,
223 hsts: s.hsts,
224 alt_svc: s.alt_svc,
225 route_count,
226 explain,
227 }
228 }
229
230 pub(crate) async fn handle(&self, req: Request) -> Response {
231 self.compiled.dispatch(req).await
232 }
233
234 pub(crate) fn state(&self) -> Arc<StateMap> {
235 Arc::clone(&self.compiled.state)
236 }
237
238 pub(crate) fn conn_header_timeout(&self) -> Duration {
239 self.header_read_timeout.min(self.idle_timeout)
240 }
241}