A now defunct web server engine that is notable for its overuse of unsafe code, the memory safety bugs caused by that, and its deletion by its creator.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

600 lines
18 KiB

  1. use std::marker::PhantomData;
  2. use std::sync::{Arc, Mutex};
  3. use std::{fmt, io, net};
  4. use actix_http::{body::MessageBody, Error, HttpService, KeepAlive, Request, Response};
  5. use actix_server::{Server, ServerBuilder};
  6. use actix_service::{map_config, IntoServiceFactory, Service, ServiceFactory};
  7. use net2::TcpBuilder;
  8. #[cfg(unix)]
  9. use actix_http::Protocol;
  10. #[cfg(unix)]
  11. use actix_service::pipeline_factory;
  12. #[cfg(unix)]
  13. use futures::future::ok;
  14. #[cfg(feature = "openssl")]
  15. use actix_tls::openssl::{AlpnError, SslAcceptor, SslAcceptorBuilder};
  16. #[cfg(feature = "rustls")]
  17. use actix_tls::rustls::ServerConfig as RustlsServerConfig;
  18. use crate::config::AppConfig;
  19. struct Socket {
  20. scheme: &'static str,
  21. addr: net::SocketAddr,
  22. }
  23. struct Config {
  24. host: Option<String>,
  25. keep_alive: KeepAlive,
  26. client_timeout: u64,
  27. client_shutdown: u64,
  28. }
  29. /// An HTTP Server.
  30. ///
  31. /// Create new http server with application factory.
  32. ///
  33. /// ```rust
  34. /// use std::io;
  35. /// use actix_web::{web, App, HttpResponse, HttpServer};
  36. ///
  37. /// fn main() -> io::Result<()> {
  38. /// let sys = actix_rt::System::new("example"); // <- create Actix runtime
  39. ///
  40. /// HttpServer::new(
  41. /// || App::new()
  42. /// .service(web::resource("/").to(|| HttpResponse::Ok())))
  43. /// .bind("127.0.0.1:59090")?
  44. /// .start();
  45. ///
  46. /// # actix_rt::System::current().stop();
  47. /// sys.run()
  48. /// }
  49. /// ```
  50. pub struct HttpServer<F, I, S, B>
  51. where
  52. F: Fn() -> I + Send + Clone + 'static,
  53. I: IntoServiceFactory<S>,
  54. S: ServiceFactory<Config = AppConfig, Request = Request>,
  55. S::Error: Into<Error>,
  56. S::InitError: fmt::Debug,
  57. S::Response: Into<Response<B>>,
  58. B: MessageBody,
  59. {
  60. pub(super) factory: F,
  61. config: Arc<Mutex<Config>>,
  62. backlog: i32,
  63. sockets: Vec<Socket>,
  64. builder: ServerBuilder,
  65. _t: PhantomData<(S, B)>,
  66. }
  67. impl<F, I, S, B> HttpServer<F, I, S, B>
  68. where
  69. F: Fn() -> I + Send + Clone + 'static,
  70. I: IntoServiceFactory<S>,
  71. S: ServiceFactory<Config = AppConfig, Request = Request>,
  72. S::Error: Into<Error> + 'static,
  73. S::InitError: fmt::Debug,
  74. S::Response: Into<Response<B>> + 'static,
  75. <S::Service as Service>::Future: 'static,
  76. B: MessageBody + 'static,
  77. {
  78. /// Create new http server with application factory
  79. pub fn new(factory: F) -> Self {
  80. HttpServer {
  81. factory,
  82. config: Arc::new(Mutex::new(Config {
  83. host: None,
  84. keep_alive: KeepAlive::Timeout(5),
  85. client_timeout: 5000,
  86. client_shutdown: 5000,
  87. })),
  88. backlog: 1024,
  89. sockets: Vec::new(),
  90. builder: ServerBuilder::default(),
  91. _t: PhantomData,
  92. }
  93. }
  94. /// Set number of workers to start.
  95. ///
  96. /// By default http server uses number of available logical cpu as threads
  97. /// count.
  98. pub fn workers(mut self, num: usize) -> Self {
  99. self.builder = self.builder.workers(num);
  100. self
  101. }
  102. /// Set the maximum number of pending connections.
  103. ///
  104. /// This refers to the number of clients that can be waiting to be served.
  105. /// Exceeding this number results in the client getting an error when
  106. /// attempting to connect. It should only affect servers under significant
  107. /// load.
  108. ///
  109. /// Generally set in the 64-2048 range. Default value is 2048.
  110. ///
  111. /// This method should be called before `bind()` method call.
  112. pub fn backlog(mut self, backlog: i32) -> Self {
  113. self.backlog = backlog;
  114. self.builder = self.builder.backlog(backlog);
  115. self
  116. }
  117. /// Sets the maximum per-worker number of concurrent connections.
  118. ///
  119. /// All socket listeners will stop accepting connections when this limit is reached
  120. /// for each worker.
  121. ///
  122. /// By default max connections is set to a 25k.
  123. pub fn maxconn(mut self, num: usize) -> Self {
  124. self.builder = self.builder.maxconn(num);
  125. self
  126. }
  127. /// Sets the maximum per-worker concurrent connection establish process.
  128. ///
  129. /// All listeners will stop accepting connections when this limit is reached. It
  130. /// can be used to limit the global SSL CPU usage.
  131. ///
  132. /// By default max connections is set to a 256.
  133. pub fn maxconnrate(self, num: usize) -> Self {
  134. actix_tls::max_concurrent_ssl_connect(num);
  135. self
  136. }
  137. /// Set server keep-alive setting.
  138. ///
  139. /// By default keep alive is set to a 5 seconds.
  140. pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self {
  141. self.config.lock().unwrap().keep_alive = val.into();
  142. self
  143. }
  144. /// Set server client timeout in milliseconds for first request.
  145. ///
  146. /// Defines a timeout for reading client request header. If a client does not transmit
  147. /// the entire set headers within this time, the request is terminated with
  148. /// the 408 (Request Time-out) error.
  149. ///
  150. /// To disable timeout set value to 0.
  151. ///
  152. /// By default client timeout is set to 5000 milliseconds.
  153. pub fn client_timeout(self, val: u64) -> Self {
  154. self.config.lock().unwrap().client_timeout = val;
  155. self
  156. }
  157. /// Set server connection shutdown timeout in milliseconds.
  158. ///
  159. /// Defines a timeout for shutdown connection. If a shutdown procedure does not complete
  160. /// within this time, the request is dropped.
  161. ///
  162. /// To disable timeout set value to 0.
  163. ///
  164. /// By default client timeout is set to 5000 milliseconds.
  165. pub fn client_shutdown(self, val: u64) -> Self {
  166. self.config.lock().unwrap().client_shutdown = val;
  167. self
  168. }
  169. /// Set server host name.
  170. ///
  171. /// Host name is used by application router as a hostname for url generation.
  172. /// Check [ConnectionInfo](./dev/struct.ConnectionInfo.html#method.host)
  173. /// documentation for more information.
  174. ///
  175. /// By default host name is set to a "localhost" value.
  176. pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
  177. self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
  178. self
  179. }
  180. /// Stop actix system.
  181. pub fn system_exit(mut self) -> Self {
  182. self.builder = self.builder.system_exit();
  183. self
  184. }
  185. /// Disable signal handling
  186. pub fn disable_signals(mut self) -> Self {
  187. self.builder = self.builder.disable_signals();
  188. self
  189. }
  190. /// Timeout for graceful workers shutdown.
  191. ///
  192. /// After receiving a stop signal, workers have this much time to finish
  193. /// serving requests. Workers still alive after the timeout are force
  194. /// dropped.
  195. ///
  196. /// By default shutdown timeout sets to 30 seconds.
  197. pub fn shutdown_timeout(mut self, sec: u64) -> Self {
  198. self.builder = self.builder.shutdown_timeout(sec);
  199. self
  200. }
  201. /// Get addresses of bound sockets.
  202. pub fn addrs(&self) -> Vec<net::SocketAddr> {
  203. self.sockets.iter().map(|s| s.addr).collect()
  204. }
  205. /// Get addresses of bound sockets and the scheme for it.
  206. ///
  207. /// This is useful when the server is bound from different sources
  208. /// with some sockets listening on http and some listening on https
  209. /// and the user should be presented with an enumeration of which
  210. /// socket requires which protocol.
  211. pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
  212. self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
  213. }
  214. /// Use listener for accepting incoming connection requests
  215. ///
  216. /// HttpServer does not change any configuration for TcpListener,
  217. /// it needs to be configured before passing it to listen() method.
  218. pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
  219. let cfg = self.config.clone();
  220. let factory = self.factory.clone();
  221. let addr = lst.local_addr().unwrap();
  222. self.sockets.push(Socket {
  223. addr,
  224. scheme: "http",
  225. });
  226. self.builder = self.builder.listen(
  227. format!("actix-web-service-{}", addr),
  228. lst,
  229. move || {
  230. let c = cfg.lock().unwrap();
  231. let cfg = AppConfig::new(
  232. false,
  233. addr,
  234. c.host.clone().unwrap_or_else(|| format!("{}", addr)),
  235. );
  236. HttpService::build()
  237. .keep_alive(c.keep_alive)
  238. .client_timeout(c.client_timeout)
  239. .local_addr(addr)
  240. .finish(map_config(factory(), move |_| cfg.clone()))
  241. .tcp()
  242. },
  243. )?;
  244. Ok(self)
  245. }
  246. #[cfg(feature = "openssl")]
  247. /// Use listener for accepting incoming tls connection requests
  248. ///
  249. /// This method sets alpn protocols to "h2" and "http/1.1"
  250. pub fn listen_openssl(
  251. self,
  252. lst: net::TcpListener,
  253. builder: SslAcceptorBuilder,
  254. ) -> io::Result<Self> {
  255. self.listen_ssl_inner(lst, openssl_acceptor(builder)?)
  256. }
  257. #[cfg(feature = "openssl")]
  258. fn listen_ssl_inner(
  259. mut self,
  260. lst: net::TcpListener,
  261. acceptor: SslAcceptor,
  262. ) -> io::Result<Self> {
  263. let factory = self.factory.clone();
  264. let cfg = self.config.clone();
  265. let addr = lst.local_addr().unwrap();
  266. self.sockets.push(Socket {
  267. addr,
  268. scheme: "https",
  269. });
  270. self.builder = self.builder.listen(
  271. format!("actix-web-service-{}", addr),
  272. lst,
  273. move || {
  274. let c = cfg.lock().unwrap();
  275. let cfg = AppConfig::new(
  276. true,
  277. addr,
  278. c.host.clone().unwrap_or_else(|| format!("{}", addr)),
  279. );
  280. HttpService::build()
  281. .keep_alive(c.keep_alive)
  282. .client_timeout(c.client_timeout)
  283. .client_disconnect(c.client_shutdown)
  284. .finish(map_config(factory(), move |_| cfg.clone()))
  285. .openssl(acceptor.clone())
  286. },
  287. )?;
  288. Ok(self)
  289. }
  290. #[cfg(feature = "rustls")]
  291. /// Use listener for accepting incoming tls connection requests
  292. ///
  293. /// This method sets alpn protocols to "h2" and "http/1.1"
  294. pub fn listen_rustls(
  295. self,
  296. lst: net::TcpListener,
  297. config: RustlsServerConfig,
  298. ) -> io::Result<Self> {
  299. self.listen_rustls_inner(lst, config)
  300. }
  301. #[cfg(feature = "rustls")]
  302. fn listen_rustls_inner(
  303. mut self,
  304. lst: net::TcpListener,
  305. config: RustlsServerConfig,
  306. ) -> io::Result<Self> {
  307. let factory = self.factory.clone();
  308. let cfg = self.config.clone();
  309. let addr = lst.local_addr().unwrap();
  310. self.sockets.push(Socket {
  311. addr,
  312. scheme: "https",
  313. });
  314. self.builder = self.builder.listen(
  315. format!("actix-web-service-{}", addr),
  316. lst,
  317. move || {
  318. let c = cfg.lock().unwrap();
  319. let cfg = AppConfig::new(
  320. true,
  321. addr,
  322. c.host.clone().unwrap_or_else(|| format!("{}", addr)),
  323. );
  324. HttpService::build()
  325. .keep_alive(c.keep_alive)
  326. .client_timeout(c.client_timeout)
  327. .client_disconnect(c.client_shutdown)
  328. .finish(map_config(factory(), move |_| cfg.clone()))
  329. .rustls(config.clone())
  330. },
  331. )?;
  332. Ok(self)
  333. }
  334. /// The socket address to bind
  335. ///
  336. /// To bind multiple addresses this method can be called multiple times.
  337. pub fn bind<A: net::ToSocketAddrs>(mut self, addr: A) -> io::Result<Self> {
  338. let sockets = self.bind2(addr)?;
  339. for lst in sockets {
  340. self = self.listen(lst)?;
  341. }
  342. Ok(self)
  343. }
  344. fn bind2<A: net::ToSocketAddrs>(
  345. &self,
  346. addr: A,
  347. ) -> io::Result<Vec<net::TcpListener>> {
  348. let mut err = None;
  349. let mut succ = false;
  350. let mut sockets = Vec::new();
  351. for addr in addr.to_socket_addrs()? {
  352. match create_tcp_listener(addr, self.backlog) {
  353. Ok(lst) => {
  354. succ = true;
  355. sockets.push(lst);
  356. }
  357. Err(e) => err = Some(e),
  358. }
  359. }
  360. if !succ {
  361. if let Some(e) = err.take() {
  362. Err(e)
  363. } else {
  364. Err(io::Error::new(
  365. io::ErrorKind::Other,
  366. "Can not bind to address.",
  367. ))
  368. }
  369. } else {
  370. Ok(sockets)
  371. }
  372. }
  373. #[cfg(feature = "openssl")]
  374. /// Start listening for incoming tls connections.
  375. ///
  376. /// This method sets alpn protocols to "h2" and "http/1.1"
  377. pub fn bind_openssl<A>(
  378. mut self,
  379. addr: A,
  380. builder: SslAcceptorBuilder,
  381. ) -> io::Result<Self>
  382. where
  383. A: net::ToSocketAddrs,
  384. {
  385. let sockets = self.bind2(addr)?;
  386. let acceptor = openssl_acceptor(builder)?;
  387. for lst in sockets {
  388. self = self.listen_ssl_inner(lst, acceptor.clone())?;
  389. }
  390. Ok(self)
  391. }
  392. #[cfg(feature = "rustls")]
  393. /// Start listening for incoming tls connections.
  394. ///
  395. /// This method sets alpn protocols to "h2" and "http/1.1"
  396. pub fn bind_rustls<A: net::ToSocketAddrs>(
  397. mut self,
  398. addr: A,
  399. config: RustlsServerConfig,
  400. ) -> io::Result<Self> {
  401. let sockets = self.bind2(addr)?;
  402. for lst in sockets {
  403. self = self.listen_rustls_inner(lst, config.clone())?;
  404. }
  405. Ok(self)
  406. }
  407. #[cfg(unix)]
  408. /// Start listening for unix domain connections on existing listener.
  409. ///
  410. /// This method is available with `uds` feature.
  411. pub fn listen_uds(
  412. mut self,
  413. lst: std::os::unix::net::UnixListener,
  414. ) -> io::Result<Self> {
  415. use actix_rt::net::UnixStream;
  416. let cfg = self.config.clone();
  417. let factory = self.factory.clone();
  418. let socket_addr = net::SocketAddr::new(
  419. net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)),
  420. 8080,
  421. );
  422. self.sockets.push(Socket {
  423. scheme: "http",
  424. addr: socket_addr,
  425. });
  426. let addr = format!("actix-web-service-{:?}", lst.local_addr()?);
  427. self.builder = self.builder.listen_uds(addr, lst, move || {
  428. let c = cfg.lock().unwrap();
  429. let config = AppConfig::new(
  430. false,
  431. socket_addr,
  432. c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
  433. );
  434. pipeline_factory(|io: UnixStream| ok((io, Protocol::Http1, None))).and_then(
  435. HttpService::build()
  436. .keep_alive(c.keep_alive)
  437. .client_timeout(c.client_timeout)
  438. .finish(map_config(factory(), move |_| config.clone())),
  439. )
  440. })?;
  441. Ok(self)
  442. }
  443. #[cfg(unix)]
  444. /// Start listening for incoming unix domain connections.
  445. ///
  446. /// This method is available with `uds` feature.
  447. pub fn bind_uds<A>(mut self, addr: A) -> io::Result<Self>
  448. where
  449. A: AsRef<std::path::Path>,
  450. {
  451. use actix_rt::net::UnixStream;
  452. let cfg = self.config.clone();
  453. let factory = self.factory.clone();
  454. let socket_addr = net::SocketAddr::new(
  455. net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)),
  456. 8080,
  457. );
  458. self.sockets.push(Socket {
  459. scheme: "http",
  460. addr: socket_addr,
  461. });
  462. self.builder = self.builder.bind_uds(
  463. format!("actix-web-service-{:?}", addr.as_ref()),
  464. addr,
  465. move || {
  466. let c = cfg.lock().unwrap();
  467. let config = AppConfig::new(
  468. false,
  469. socket_addr,
  470. c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
  471. );
  472. pipeline_factory(|io: UnixStream| ok((io, Protocol::Http1, None)))
  473. .and_then(
  474. HttpService::build()
  475. .keep_alive(c.keep_alive)
  476. .client_timeout(c.client_timeout)
  477. .finish(map_config(factory(), move |_| config.clone())),
  478. )
  479. },
  480. )?;
  481. Ok(self)
  482. }
  483. }
  484. impl<F, I, S, B> HttpServer<F, I, S, B>
  485. where
  486. F: Fn() -> I + Send + Clone + 'static,
  487. I: IntoServiceFactory<S>,
  488. S: ServiceFactory<Config = AppConfig, Request = Request>,
  489. S::Error: Into<Error>,
  490. S::InitError: fmt::Debug,
  491. S::Response: Into<Response<B>>,
  492. S::Service: 'static,
  493. B: MessageBody,
  494. {
  495. /// Start listening for incoming connections.
  496. ///
  497. /// This method starts number of http workers in separate threads.
  498. /// For each address this method starts separate thread which does
  499. /// `accept()` in a loop.
  500. ///
  501. /// This methods panics if no socket address can be bound or an `Actix` system is not yet
  502. /// configured.
  503. ///
  504. /// ```rust,no_run
  505. /// use std::io;
  506. /// use actix_web::{web, App, HttpResponse, HttpServer};
  507. ///
  508. /// #[actix_rt::main]
  509. /// async fn main() -> io::Result<()> {
  510. /// HttpServer::new(|| App::new().service(web::resource("/").to(|| HttpResponse::Ok())))
  511. /// .bind("127.0.0.1:0")?
  512. /// .start()
  513. /// .await
  514. /// }
  515. /// ```
  516. pub fn start(self) -> Server {
  517. self.builder.start()
  518. }
  519. }
  520. fn create_tcp_listener(
  521. addr: net::SocketAddr,
  522. backlog: i32,
  523. ) -> io::Result<net::TcpListener> {
  524. let builder = match addr {
  525. net::SocketAddr::V4(_) => TcpBuilder::new_v4()?,
  526. net::SocketAddr::V6(_) => TcpBuilder::new_v6()?,
  527. };
  528. builder.reuse_address(true)?;
  529. builder.bind(addr)?;
  530. Ok(builder.listen(backlog)?)
  531. }
  532. #[cfg(feature = "openssl")]
  533. /// Configure `SslAcceptorBuilder` with custom server flags.
  534. fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
  535. builder.set_alpn_select_callback(|_, protos| {
  536. const H2: &[u8] = b"\x02h2";
  537. const H11: &[u8] = b"\x08http/1.1";
  538. if protos.windows(3).any(|window| window == H2) {
  539. Ok(b"h2")
  540. } else if protos.windows(9).any(|window| window == H11) {
  541. Ok(b"http/1.1")
  542. } else {
  543. Err(AlpnError::NOACK)
  544. }
  545. });
  546. builder.set_alpn_protos(b"\x08http/1.1\x02h2")?;
  547. Ok(builder.build())
  548. }