Last active
June 3, 2023 23:40
-
-
Save ethereumdegen/e5d1d6886e75de0bfc9fe0168f8ffc35 to your computer and use it in GitHub Desktop.
Actix webserver wrapper (controllers)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use actix_web::{web, HttpRequest, HttpResponse, Responder}; | |
use std::future::{Future}; | |
use std::pin::Pin; | |
use futures::future::BoxFuture; | |
use std::sync::Arc; | |
use crate::lib::web_server::{WebServerResources}; | |
pub trait JsonInput: serde::de::DeserializeOwned {} | |
impl<T: serde::de::DeserializeOwned> JsonInput for T {} | |
#[derive(Clone)] | |
pub enum RequestType { | |
Get, | |
Post // { JsonData :T } | |
} | |
#[derive(Clone)] | |
pub struct Route<T> { | |
pub path: &'static str, | |
pub handler: RouteHandler<T>, | |
pub request_type: RequestType, | |
} | |
// handler: Box<dyn Fn(HttpRequest, web::Json<T>) -> impl Responder>, | |
/* | |
pub async fn client_register( | |
input: web::Json<ClientRegisterInputData>, | |
res: web::Data<GridServerResources>, | |
) -> impl Responder { | |
*/ | |
// Assuming this is the signature of your handlers. | |
//pub type RouteHandler = fn(HttpRequest) -> Pin<Box<dyn Future<Output = Result<HttpResponse, actix_web::Error>>>>; | |
//pub type RouteHandler = fn(web::Data<HttpRequest>) -> Pin<Box<dyn Future<Output = Result<HttpResponse, actix_web::Error>>>>; | |
//pub type RouteHandler = fn(web::Data<HttpRequest>) -> BoxFuture<'static, Result<HttpResponse, actix_web::Error>>; | |
/* | |
pub type RouteHandler<T> = Arc<Box< dyn Fn( | |
Arc<web::Data<WebServerResources>>, | |
HttpRequest, | |
web::json<T> | |
)> > -> BoxFuture<'static, Result<HttpResponse, actix_web::Error>> + Send + Sync>; | |
*/ | |
pub type RouteHandler<T> = Arc<Box<dyn Fn( | |
Arc<web::Data<WebServerResources>>, | |
HttpRequest, | |
web::Json<T>, | |
) -> BoxFuture<'static, Result<HttpResponse, actix_web::Error>> + Send + Sync>>; | |
//pub type RouteHandler = Arc<dyn Fn(Arc<web::Data<WebServerResources>>, web::Json<MyData>, HttpRequest) -> BoxFuture<'static, Result<HttpResponse, actix_web::Error>> + Send + Sync>; | |
//pub type RouteHandler = fn(HttpRequest) -> impl futures::Future<Output = HttpResponse> ; | |
pub trait ApiController { | |
fn get_routes(&self) -> Vec<Route<Box<dyn JsonInput>>>; | |
} | |
/* | |
pub struct Route { | |
path: &'static str, | |
handler: Box<dyn Fn(_, _, _) -> _>, | |
} | |
impl Route { | |
pub fn new<T, F>(path: &'static str, handler: F) -> Self | |
where | |
T: serde::de::DeserializeOwned + 'static, | |
F: Fn(_, _, web::Json<T>) -> _ + 'static, | |
{ | |
Self { | |
path, | |
handler: Box::new(handler), | |
} | |
} | |
} | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] | |
extern crate log; | |
use actix_web::{get, middleware::Logger, post, web, App, HttpResponse, HttpServer, Responder}; | |
//use actix_web_lab::{extract::Path, respond::Html}; | |
use tokio::signal::unix::{signal, SignalKind}; | |
use std::sync::{ atomic::{AtomicBool, Ordering}}; | |
mod lib; | |
mod db; | |
mod controllers; | |
use std::thread; | |
use std::{io, sync::{Arc, Mutex,RwLock}}; | |
use crate::lib::web_server::WebServerResources; | |
use crate::controllers::session_controller::SessionController; | |
use lib::web_server::WebServer; | |
use crate::controllers::api_controller::{ApiController, RouteHandler}; | |
#[actix_web::main] | |
async fn main() { | |
env_logger::builder().filter_level(log::LevelFilter::Debug).init(); | |
let shutdown_flag = Arc::new(AtomicBool::new(false)); | |
let mut web_server = WebServer::new( | |
WebServerResources { | |
//db: db, | |
} | |
); | |
//need to put dyn in a box since its size is unknown | |
let api_controllers: Vec<Box<dyn ApiController>> = vec![ | |
Box::new(SessionController::new()), | |
]; | |
for controller in api_controllers { | |
web_server.register_controller_routes(controller); | |
} | |
//do this in a new tokio thread ? | |
let web_server_future = web_server.start( | |
"127.0.0.1".to_string(), | |
"7000".to_string() | |
).unwrap(); | |
// web_server_future.await | |
let web_server_thread = thread::spawn(move || { //use a non-tokio thread here | |
let runtime = tokio::runtime::Runtime::new().unwrap(); | |
runtime.block_on(async { | |
println!("Starting server"); | |
if let Err(e) = web_server_future.await { | |
eprintln!("Server error: {}", e); | |
} | |
}); | |
}); | |
let web_server_thread_tokio = tokio::task::spawn_blocking(move || web_server_thread.join()); | |
// Register a signal handler for SIGINT | |
let mut sigint = signal(SignalKind::interrupt()).expect("Failed to register SIGINT handler"); | |
// Wait for either the process threads or the SIGINT signal to complete. If any complete, the whole app ends | |
tokio::select! { | |
_ = web_server_thread_tokio => { | |
// Web server future completed | |
println!("Web server has shut down"); | |
} | |
_ = sigint.recv() => { | |
// SIGINT signal received | |
println!("Received SIGINT signal, shutting down..."); | |
// Perform any necessary cleanup or shutdown logic here | |
shutdown_flag.store(true, Ordering::SeqCst); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use actix_web::{web, HttpResponse, HttpRequest}; | |
use futures::future::BoxFuture; | |
use super::api_controller::{ApiController, RouteHandler,Route, RequestType, JsonInput}; | |
use std::sync::Arc; | |
use crate::lib::web_server::WebServerResources; | |
use serde::{Serialize, Deserialize}; | |
pub struct SessionController {} | |
impl SessionController { | |
pub fn new() -> Self { | |
Self {} | |
} | |
} | |
pub struct CreateSessionInputData { | |
session_id: String | |
} | |
impl JsonInput for CreateSessionInputData {} | |
// why does the httprequest data need to be in an arc? | |
fn get_session( | |
res: Arc<web::Data<WebServerResources>>, | |
input: web::Json<()>, | |
) -> BoxFuture<'static, Result<HttpResponse, actix_web::Error>> { | |
Box::pin(async { | |
Ok(HttpResponse::Ok().body("get_session")) | |
}) | |
} | |
fn create_session( | |
res: Arc<web::Data<WebServerResources>>, | |
input: web::Json<CreateSessionInputData>, | |
) -> BoxFuture<'static, Result<HttpResponse, actix_web::Error>> { | |
Box::pin(async { | |
Ok(HttpResponse::Ok().body("get_session")) | |
}) | |
} | |
impl ApiController for SessionController { | |
fn get_routes(&self) -> Vec<Route<Box<dyn JsonInput>>> { | |
vec![ | |
Route {path: "/api/session", handler: Arc::new(get_session), request_type: RequestType::Get}, | |
Route {path: "/api/create", handler: Arc::new(create_session), request_type: RequestType::Post}, | |
/* ("/api/session/{id}", Arc::new(get_session_by_id)), | |
("/api/session", Arc::new(create_session)), | |
("/api/session/{id}", Arc::new(update_session)), | |
("/api/session/{id}", Arc::new(delete_session)),*/ | |
] | |
} | |
} | |
/* | |
pub async fn get_session_by_id(req: HttpRequest) -> HttpResponse { | |
HttpResponse::Ok().body("get_session_by_id") | |
} | |
pub async fn create_session(req: HttpRequest) -> HttpResponse { | |
HttpResponse::Ok().body("create_session") | |
} | |
pub async fn update_session(req: HttpRequest) -> HttpResponse { | |
HttpResponse::Ok().body("update_session") | |
} | |
pub async fn delete_session(req: HttpRequest) -> HttpResponse { | |
HttpResponse::Ok().body("delete_session") | |
}*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment