Advertisement
SpiderLordCoder1st

Untitled

Jun 9th, 2025
31
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.42 KB | None | 0 0
  1.  
  2. #[tokio::main]
  3. async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
  4. println!("Starting server...");
  5.  
  6. let db_user = std::env::var("POSTGRES_USER").unwrap_or("gameserver".to_string());
  7. let db_password = std::env::var("POSTGRES_PASSWORD").unwrap_or("gameserverpass".to_string());
  8. let db = std::env::var("POSTGRES_DB").unwrap_or("gameserver_db".to_string());
  9. let db_port = std::env::var("POSTGRES_PORT").unwrap_or("5432".to_string());
  10. let db_host = std::env::var("POSTGRES_HOST").unwrap_or("gameserver-postgres".to_string());
  11.  
  12. let conn = sqlx::postgres::PgPool::connect(&format!("postgres://{}:{}@{}:{}/{}", db_user, db_password, db_host, db_port, db)).await.unwrap();
  13. let database = database::Postgres::new(conn);
  14.  
  15. let verbose = std::env::var("VERBOSE").is_ok();
  16. let base_path = std::env::var("SITE_URL")
  17. .map(|s| {
  18. let mut s = s.trim().to_string();
  19. if !s.is_empty() {
  20. if !s.starts_with('/') { s.insert(0, '/'); }
  21. if s.ends_with('/') && s != "/" { s.pop(); }
  22. }
  23. s
  24. })
  25. .unwrap_or_default();
  26.  
  27. const ENABLE_K8S_CLIENT: bool = true;
  28. const ENABLE_INITIAL_CONNECTION: bool = false;
  29. const FORCE_REBUILD: bool = false;
  30. const BUILD_DOCKER_IMAGE: bool = true;
  31. const BUILD_DEPLOYMENT: bool = true;
  32.  
  33. let (ws_tx, _) = broadcast::channel::<String>(CHANNEL_BUFFER_SIZE);
  34. let (tcp_tx, tcp_rx) = mpsc::channel::<Vec<u8>>(CHANNEL_BUFFER_SIZE);
  35.  
  36. let mut client: Option<Client> = None;
  37. if ENABLE_K8S_CLIENT && K8S_WORKS {
  38. client = Some(Client::try_default().await?);
  39. }
  40.  
  41. let state = AppState {
  42. tcp_tx: Arc::new(Mutex::new(tcp_tx)),
  43. tcp_rx: Arc::new(Mutex::new(tcp_rx)),
  44. ws_tx: ws_tx.clone(),
  45. base_path: base_path.clone(),
  46. database,
  47. client,
  48. };
  49.  
  50. if ENABLE_INITIAL_CONNECTION && state.client.is_some() {
  51. println!("Trying initial connection...");
  52. if try_initial_connection(ws_tx.clone(), state.tcp_tx.clone()).await.is_err() || FORCE_REBUILD {
  53. eprintln!("Initial connection failed or force rebuild enabled");
  54. if BUILD_DOCKER_IMAGE {
  55. docker::build_docker_image().await?;
  56. }
  57. if BUILD_DEPLOYMENT {
  58. kubernetes::create_k8s_deployment(state.client.as_ref().unwrap()).await?;
  59. }
  60. }
  61. }
  62.  
  63. let bridge_rx = state.tcp_rx.clone();
  64. let bridge_tx = state.ws_tx.clone();
  65. tokio::spawn(async move {
  66. if let Err(e) = connect_to_server(bridge_rx, bridge_tx).await {
  67. eprintln!("Connection task failed: {}", e);
  68. }
  69. });
  70.  
  71. let cors = CorsLayer::new()
  72. .allow_origin(Any)
  73. .allow_methods([Method::GET, Method::POST])
  74. .allow_headers(Any);
  75.  
  76. let fallback_router = routes_static(state.clone().into());
  77.  
  78. let inner = Router::new()
  79. .route("/api/message", get(get_message))
  80. .route("/api/nodes", get(get_nodes))
  81. .route("/api/ws", get(ws_handler))
  82. .route("/api/users", get(users))
  83. .route("/api/send", post(receive_message))
  84. .route("/api/general", post(process_general))
  85. .route("/api/signin", post(sign_in))
  86. .route("/api/createuser", post(create_user))
  87. .route("/api/deleteuser", post(delete_user))
  88. .merge(fallback_router)
  89. .with_state(state.clone());
  90.  
  91.  
  92. let app = if base_path.is_empty() || base_path == "/" {
  93. inner.layer(cors)
  94. } else {
  95. Router::new().nest(&base_path, inner).layer(cors)
  96. };
  97.  
  98. let addr: SocketAddr = LocalUrl.parse().unwrap();
  99. println!("Listening on http://{}{}", addr, base_path);
  100.  
  101. // let addr: SocketAddr = "0.0.0.0:8081".parse().unwrap();
  102. // println!("Listening on http://{}{}", addr, base_path);
  103. // axum::serve(TcpListener::bind(addr).await?, app).await?;
  104.  
  105. // Updated server start:
  106. let listener = TcpListener::bind(addr).await?;
  107. axum::serve(listener, app.into_make_service())
  108. .await?;
  109.  
  110. Ok(())
  111. }
  112.  
  113. pub async fn serve_html_with_replacement(
  114. file: &str,
  115. state: &AppState,
  116. ) -> Result<Response<Body>, StatusCode> {
  117. let path = Path::new("src/svelte/build").join(file);
  118.  
  119. if path.extension().and_then(|e| e.to_str()) == Some("html") {
  120. let html = tokio_fs::read_to_string(&path)
  121. .await
  122. .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
  123.  
  124. let mut replaced = html.replace(
  125. "<head>",
  126. &format!(r#"
  127. <head>
  128. <script>window.__sveltekit_base = '[[SITE_URL]]';</script>
  129. <base href="[[SITE_URL]]/" />
  130. "#)
  131. );
  132. replaced = replaced.replace("[[SITE_URL]]", &state.base_path);
  133. return Ok(Html(replaced).into_response());
  134. }
  135.  
  136. // For static files (CSS, JS, images), just serve normally
  137. let bytes = tokio_fs::read(&path)
  138. .await
  139. .map_err(|_| StatusCode::NOT_FOUND)?;
  140. let content_type = from_path(&path).first_or_octet_stream().to_string();
  141.  
  142. Ok(Response::builder()
  143. .header("Content-Type", content_type)
  144. .body(Body::from(bytes))
  145. .unwrap())
  146. }
  147.  
  148. async fn handle_static_request(
  149. Extension(state): Extension<Arc<AppState>>,
  150. req: Request<Body>,
  151. ) -> Result<Response<Body>, StatusCode> {
  152. let base_path = &state.base_path;
  153. let full_path = req.uri().path();
  154.  
  155. // Strip base_path
  156. let relative_path = full_path.strip_prefix(base_path).unwrap_or(full_path);
  157.  
  158. let file = if relative_path == "/" || relative_path.is_empty() {
  159. "index.html".to_string()
  160. } else {
  161. relative_path.trim_start_matches('/').to_string()
  162. };
  163.  
  164. let ext = Path::new(&file)
  165. .extension()
  166. .and_then(|e| e.to_str())
  167. .unwrap_or("");
  168.  
  169. if ext == "html" {
  170. serve_html_with_replacement(&file, &state).await
  171. } else {
  172. let path = Path::new("src/svelte/build").join(&file);
  173. let bytes = tokio_fs::read(&path)
  174. .await
  175. .map_err(|_| StatusCode::NOT_FOUND)?;
  176. let content_type = from_path(&path).first_or_octet_stream().to_string();
  177.  
  178. Ok(Response::builder()
  179. .header("Content-Type", content_type)
  180. .body(Body::from(bytes))
  181. .unwrap())
  182. }
  183. }
  184.  
  185.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement