Añade carga de ajustes de configuración globales
This commit is contained in:
parent
4e23523e80
commit
96884cbbc0
12 changed files with 146 additions and 12 deletions
|
|
@ -24,15 +24,18 @@ categories = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
doc-comment = "0.3.3"
|
||||||
once_cell = "1.9.0"
|
once_cell = "1.9.0"
|
||||||
|
|
||||||
|
config_rs = { package = "config", version = "0.11.0", features = ["toml"] }
|
||||||
actix-web = "4.0.0-rc.3"
|
actix-web = "4.0.0-rc.3"
|
||||||
sycamore = { version = "0.8.0-beta.2", features = ["ssr"] }
|
sycamore = { version = "0.8.0-beta.2", features = ["ssr"] }
|
||||||
|
|
||||||
|
tokio = { version = "1.16", features = ["macros", "rt-multi-thread"] }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "pagetop"
|
name = "pagetop"
|
||||||
path = "src/lib.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "pagetop"
|
name = "pagetop"
|
||||||
path = "src/main.rs"
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pagetop = { path = "pagetop" }
|
pagetop = { path = "pagetop" }
|
||||||
actix-web = "4.0.0-rc.3"
|
tokio = { version = "1.16", features = ["macros", "rt-multi-thread"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "app"
|
name = "app"
|
||||||
|
|
|
||||||
2
config/default.toml
Normal file
2
config/default.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[app]
|
||||||
|
name = "PageTop Essence"
|
||||||
9
config/settings.default.toml
Normal file
9
config/settings.default.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
[app]
|
||||||
|
name = "PageTop Application"
|
||||||
|
description = "Developed with the amazing PageTop framework."
|
||||||
|
|
||||||
|
[webserver]
|
||||||
|
# Configuración opcional del servidor web.
|
||||||
|
# Usar bind_address = "" para deshabilitar el servidor web.
|
||||||
|
bind_address = "localhost"
|
||||||
|
bind_port = 8088
|
||||||
5
src/config/mod.rs
Normal file
5
src/config/mod.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
/// Nombre del directorio donde se encuentra la configuración.
|
||||||
|
pub const CONFIG_DIR: &'static str = "config";
|
||||||
|
|
||||||
|
mod settings;
|
||||||
|
pub use crate::config::settings::{CONFIG, SETTINGS};
|
||||||
103
src/config/settings.rs
Normal file
103
src/config/settings.rs
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
use crate::Lazy;
|
||||||
|
use crate::config::CONFIG_DIR;
|
||||||
|
|
||||||
|
use config_rs::{Config, File};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
/// Carga los ajustes globales "clave = valor" al arrancar la aplicación.
|
||||||
|
pub static CONFIG: Lazy<Config> = Lazy::new(|| {
|
||||||
|
// Establece el modo de ejecución según el valor de la variable de entorno
|
||||||
|
// PAGETOP_RUN_MODE. Asume "default" por defecto.
|
||||||
|
let run_mode = env::var("PAGETOP_RUN_MODE").unwrap_or("default".into());
|
||||||
|
|
||||||
|
// Inicializa los ajustes.
|
||||||
|
let mut settings = Config::default();
|
||||||
|
|
||||||
|
// Lee los ajustes combinando los archivos de configuración disponibles y
|
||||||
|
// asigna el modo de ejecución.
|
||||||
|
settings
|
||||||
|
.merge(
|
||||||
|
File::with_name(
|
||||||
|
&format!("{}/{}.toml", CONFIG_DIR, "common")
|
||||||
|
).required(false)).unwrap()
|
||||||
|
.merge(
|
||||||
|
File::with_name(
|
||||||
|
&format!("{}/{}.toml", CONFIG_DIR, run_mode)
|
||||||
|
).required(false)).unwrap()
|
||||||
|
.merge(
|
||||||
|
File::with_name(
|
||||||
|
&format!("{}/{}.toml", CONFIG_DIR, "local")
|
||||||
|
).required(false)).unwrap()
|
||||||
|
.set("app.run_mode", run_mode).unwrap();
|
||||||
|
|
||||||
|
settings
|
||||||
|
});
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
/// Usar esta macro para obtener el valor de cualquier ajuste global, donde
|
||||||
|
/// clave y valor son cadenas de caracteres. Devuelve la cadena vacía si no
|
||||||
|
/// encuentra un ajuste para la clave.
|
||||||
|
macro_rules! config_get {
|
||||||
|
( $key:expr ) => {
|
||||||
|
$crate::config::CONFIG.get_str($key).unwrap_or("".to_string())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
/// Carga los ajustes específicos de tu módulo o aplicación en una estructura
|
||||||
|
/// similar a [`SETTINGS`] con tipos de variables seguros. Genera un *panic!*
|
||||||
|
/// en caso de asignaciones no válidas.
|
||||||
|
macro_rules! config_map {
|
||||||
|
( $COMMENT:expr, $CONF:ident, $TYPE:tt $(, $key:expr => $value:expr)* ) => {
|
||||||
|
$crate::doc_comment! {
|
||||||
|
concat!($COMMENT),
|
||||||
|
|
||||||
|
pub static $CONF: $crate::Lazy<$TYPE> = $crate::Lazy::new(|| {
|
||||||
|
let mut settings = $crate::config::CONFIG.clone();
|
||||||
|
$(
|
||||||
|
settings.set_default($key, $value).unwrap();
|
||||||
|
)*
|
||||||
|
match settings.try_into() {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => panic!("Error parsing settings: {}", e),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct App {
|
||||||
|
pub name : String,
|
||||||
|
pub description : String,
|
||||||
|
pub run_mode : String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Webserver {
|
||||||
|
pub bind_address : String,
|
||||||
|
pub bind_port : u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Settings {
|
||||||
|
pub app : App,
|
||||||
|
pub webserver : Webserver,
|
||||||
|
}
|
||||||
|
|
||||||
|
config_map!(r#"
|
||||||
|
Ajustes globales y valores por defecto para las secciones *\[app\]* y
|
||||||
|
*\[webserver\]* específicas de PageTop.
|
||||||
|
"#,
|
||||||
|
SETTINGS, Settings,
|
||||||
|
|
||||||
|
// [app]
|
||||||
|
"app.name" => "PageTop Application",
|
||||||
|
"app.description" => "Developed with the amazing PageTop framework.",
|
||||||
|
|
||||||
|
// [webserver]
|
||||||
|
"webserver.bind_address" => "localhost",
|
||||||
|
"webserver.bind_port" => 8088
|
||||||
|
);
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::core::server;
|
use crate::core::server;
|
||||||
|
|
||||||
/// Modules must implement this trait.
|
/// Los módulos deben implementar este *trait*.
|
||||||
pub trait Module: Send + Sync {
|
pub trait Module: Send + Sync {
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,21 @@
|
||||||
|
use crate::config::SETTINGS;
|
||||||
use crate::core::{Server, all, server};
|
use crate::core::{Server, all, server};
|
||||||
|
|
||||||
pub fn run(bootstrap: Option<fn()>) -> Result<Server, std::io::Error> {
|
pub fn run(bootstrap: Option<fn()>) -> Result<Server, std::io::Error> {
|
||||||
// Call application bootstrap.
|
// Ejecuta la función de inicio específica para la aplicación.
|
||||||
if bootstrap != None {
|
if bootstrap != None {
|
||||||
let _ = &(bootstrap.unwrap())();
|
let _ = &(bootstrap.unwrap())();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inicializa el servidor web.
|
||||||
let server = server::HttpServer::new(|| {
|
let server = server::HttpServer::new(|| {
|
||||||
server::App::new()
|
server::App::new()
|
||||||
.configure(&all::modules)
|
.configure(&all::modules)
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8000")?
|
.bind(format!("{}:{}",
|
||||||
|
&SETTINGS.webserver.bind_address,
|
||||||
|
&SETTINGS.webserver.bind_port
|
||||||
|
))?
|
||||||
.run();
|
.run();
|
||||||
Ok(server)
|
Ok(server)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::core::module::Module;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Registered modules.
|
// Módulos registrados.
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
pub static MODULES: Lazy<RwLock<Vec<&dyn Module>>> = Lazy::new(|| {
|
pub static MODULES: Lazy<RwLock<Vec<&dyn Module>>> = Lazy::new(|| {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
// Global.
|
// Global.
|
||||||
|
|
||||||
|
pub use doc_comment::doc_comment;
|
||||||
pub use once_cell::sync::Lazy;
|
pub use once_cell::sync::Lazy;
|
||||||
|
|
||||||
pub mod core;
|
// -----------------------------------------------------------------------------
|
||||||
|
// APIs públicas.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
pub use actix_web::main;
|
pub mod config; // Gestión de la configuración.
|
||||||
|
pub mod core; // Servidor web y sistemas para Temas, Módulos y Respuestas.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use pagetop::config_get;
|
||||||
use pagetop::core::module::Module;
|
use pagetop::core::module::Module;
|
||||||
use pagetop::core::{register_module, server};
|
use pagetop::core::{register_module, server};
|
||||||
|
|
||||||
|
|
@ -16,7 +17,7 @@ impl Module for Greet {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn greet() -> impl server::Responder {
|
async fn greet() -> impl server::Responder {
|
||||||
"Hello!"
|
format!("Hello from {}!", config_get!("app.name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GreetWithParam;
|
struct GreetWithParam;
|
||||||
|
|
@ -46,7 +47,7 @@ fn bootstrap() {
|
||||||
register_module(&GreetWithParam);
|
register_module(&GreetWithParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pagetop::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
server::run(Some(bootstrap))?.await
|
server::run(Some(bootstrap))?.await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
use pagetop::core::server;
|
||||||
|
|
||||||
fn spawn_app() {
|
fn spawn_app() {
|
||||||
let server = pagetop::core::server::run().expect("Failed to bind address");
|
let server = server::run(None).expect("Failed to bind address");
|
||||||
let _ = tokio::spawn(server);
|
let _ = tokio::spawn(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue