mod website; use actix_web::{get, App, HttpResponse, HttpServer, Responder}; use std::path::PathBuf; use website::WebSite; fn load_website_template() -> WebSite { let site_template_path = std::env::current_dir() .unwrap() .join("templates") .join("new_website.json"); let site_template = std::fs::read_to_string(site_template_path).unwrap(); WebSite::from_json_str(&site_template) } #[get("/{pth:.*}")] async fn page( website: actix_web::web::Data<WebSite>, pth: actix_web::web::Path<PathBuf>, ) -> impl Responder { let pth = pth.into_inner(); match website.get_page_by_url(&pth) { Some(page) => HttpResponse::Ok().body(page.html_doc.to_string()), None => HttpResponse::NotFound().body(format!("Not found {}", pth.display())), } } #[get("/admin/dashboard")] async fn admin_dashboard() -> impl Responder { HttpResponse::Ok().body("Admin") } #[get("/admin/login")] async fn admin_login() -> impl Responder { HttpResponse::Ok().body("Login") } #[actix_web::main] async fn main() -> std::io::Result<()> { let website = load_website_template(); // GET HOST AND CERTS DIR FROM CLI ARGUMENT // Get port from arg, or get context from arg and define default port, or set default port to standard // LOAD A WEBSITE SCHEMA (JSON) FROM CLI ARGUMENT PATH OR search in /var/{sitename} and load it CREATE A NEW ONE // create pages resources with templates and the contents from the json file // Save the resources in an appstate // create the static dir in standard location if doesn't exist (like /var/{sitename}/static) // create the static files index (like Arc<Mutex<StaticFilesIndex>>) // create a Rest service at root with extensive path argument: like #[get(/{pth:.*})] // Then parse the website document and return the corresponding template, or 404 template let host = "localhost"; let certs_dir = std::path::PathBuf::from("/etc/letsencrypt/live").join(host); let cert_file = &mut std::io::BufReader::new(std::fs::File::open(certs_dir.join("fullchain.pem")).unwrap()); let key_file = &mut std::io::BufReader::new(std::fs::File::open(certs_dir.join("privkey.pem")).unwrap()); let cert = rustls::Certificate(rustls_pemfile::certs(cert_file).unwrap().remove(0).to_vec()); let key = rustls::PrivateKey( rustls_pemfile::pkcs8_private_keys(key_file) .unwrap() .remove(0) .to_vec(), ); let srv_conf = rustls::ServerConfig::builder() .with_safe_defaults() .with_no_client_auth() .with_single_cert(vec![cert], key) .expect("bad certificate/key"); HttpServer::new(move || { App::new() .wrap(actix_web::middleware::Logger::default()) .wrap(actix_web::middleware::Compress::default()) .app_data(actix_web::web::Data::new(website.clone())) .service(admin_dashboard) .service(admin_login) .service(page) }) .bind("127.0.0.1:8080")? .bind_rustls("127.0.0.1:8443", srv_conf)? .run() .await }