2025-01-02 15:57:13 +00:00
|
|
|
use actix::prelude::*;
|
2025-01-01 01:50:26 +00:00
|
|
|
use actix_files::Files;
|
2025-01-02 15:57:13 +00:00
|
|
|
use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer, Responder};
|
2025-01-01 01:50:26 +00:00
|
|
|
use actix_web_actors::ws;
|
2025-01-02 15:57:13 +00:00
|
|
|
use log::info;
|
2025-01-01 01:50:26 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use std::{fs, time::Duration};
|
2025-01-02 16:33:01 +00:00
|
|
|
use chrono::Local;
|
2025-01-02 15:57:13 +00:00
|
|
|
|
2025-01-01 01:50:26 +00:00
|
|
|
|
|
|
|
/// Greeting API structures
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
struct GreetingRequest {
|
|
|
|
name: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize)]
|
|
|
|
struct GreetingResponse {
|
|
|
|
message: String,
|
|
|
|
}
|
|
|
|
|
2025-01-02 16:33:01 +00:00
|
|
|
#[derive(Serialize)]
|
|
|
|
pub struct Landing {
|
|
|
|
pub time : String
|
|
|
|
}
|
|
|
|
|
2025-01-02 15:57:13 +00:00
|
|
|
#[derive(Serialize)]
|
|
|
|
enum ToFrontend {
|
2025-01-02 16:33:01 +00:00
|
|
|
Landing(Landing)
|
2025-01-02 15:57:13 +00:00
|
|
|
}
|
|
|
|
|
2025-01-01 01:50:26 +00:00
|
|
|
async fn greet(req: web::Json<GreetingRequest>) -> impl Responder {
|
|
|
|
info!("Received request to /api/greet with name: {}", req.name);
|
|
|
|
let message = format!("Hello, {}!", req.name);
|
|
|
|
web::Json(GreetingResponse { message })
|
|
|
|
}
|
|
|
|
|
|
|
|
/// WebSocket actor
|
|
|
|
struct MyWebSocket;
|
|
|
|
|
|
|
|
impl Actor for MyWebSocket {
|
|
|
|
type Context = ws::WebsocketContext<Self>;
|
|
|
|
|
|
|
|
fn started(&mut self, ctx: &mut Self::Context) {
|
|
|
|
info!("WebSocket actor started");
|
|
|
|
// Send messages every second
|
|
|
|
ctx.run_interval(Duration::from_secs(1), |_, ctx| {
|
2025-01-02 16:33:01 +00:00
|
|
|
// Format the current time as HH:mm:ss
|
|
|
|
let current_time = Local::now().format("%H:%M:%S").to_string();
|
|
|
|
let message = ToFrontend::Landing(Landing { time: current_time });
|
|
|
|
|
|
|
|
// Serialize the message to JSON
|
|
|
|
if let Ok(json_message) = serde_json::to_string(&message) {
|
|
|
|
ctx.text(json_message);
|
|
|
|
} else {
|
|
|
|
info!("Failed to serialize the message");
|
|
|
|
}
|
2025-01-01 01:50:26 +00:00
|
|
|
});
|
|
|
|
info!("Leaving started");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWebSocket {
|
2025-01-02 15:57:13 +00:00
|
|
|
fn handle(
|
|
|
|
&mut self,
|
|
|
|
msg: Result<ws::Message, ws::ProtocolError>,
|
|
|
|
ctx: &mut ws::WebsocketContext<Self>,
|
|
|
|
) {
|
2025-01-01 01:50:26 +00:00
|
|
|
if let Ok(ws::Message::Ping(msg)) = msg {
|
|
|
|
ctx.pong(&msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn websocket_handler(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
|
|
|
|
ws::start(MyWebSocket {}, &req, stream)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_web::main]
|
|
|
|
async fn main() -> std::io::Result<()> {
|
|
|
|
env_logger::init();
|
|
|
|
|
|
|
|
let address = "127.0.0.1";
|
|
|
|
let port = 8080;
|
|
|
|
|
|
|
|
info!("Starting server at http://{}:{}", address, port);
|
|
|
|
|
|
|
|
HttpServer::new(|| {
|
|
|
|
App::new()
|
|
|
|
.route("/api/greet", web::post().to(greet)) // Greeting API
|
|
|
|
.route("/ws/", web::get().to(websocket_handler)) // WebSocket endpoint
|
|
|
|
.service(Files::new("/assets", "./public/assets"))
|
|
|
|
.service(Files::new("/", "./public").index_file("index.html")) // Serve frontend
|
|
|
|
.default_service(web::route().to(|| async {
|
|
|
|
// Serve the `index.html` file
|
|
|
|
let index_html = fs::read_to_string("./public/index.html")
|
|
|
|
.unwrap_or_else(|_| "404 Not Found".to_string());
|
|
|
|
HttpResponse::Ok()
|
|
|
|
.content_type("text/html; charset=utf-8")
|
|
|
|
.body(index_html)
|
|
|
|
}))
|
|
|
|
})
|
|
|
|
.bind((address, port))?
|
|
|
|
.run()
|
|
|
|
.await
|
|
|
|
}
|