http_server.rs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. /*************************************************************************
  2. *
  3. * Copyright (C) 2018-2025 Ruilin Peng (Nick) <[email protected]>.
  4. *
  5. * smartdns is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * smartdns is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. extern crate cfg_if;
  19. use crate::data_server::*;
  20. use crate::dns_log;
  21. use crate::http_api_msg::*;
  22. use crate::http_jwt::*;
  23. use crate::http_server_api::*;
  24. use crate::plugin::SmartdnsPlugin;
  25. use crate::smartdns::*;
  26. use crate::utils;
  27. use bytes::Bytes;
  28. use http_body_util::Full;
  29. use hyper::body;
  30. use hyper::header::HeaderValue;
  31. use hyper::StatusCode;
  32. use hyper::{service::service_fn, Request, Response};
  33. use hyper_util::rt::TokioIo;
  34. use hyper_util::server::conn::auto;
  35. use std::convert::Infallible;
  36. use std::error::Error;
  37. use std::fs::Metadata;
  38. use std::net::SocketAddr;
  39. use std::path::PathBuf;
  40. use std::path::{Component, Path};
  41. use std::sync::MutexGuard;
  42. use std::sync::Weak;
  43. use std::sync::{Arc, Mutex};
  44. use std::time::Duration;
  45. use std::time::Instant;
  46. use tokio::fs::read;
  47. use tokio::net::TcpListener;
  48. use tokio::net::TcpStream;
  49. use tokio::sync::mpsc;
  50. use tokio::task::JoinHandle;
  51. cfg_if::cfg_if! {
  52. if #[cfg(feature = "https")] {
  53. use rustls_pemfile;
  54. use std::io::BufReader;
  55. use tokio_rustls::{rustls, TlsAcceptor};
  56. }
  57. }
  58. const HTTP_SERVER_DEFAULT_PASSWORD: &str = "password";
  59. const HTTP_SERVER_DEFAULT_USERNAME: &str = "admin";
  60. const HTTP_SERVER_DEFAULT_WWW_ROOT: &str = "/usr/share/smartdns/wwwroot";
  61. const HTTP_SERVER_DEFAULT_IPV6: &str = "http://[::]:6080";
  62. const HTTP_SERVER_DEFAULT_IP: &str = "http://0.0.0.0:6080";
  63. #[derive(Clone)]
  64. pub struct HttpServerConfig {
  65. pub http_ip: String,
  66. pub http_root: String,
  67. pub username: String,
  68. pub password: String,
  69. pub token_expired_time: u32,
  70. pub enable_cors: bool,
  71. pub enable_terminal: bool,
  72. }
  73. impl HttpServerConfig {
  74. pub fn new() -> Self {
  75. let host_ip = if utils::is_ipv6_supported() {
  76. HTTP_SERVER_DEFAULT_IPV6.to_string()
  77. } else {
  78. HTTP_SERVER_DEFAULT_IP.to_string()
  79. };
  80. HttpServerConfig {
  81. http_ip: host_ip,
  82. http_root: HTTP_SERVER_DEFAULT_WWW_ROOT.to_string(),
  83. username: HTTP_SERVER_DEFAULT_USERNAME.to_string(),
  84. password: utils::hash_password(HTTP_SERVER_DEFAULT_PASSWORD, Some(1000)).unwrap(),
  85. token_expired_time: 600,
  86. enable_cors: false,
  87. enable_terminal: false,
  88. }
  89. }
  90. pub fn settings_map(&self) -> std::collections::HashMap<String, String> {
  91. let mut map = std::collections::HashMap::new();
  92. map.insert("http_ip".to_string(), self.http_ip.clone());
  93. map.insert("username".to_string(), self.username.clone());
  94. map.insert(
  95. "token_expired_time".to_string(),
  96. self.token_expired_time.to_string(),
  97. );
  98. map.insert("enable_cors".to_string(), self.enable_cors.to_string());
  99. map.insert(
  100. "enable_terminal".to_string(),
  101. self.enable_terminal.to_string(),
  102. );
  103. map
  104. }
  105. pub fn load_config(&mut self, data_server: Arc<DataServer>) -> Result<(), Box<dyn Error>> {
  106. if let Some(password) = data_server.get_config("smartdns-ui.password") {
  107. self.password = password;
  108. } else {
  109. if let Some(password_from_file) =
  110. data_server.get_server_config_from_file("smartdns-ui.password")
  111. {
  112. self.password =
  113. utils::hash_password(password_from_file.as_str(), Some(10000)).unwrap();
  114. }
  115. }
  116. if let Some(username) = data_server.get_server_config("smartdns-ui.username") {
  117. self.username = username;
  118. }
  119. if let Some(enable_cors) = data_server.get_server_config("smartdns-ui.enable-cors") {
  120. if enable_cors.eq_ignore_ascii_case("yes") || enable_cors.eq_ignore_ascii_case("true") {
  121. self.enable_cors = true;
  122. } else {
  123. self.enable_cors = false;
  124. }
  125. }
  126. if let Some(enable_terminal) = data_server.get_server_config("smartdns-ui.enable-terminal")
  127. {
  128. if enable_terminal.eq_ignore_ascii_case("yes")
  129. || enable_terminal.eq_ignore_ascii_case("true")
  130. {
  131. self.enable_terminal = true;
  132. } else {
  133. self.enable_terminal = false;
  134. }
  135. }
  136. Ok(())
  137. }
  138. }
  139. pub struct HttpServerControl {
  140. http_server: Arc<HttpServer>,
  141. server_thread: Mutex<Option<JoinHandle<()>>>,
  142. plugin: Mutex<Weak<SmartdnsPlugin>>,
  143. }
  144. #[allow(dead_code)]
  145. impl HttpServerControl {
  146. pub fn new() -> Self {
  147. HttpServerControl {
  148. http_server: Arc::new(HttpServer::new()),
  149. server_thread: Mutex::new(None),
  150. plugin: Mutex::new(Weak::new()),
  151. }
  152. }
  153. pub fn set_plugin(&self, plugin: Arc<SmartdnsPlugin>) {
  154. *self.plugin.lock().unwrap() = Arc::downgrade(&plugin);
  155. }
  156. pub fn get_plugin(&self) -> Result<Arc<SmartdnsPlugin>, Box<dyn Error>> {
  157. let plugin = match self.plugin.lock() {
  158. Ok(plugin) => plugin,
  159. Err(_) => return Err("Failed to lock plugin mutex".into()),
  160. };
  161. if let Some(plugin) = plugin.upgrade() {
  162. return Ok(plugin);
  163. }
  164. Err("Plugin is not set".into())
  165. }
  166. pub fn get_http_server(&self) -> Arc<HttpServer> {
  167. Arc::clone(&self.http_server)
  168. }
  169. pub fn start_http_server(&self, conf: &HttpServerConfig) -> Result<(), Box<dyn Error>> {
  170. dns_log!(LogLevel::INFO, "start smartdns-ui server.");
  171. let inner_clone = Arc::clone(&self.http_server);
  172. let ret = inner_clone.set_conf(conf);
  173. if let Err(e) = ret {
  174. return Err(e);
  175. }
  176. let plugin = self.get_plugin()?;
  177. inner_clone.set_plugin(plugin.clone());
  178. let (tx, rx) = tokio::sync::oneshot::channel::<i32>();
  179. let rt = plugin.get_runtime();
  180. let server_thread = rt.spawn(async move {
  181. let ret = HttpServer::http_server_loop(inner_clone, tx).await;
  182. if let Err(e) = ret {
  183. dns_log!(LogLevel::ERROR, "http server error: {}", e);
  184. Plugin::smartdns_exit(1);
  185. }
  186. dns_log!(LogLevel::INFO, "http server exit.");
  187. });
  188. tokio::task::block_in_place(|| {
  189. let _ = rt.block_on(rx);
  190. });
  191. *self.server_thread.lock().unwrap() = Some(server_thread);
  192. Ok(())
  193. }
  194. pub fn stop_http_server(&self) {
  195. let mut server_thread = self.server_thread.lock().unwrap();
  196. if server_thread.is_none() {
  197. return;
  198. }
  199. dns_log!(LogLevel::INFO, "stop smartdns-ui server.");
  200. self.http_server.stop_http_server();
  201. if let Some(server_thread) = server_thread.take() {
  202. let plugin = self.get_plugin();
  203. if plugin.is_err() {
  204. dns_log!(
  205. LogLevel::ERROR,
  206. "get plugin error: {}",
  207. plugin.err().unwrap()
  208. );
  209. return;
  210. }
  211. let plugin = plugin.unwrap();
  212. let rt = plugin.get_runtime();
  213. tokio::task::block_in_place(|| {
  214. if let Err(e) = rt.block_on(server_thread) {
  215. dns_log!(LogLevel::ERROR, "http server stop error: {}", e);
  216. }
  217. });
  218. }
  219. }
  220. }
  221. impl Drop for HttpServerControl {
  222. fn drop(&mut self) {
  223. self.stop_http_server();
  224. }
  225. }
  226. #[derive(Clone)]
  227. pub struct TokioExecutor;
  228. impl<F> hyper::rt::Executor<F> for TokioExecutor
  229. where
  230. F: std::future::Future + Send + 'static,
  231. F::Output: Send + 'static,
  232. {
  233. fn execute(&self, fut: F) {
  234. tokio::task::spawn(fut);
  235. }
  236. }
  237. pub struct HttpServer {
  238. conf: Mutex<HttpServerConfig>,
  239. notify_tx: Option<mpsc::Sender<()>>,
  240. notify_rx: Mutex<Option<mpsc::Receiver<()>>>,
  241. api: API,
  242. local_addr: Mutex<Option<SocketAddr>>,
  243. mime_map: std::collections::HashMap<&'static str, &'static str>,
  244. login_attempts: Mutex<(i32, Instant)>,
  245. plugin: Mutex<Weak<SmartdnsPlugin>>,
  246. }
  247. #[allow(dead_code)]
  248. impl HttpServer {
  249. fn new() -> Self {
  250. let mut plugin = HttpServer {
  251. conf: Mutex::new(HttpServerConfig::new()),
  252. notify_tx: None,
  253. notify_rx: Mutex::new(None),
  254. api: API::new(),
  255. local_addr: Mutex::new(None),
  256. login_attempts: Mutex::new((0, Instant::now())),
  257. plugin: Mutex::new(Weak::new()),
  258. mime_map: std::collections::HashMap::from([
  259. /* text */
  260. ("htm", "text/html"),
  261. ("html", "text/html"),
  262. ("js", "text/javascript"),
  263. ("css", "text/css"),
  264. ("txt", "text/plain"),
  265. ("conf", "text/plain"),
  266. ("xml", "text/xml"),
  267. ("csv", "text/csv"),
  268. ("md", "text/markdown"),
  269. /* image */
  270. ("png", "image/png"),
  271. ("gif", "image/gif"),
  272. ("jpeg", "image/jpeg"),
  273. ("svg", "image/svg+xml"),
  274. ("ico", "image/x-icon"),
  275. ("bmp", "image/bmp"),
  276. ("avif", "image/avif"),
  277. /* video */
  278. ("mpeg", "video/mpeg"),
  279. ("mp4", "video/mp4"),
  280. ("webm", "video/webm"),
  281. /* audio */
  282. ("mp3", "audio/mpeg"),
  283. ("ogg", "audio/ogg"),
  284. ("wav", "audio/wav"),
  285. /* font */
  286. ("woff", "font/woff"),
  287. ("woff2", "font/woff2"),
  288. ("ttf", "font/ttf"),
  289. ("otf", "font/otf"),
  290. /* application */
  291. ("wasm", "application/wasm"),
  292. ("pdf", "application/pdf"),
  293. ("json", "application/json"),
  294. ("tar", "application/x-tar"),
  295. ("zip", "application/zip"),
  296. ]),
  297. };
  298. let (tx, rx) = mpsc::channel(100);
  299. plugin.notify_tx = Some(tx);
  300. plugin.notify_rx = Mutex::new(Some(rx));
  301. plugin
  302. }
  303. pub fn get_conf(&self) -> HttpServerConfig {
  304. let conf = self.conf.lock().unwrap();
  305. conf.clone()
  306. }
  307. pub fn get_conf_mut(&'_ self) -> MutexGuard<'_, HttpServerConfig> {
  308. self.conf.lock().unwrap()
  309. }
  310. pub fn login_attempts_reset(&self) {
  311. let mut attempts = self.login_attempts.lock().unwrap();
  312. attempts.0 = 0;
  313. attempts.1 = Instant::now();
  314. }
  315. pub fn login_attempts_check(&self) -> bool {
  316. let mut attempts = self.login_attempts.lock().unwrap();
  317. if attempts.0 == 0 {
  318. attempts.1 = Instant::now();
  319. }
  320. attempts.0 += 1;
  321. if attempts.0 > 5 {
  322. let now = Instant::now();
  323. let duration = now.duration_since(attempts.1);
  324. if duration.as_secs() < 60 {
  325. if duration.as_secs() < 30 {
  326. attempts.1 = Instant::now();
  327. }
  328. return false;
  329. }
  330. attempts.0 = 0;
  331. attempts.1 = now;
  332. }
  333. true
  334. }
  335. pub fn get_local_addr(&self) -> Option<SocketAddr> {
  336. let local_addr = self.local_addr.lock().unwrap();
  337. local_addr.clone()
  338. }
  339. fn set_conf(&self, conf: &HttpServerConfig) -> Result<(), Box<dyn Error>> {
  340. let mut conf_clone = self.conf.lock().unwrap();
  341. *conf_clone = conf.clone();
  342. dns_log!(LogLevel::INFO, "http server URI: {}", conf_clone.http_ip);
  343. dns_log!(
  344. LogLevel::INFO,
  345. "http server www root: {}",
  346. conf_clone.http_root
  347. );
  348. Ok(())
  349. }
  350. fn set_plugin(&self, plugin: Arc<SmartdnsPlugin>) {
  351. let mut _plugin = self.plugin.lock().unwrap();
  352. *_plugin = Arc::downgrade(&plugin);
  353. }
  354. fn get_plugin(&self) -> Result<Arc<SmartdnsPlugin>, Box<dyn Error>> {
  355. let plugin = match self.plugin.lock() {
  356. Ok(plugin) => plugin,
  357. Err(_) => return Err("Failed to lock plugin mutex".into()),
  358. };
  359. if let Some(plugin) = plugin.upgrade() {
  360. return Ok(plugin);
  361. }
  362. Err("Plugin is not set".into())
  363. }
  364. pub fn is_https_server(&self) -> bool {
  365. let http_ip = self.get_conf().http_ip;
  366. if http_ip.parse::<url::Url>().is_err() {
  367. return false;
  368. }
  369. let binding = http_ip.parse::<url::Url>().unwrap();
  370. let scheme = binding.scheme();
  371. if scheme == "https" {
  372. return true;
  373. }
  374. false
  375. }
  376. pub fn get_data_server(&self) -> Arc<DataServer> {
  377. self.get_plugin().unwrap().get_data_server()
  378. }
  379. pub fn get_token_from_header(
  380. req: &Request<body::Incoming>,
  381. ) -> Result<Option<String>, Box<dyn Error>> {
  382. let token: String;
  383. let header_auth = req.headers().get("Authorization");
  384. if header_auth.is_none() {
  385. let cookie = req.headers().get("Cookie");
  386. if cookie.is_none() {
  387. return Ok(None);
  388. }
  389. let cookie = cookie.unwrap().to_str();
  390. if let Err(_) = cookie {
  391. return Ok(None);
  392. }
  393. let cookies = cookie.unwrap().split(';').collect::<Vec<&str>>();
  394. let token_cookie = cookies.iter().find(|c| c.trim().starts_with("token="));
  395. if token_cookie.is_none() {
  396. return Ok(None);
  397. }
  398. let token_cookie = token_cookie.unwrap().trim().strip_prefix("token=");
  399. if token_cookie.is_none() {
  400. return Ok(None);
  401. }
  402. let data = urlencoding::decode(token_cookie.unwrap());
  403. if let Err(_) = data {
  404. return Ok(None);
  405. }
  406. let data = data.unwrap();
  407. token = data.to_string();
  408. } else {
  409. let auth = header_auth.unwrap().to_str();
  410. if let Err(_) = auth {
  411. return Ok(None);
  412. }
  413. token = auth.unwrap().to_string();
  414. }
  415. let token_type = "Bearer";
  416. if !token.starts_with(token_type) {
  417. return Err("Invalid authorization type".into());
  418. }
  419. let token = token.strip_prefix(token_type).unwrap().trim();
  420. Ok(Some(token.to_string()))
  421. }
  422. pub fn auth_token_is_valid(
  423. &self,
  424. req: &Request<body::Incoming>,
  425. ) -> Result<bool, Box<dyn Error>> {
  426. let token = HttpServer::get_token_from_header(req)?;
  427. if token.is_none() {
  428. return Ok(false);
  429. }
  430. let token = token.unwrap();
  431. let conf = self.conf.lock().unwrap();
  432. let jwt = Jwt::new(&conf.username, &conf.password, "", conf.token_expired_time);
  433. if !jwt.is_token_valid(token.as_str()) {
  434. return Ok(false);
  435. }
  436. Ok(true)
  437. }
  438. fn server_add_cors_header(
  439. &self,
  440. origin: &Option<hyper::header::HeaderValue>,
  441. response: &mut Response<Full<Bytes>>,
  442. ) {
  443. if self.get_conf().enable_cors {
  444. if let Some(origin) = origin {
  445. response
  446. .headers_mut()
  447. .insert("Access-Control-Allow-Origin", origin.clone());
  448. } else {
  449. response
  450. .headers_mut()
  451. .insert("Access-Control-Allow-Origin", "*".parse().unwrap());
  452. }
  453. response.headers_mut().insert(
  454. "Access-Control-Allow-Methods",
  455. "GET, POST, PUT, DELETE, OPTIONS, PATCH".parse().unwrap(),
  456. );
  457. response.headers_mut().insert(
  458. "Access-Control-Allow-Headers",
  459. "Content-Type, Authorization, Set-Cookie".parse().unwrap(),
  460. );
  461. response
  462. .headers_mut()
  463. .insert("Access-Control-Allow-Credentials", "true".parse().unwrap());
  464. response
  465. .headers_mut()
  466. .insert("Access-Control-Max-Age", "600".parse().unwrap());
  467. }
  468. }
  469. async fn server_handle_http_api_request(
  470. this: Arc<HttpServer>,
  471. req: Request<body::Incoming>,
  472. _path: PathBuf,
  473. ) -> Result<Response<Full<Bytes>>, Box<dyn std::error::Error>> {
  474. let mut origin: Option<HeaderValue> = None;
  475. if let Some(o) = req.headers().get("Origin") {
  476. origin = Some(o.clone());
  477. }
  478. let error_response = |code: StatusCode, msg: &str| {
  479. let bytes = Bytes::from(api_msg_error(msg));
  480. let mut response = Response::new(Full::new(bytes));
  481. response
  482. .headers_mut()
  483. .insert("Content-Type", "application/json".parse().unwrap());
  484. response
  485. .headers_mut()
  486. .insert("Cache-Control", "no-cache".parse().unwrap());
  487. *response.status_mut() = code;
  488. this.server_add_cors_header(&origin, &mut response);
  489. Ok(response)
  490. };
  491. dns_log!(LogLevel::DEBUG, "api request: {:?}", req.uri());
  492. if req.method() == hyper::Method::OPTIONS {
  493. let mut response = Response::new(Full::new(Bytes::from("")));
  494. response
  495. .headers_mut()
  496. .insert("Content-Type", "application/json".parse().unwrap());
  497. response
  498. .headers_mut()
  499. .insert("Cache-Control", "no-cache".parse().unwrap());
  500. this.server_add_cors_header(&origin, &mut response);
  501. return Ok(response);
  502. }
  503. match this.api.get_router(req.method(), req.uri().path()) {
  504. Some((router, param)) => {
  505. if router.auth {
  506. let is_token_valid = this.auth_token_is_valid(&req);
  507. if let Err(e) = is_token_valid {
  508. return error_response(StatusCode::BAD_REQUEST, e.to_string().as_str());
  509. }
  510. if !is_token_valid.unwrap() {
  511. return error_response(StatusCode::UNAUTHORIZED, "Please login.");
  512. }
  513. }
  514. if router.method != req.method() {
  515. return error_response(StatusCode::METHOD_NOT_ALLOWED, "Method Not Allowed");
  516. }
  517. let resp = (router.handler)(this.clone(), param, req).await;
  518. match resp {
  519. Ok(resp) => {
  520. let mut resp = resp;
  521. if resp.headers().get("Content-Type").is_none() {
  522. resp.headers_mut()
  523. .insert("Content-Type", "application/json".parse().unwrap());
  524. }
  525. if resp.headers().get("Cache-Control").is_none() {
  526. resp.headers_mut()
  527. .insert("Cache-Control", "no-cache".parse().unwrap());
  528. }
  529. this.server_add_cors_header(&origin, &mut resp);
  530. Ok(resp)
  531. }
  532. Err(e) => Ok(e.to_response()),
  533. }
  534. }
  535. None => error_response(StatusCode::NOT_FOUND, "API not found."),
  536. }
  537. }
  538. pub fn get_mime_type(&self, file: &str) -> String {
  539. let ext = file.split('.').last().unwrap();
  540. if let Some(mime) = self.mime_map.get(ext) {
  541. return mime.to_string();
  542. }
  543. "application/octet-stream".to_string()
  544. }
  545. async fn server_handle_http_request(
  546. this: Arc<HttpServer>,
  547. req: Request<body::Incoming>,
  548. ) -> Result<Response<Full<Bytes>>, Infallible> {
  549. let path = PathBuf::from(req.uri().path());
  550. let mut is_404 = false;
  551. let www_root = {
  552. let conf = this.conf.lock().unwrap();
  553. PathBuf::from(conf.http_root.clone())
  554. };
  555. let mut path = normalize_path(path.as_path());
  556. if path.starts_with("/") {
  557. path = path.strip_prefix("/").unwrap().to_path_buf();
  558. }
  559. if path.starts_with("api/") {
  560. let ret = HttpServer::server_handle_http_api_request(this, req, path.clone()).await;
  561. if let Err(e) = ret {
  562. dns_log!(LogLevel::ERROR, "api request error: {:?}", e);
  563. let mut response = Response::new(Full::new(Bytes::from("Internal Server Error")));
  564. *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
  565. return Ok(response);
  566. }
  567. let ret = ret.unwrap();
  568. return Ok(ret);
  569. }
  570. dns_log!(LogLevel::DEBUG, "page request: {:?}", req.uri());
  571. let mut filepath = www_root.join(path);
  572. let uri_path = req.uri().path().to_string();
  573. let mut path = uri_path.clone();
  574. if !filepath.exists() || filepath.is_dir() {
  575. let suffix = filepath.extension();
  576. if suffix.is_none() && !uri_path.ends_with("/") {
  577. let check_filepath = filepath.with_extension("html");
  578. if check_filepath.exists() {
  579. filepath = check_filepath;
  580. path = format!("{}.html", uri_path);
  581. }
  582. }
  583. if filepath.is_dir() {
  584. filepath = filepath.join("index.html");
  585. path = format!("{}/index.html", uri_path);
  586. }
  587. if !filepath.exists() {
  588. filepath = www_root.join("404.html");
  589. path = "/404.html".to_string();
  590. if !filepath.exists() {
  591. filepath = www_root.join("index.html");
  592. path = format!("/index.html");
  593. } else {
  594. is_404 = true;
  595. }
  596. }
  597. }
  598. let mut file_meta: Option<Metadata> = None;
  599. let fn_get_etag = |meta: &Metadata| -> String {
  600. let modify_time = meta.modified();
  601. if let Err(_) = modify_time {
  602. return "".to_string();
  603. }
  604. format!(
  605. "{:x}-{:?}",
  606. meta.len(),
  607. modify_time
  608. .unwrap()
  609. .duration_since(std::time::UNIX_EPOCH)
  610. .unwrap()
  611. .as_secs()
  612. )
  613. };
  614. if filepath.exists() {
  615. let meta = filepath.metadata();
  616. if let Ok(meta) = meta {
  617. file_meta = Some(meta);
  618. }
  619. }
  620. let if_none_match = req.headers().get("If-None-Match");
  621. if if_none_match.is_some() && file_meta.is_some() {
  622. let etag = fn_get_etag(&file_meta.as_ref().unwrap());
  623. if etag == if_none_match.unwrap().to_str().unwrap() {
  624. let mut response = Response::new(Full::new(Bytes::from("")));
  625. *response.status_mut() = StatusCode::NOT_MODIFIED;
  626. return Ok(response);
  627. }
  628. }
  629. match read(filepath).await {
  630. Ok(contents) => {
  631. let bytes = Bytes::from(contents);
  632. let bytes_len = bytes.len();
  633. let mut response = Response::new(Full::new(bytes));
  634. let header = response.headers_mut();
  635. header.insert("Content-Length", bytes_len.to_string().parse().unwrap());
  636. header.insert("Content-Type", this.get_mime_type(&path).parse().unwrap());
  637. header.insert("Connection", "keep-alive".parse().unwrap());
  638. header.insert("Keep-Alive", "timeout=60, max=1000".parse().unwrap());
  639. if file_meta.as_ref().is_some() {
  640. let etag = fn_get_etag(&file_meta.as_ref().unwrap());
  641. header.insert("ETag", etag.parse().unwrap());
  642. }
  643. if is_404 {
  644. *response.status_mut() = StatusCode::NOT_FOUND;
  645. } else {
  646. *response.status_mut() = StatusCode::OK;
  647. }
  648. Ok(response)
  649. }
  650. Err(_) => {
  651. let bytes = Bytes::from("Page Not Found");
  652. let mut response = Response::new(Full::new(bytes));
  653. *response.status_mut() = StatusCode::NOT_FOUND;
  654. Ok(response)
  655. }
  656. }
  657. }
  658. async fn http_server_handle_conn(this: Arc<HttpServer>, stream: TcpStream) {
  659. let io = TokioIo::new(stream);
  660. let handle_func = move |req| HttpServer::server_handle_http_request(this.clone(), req);
  661. tokio::task::spawn(async move {
  662. let conn = auto::Builder::new(TokioExecutor)
  663. .serve_connection_with_upgrades(io, service_fn(handle_func))
  664. .await;
  665. if let Err(err) = conn {
  666. dns_log!(LogLevel::DEBUG, "Error serving connection: {:?}", err);
  667. return;
  668. }
  669. });
  670. }
  671. #[cfg(feature = "https")]
  672. async fn https_server_handle_conn(
  673. this: Arc<HttpServer>,
  674. stream: tokio_rustls::server::TlsStream<TcpStream>,
  675. ) {
  676. let io = TokioIo::new(stream);
  677. let handle_func = move |req| HttpServer::server_handle_http_request(this.clone(), req);
  678. tokio::task::spawn(async move {
  679. let conn = auto::Builder::new(TokioExecutor)
  680. .serve_connection_with_upgrades(io, service_fn(handle_func))
  681. .await;
  682. if let Err(err) = conn {
  683. dns_log!(LogLevel::DEBUG, "Error serving connection: {:?}", err);
  684. return;
  685. }
  686. });
  687. }
  688. #[cfg(feature = "https")]
  689. async fn handle_tls_accept(this: Arc<HttpServer>, acceptor: TlsAcceptor, stream: TcpStream) {
  690. tokio::task::spawn(async move {
  691. let acceptor_future = acceptor.accept(stream);
  692. let stream_ssl_tmout =
  693. tokio::time::timeout(tokio::time::Duration::from_secs(60), acceptor_future).await;
  694. if let Err(e) = stream_ssl_tmout {
  695. dns_log!(LogLevel::DEBUG, "tls accept timeout. {}", e);
  696. return;
  697. }
  698. let stream_ret = stream_ssl_tmout.unwrap();
  699. if let Err(e) = stream_ret {
  700. dns_log!(LogLevel::DEBUG, "tls accept error: {}", e);
  701. return;
  702. }
  703. let stream_ssl = stream_ret.unwrap();
  704. HttpServer::https_server_handle_conn(this, stream_ssl).await;
  705. });
  706. }
  707. async fn http_server_loop(
  708. this: Arc<HttpServer>,
  709. kickoff_tx: tokio::sync::oneshot::Sender<i32>,
  710. ) -> Result<(), Box<dyn Error>> {
  711. let addr: String;
  712. let mut rx: mpsc::Receiver<()>;
  713. {
  714. let conf = this.conf.lock().unwrap();
  715. addr = format!("{}", conf.http_ip);
  716. let mut _rx = this.notify_rx.lock().unwrap();
  717. rx = _rx.take().unwrap();
  718. }
  719. let url = addr.parse::<url::Url>()?;
  720. cfg_if::cfg_if! {
  721. if #[cfg(feature = "https")]
  722. {
  723. let mut acceptor = None;
  724. if url.scheme() == "https" {
  725. #[cfg(feature = "https")]
  726. let cert_info = Plugin::smartdns_get_cert()?;
  727. dns_log!(
  728. LogLevel::DEBUG,
  729. "cert: {}, key: {}",
  730. cert_info.cert,
  731. cert_info.key
  732. );
  733. let cert_chain: Result<Vec<rustls::pki_types::CertificateDer<'_>>, _> =
  734. rustls_pemfile::certs(&mut BufReader::new(std::fs::File::open(
  735. cert_info.cert,
  736. )?))
  737. .collect();
  738. let cert_chain = cert_chain.unwrap_or_else(|_| Vec::new());
  739. let key_der = rustls_pemfile::private_key(&mut BufReader::new(
  740. std::fs::File::open(cert_info.key)?,
  741. ))?
  742. .unwrap();
  743. let mut config = rustls::ServerConfig::builder()
  744. .with_no_client_auth()
  745. .with_single_cert(cert_chain, key_der)?;
  746. config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
  747. acceptor = Some(TlsAcceptor::from(Arc::new(config)));
  748. }
  749. } else {
  750. if url.scheme() == "https" {
  751. return Err("https is not supported.".into());
  752. }
  753. }
  754. }
  755. let host = url.host_str().unwrap_or("127.0.0.1");
  756. let port = url.port().unwrap_or(80);
  757. let sock_addr = format!("{}:{}", host, port).parse::<SocketAddr>()?;
  758. let listner = TcpListener::bind(sock_addr).await?;
  759. let addr = listner.local_addr()?;
  760. *this.local_addr.lock().unwrap() = Some(addr);
  761. dns_log!(LogLevel::INFO, "http server listen at {}", url);
  762. let _ = kickoff_tx.send(0);
  763. loop {
  764. tokio::select! {
  765. _ = rx.recv() => {
  766. break;
  767. }
  768. res = listner.accept() => {
  769. match res {
  770. Ok((stream, _)) => {
  771. let sock_ref = socket2::SockRef::from(&stream);
  772. let mut ka = socket2::TcpKeepalive::new();
  773. ka = ka.with_time(Duration::from_secs(60));
  774. ka = ka.with_interval(Duration::from_secs(30));
  775. sock_ref.set_tcp_keepalive(&ka)?;
  776. sock_ref.set_nonblocking(true)?;
  777. sock_ref.tcp_nodelay()?;
  778. if let Err(_) = sock_ref.set_recv_buffer_size(262144) {
  779. dns_log!(LogLevel::DEBUG, "Failed to set recv buffer size");
  780. }
  781. if let Err(_) = sock_ref.set_send_buffer_size(262144) {
  782. dns_log!(LogLevel::DEBUG, "Failed to set send buffer size");
  783. }
  784. cfg_if::cfg_if! {
  785. if #[cfg(feature = "https")]
  786. {
  787. if acceptor.is_some() {
  788. let acceptor = acceptor.clone().unwrap().clone();
  789. let this_clone = this.clone();
  790. HttpServer::handle_tls_accept(this_clone, acceptor, stream).await;
  791. } else {
  792. HttpServer::http_server_handle_conn(this.clone(), stream).await;
  793. }
  794. } else {
  795. HttpServer::http_server_handle_conn(this.clone(), stream).await;
  796. }
  797. }
  798. }
  799. Err(e) => {
  800. dns_log!(LogLevel::ERROR, "accept error: {}", e);
  801. }
  802. }
  803. }
  804. }
  805. }
  806. Ok(())
  807. }
  808. fn stop_http_server(&self) {
  809. if let Some(tx) = self.notify_tx.as_ref().cloned() {
  810. let plugin = match self.get_plugin() {
  811. Ok(plugin) => plugin,
  812. Err(e) => {
  813. dns_log!(LogLevel::ERROR, "get plugin error: {}", e);
  814. return;
  815. }
  816. };
  817. let rt = plugin.get_runtime();
  818. tokio::task::block_in_place(|| {
  819. let _ = rt.block_on(async {
  820. let _ = tx.send(()).await;
  821. });
  822. });
  823. }
  824. }
  825. }
  826. pub fn normalize_path(path: &Path) -> PathBuf {
  827. let mut components = path.components().peekable();
  828. let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
  829. components.next();
  830. PathBuf::from(c.as_os_str())
  831. } else {
  832. PathBuf::new()
  833. };
  834. for component in components {
  835. match component {
  836. Component::Prefix(..) => unreachable!(),
  837. Component::RootDir => {
  838. ret.push(component.as_os_str());
  839. }
  840. Component::CurDir => {}
  841. Component::ParentDir => {
  842. ret.pop();
  843. }
  844. Component::Normal(c) => {
  845. ret.push(c);
  846. }
  847. }
  848. }
  849. ret
  850. }