1use futures_util::future;
2use log::info;
3use std::net::ToSocketAddrs;
4
5use super::handler::NewHandler;
6use super::{bind_server, new_runtime, tcp_listener, StartError};
7
8#[cfg(feature = "testing")]
9pub mod test;
10
11pub fn start<NH, A>(addr: A, new_handler: NH) -> Result<(), StartError>
13where
14 NH: NewHandler + 'static,
15 A: ToSocketAddrs + 'static + Send,
16{
17 start_with_num_threads(addr, new_handler, num_cpus::get())
18}
19
20pub fn start_with_num_threads<NH, A>(
22 addr: A,
23 new_handler: NH,
24 threads: usize,
25) -> Result<(), StartError>
26where
27 NH: NewHandler + 'static,
28 A: ToSocketAddrs + 'static + Send,
29{
30 let runtime = new_runtime(threads);
31 runtime.block_on(init_server(addr, new_handler))
32}
33
34pub async fn init_server<NH, A>(addr: A, new_handler: NH) -> Result<(), StartError>
40where
41 NH: NewHandler + 'static,
42 A: ToSocketAddrs + 'static + Send,
43{
44 let listener = tcp_listener(addr).await?;
45 let addr = listener.local_addr().unwrap();
46
47 info! {
48 target: "gotham::start",
49 " Gotham listening on http://{}", addr
50 }
51
52 bind_server(listener, new_handler, future::ok).await
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use crate::state::State;
59 use hyper::{Body, Response};
60
61 fn handler(_: State) -> (State, Response<Body>) {
62 unimplemented!()
63 }
64
65 #[test]
66 fn test_error_on_invalid_port() {
67 let res = start("0.0.0.0:99999", || Ok(handler));
68 assert!(res.is_err());
69 }
70}