Añade una arquitectura escalable basada en módulos

This commit is contained in:
Manuel Cillero 2022-02-10 23:58:22 +01:00
parent e1ea149988
commit 4e23523e80
10 changed files with 108 additions and 19 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "pagetop"
version = "0.0.0"
version = "0.1.0"
edition = "2021"
authors = [
@ -24,6 +24,8 @@ categories = [
]
[dependencies]
once_cell = "1.9.0"
actix-web = "4.0.0-rc.3"
sycamore = { version = "0.8.0-beta.2", features = ["ssr"] }

7
src/core/all.rs Normal file
View file

@ -0,0 +1,7 @@
use crate::core::{server, state};
pub fn modules(cfg: &mut server::web::ServiceConfig) {
for m in state::MODULES.read().unwrap().iter() {
m.configure_module(cfg);
}
}

View file

@ -1,3 +1,9 @@
pub use actix_web::dev::Server;
mod state;
pub use state::register_module;
mod all;
pub mod module;
pub mod server;

14
src/core/module/api.rs Normal file
View file

@ -0,0 +1,14 @@
use crate::core::server;
/// Modules must implement this trait.
pub trait Module: Send + Sync {
fn name(&self) -> String;
fn description(&self) -> String {
"".to_string()
}
#[allow(unused_variables)]
fn configure_module(&self, cfg: &mut server::web::ServiceConfig) {
}
}

2
src/core/module/mod.rs Normal file
View file

@ -0,0 +1,2 @@
mod api;
pub use api::Module;

View file

@ -1,22 +1,14 @@
use crate::core::{server, Server};
use crate::core::{Server, all, server};
async fn greet() -> impl server::Responder {
"Hello!"
}
pub fn run(bootstrap: Option<fn()>) -> Result<Server, std::io::Error> {
// Call application bootstrap.
if bootstrap != None {
let _ = &(bootstrap.unwrap())();
}
async fn greet_with_param(req: server::HttpRequest) -> server::HttpResponse {
let name: String = req.match_info().get("name").unwrap_or("World").into();
server::HttpResponse::Ok()
.body(sycamore::render_to_string(|ctx| sycamore::view! { ctx,
p { "Hello " (name) "!" }
}))
}
pub fn run() -> Result<Server, std::io::Error> {
let server = server::HttpServer::new(|| {
server::App::new()
.route("/", server::web::get().to(greet))
.route("/{name}", server::web::get().to(greet_with_param))
.configure(&all::modules)
})
.bind("127.0.0.1:8000")?
.run();

View file

@ -1,4 +1,4 @@
pub use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer, Responder};
pub use actix_web::{App, HttpRequest, HttpResponse, HttpServer, Responder, web};
mod main;
pub use main::run;

16
src/core/state.rs Normal file
View file

@ -0,0 +1,16 @@
use crate::Lazy;
use crate::core::module::Module;
use std::sync::RwLock;
// -----------------------------------------------------------------------------
// Registered modules.
// -----------------------------------------------------------------------------
pub static MODULES: Lazy<RwLock<Vec<&dyn Module>>> = Lazy::new(|| {
RwLock::new(vec![])
});
pub fn register_module(m: &'static (dyn Module + 'static)) {
MODULES.write().unwrap().push(m);
}

View file

@ -1,3 +1,7 @@
// Global.
pub use once_cell::sync::Lazy;
pub mod core;
pub use actix_web::main;

View file

@ -1,6 +1,52 @@
use pagetop::core::server;
use pagetop::core::module::Module;
use pagetop::core::{register_module, server};
struct Greet;
impl Module for Greet {
fn name(&self) -> String {
"Hello".to_string()
}
fn configure_module(&self, cfg: &mut server::web::ServiceConfig) {
cfg.service(
server::web::resource("/")
.route(server::web::get().to(greet))
);
}
}
async fn greet() -> impl server::Responder {
"Hello!"
}
struct GreetWithParam;
impl Module for GreetWithParam {
fn name(&self) -> String {
"Hello World!".to_string()
}
fn configure_module(&self, cfg: &mut server::web::ServiceConfig) {
cfg.service(
server::web::resource("/{name}")
.route(server::web::get().to(greet_with_param))
);
}
}
async fn greet_with_param(req: server::HttpRequest) -> server::HttpResponse {
let name: String = req.match_info().get("name").unwrap_or("World").into();
server::HttpResponse::Ok()
.body(sycamore::render_to_string(|ctx| sycamore::view! { ctx,
p { "Hello " (name) "!" }
}))
}
fn bootstrap() {
register_module(&Greet);
register_module(&GreetWithParam);
}
#[pagetop::main]
async fn main() -> std::io::Result<()> {
server::run()?.await
server::run(Some(bootstrap))?.await
}