Añade una vía para dar respuesta a errores fatales

Son errores fatales aquellos que deberán mostrarse (renderizarse) sin
depender de las APIs de renderizado de páginas. No pueden depender del
tema ni del estado actual de la aplicación. Se generan al intentar
componer una página y se llega a una situación no recuperable que debe
informarse directamente al navegador cliente. Es típico el error 500
(internal server error) pero también un error 507 (insufficient storage)
y otros más que se irán contemplando según requerimientos.
This commit is contained in:
Manuel Cillero 2022-07-21 18:20:33 +02:00
parent 8833a2aa7d
commit 1543ab2960
12 changed files with 59 additions and 14 deletions

View file

@ -1,7 +1,7 @@
use super::l;
use pagetop::prelude::*;
pub async fn summary() -> app::Result<Markup> {
pub async fn summary() -> ResultPage<Markup, FatalError> {
let top_menu = Menu::new()
.with_item(MenuItem::label(l("module_name").as_str()))
.with_item(MenuItem::link("Opción 2", "https://www.google.es"))

View file

@ -40,7 +40,7 @@ impl ModuleTrait for Node {
}
}
async fn node() -> app::Result<Markup> {
async fn node() -> ResultPage<Markup, FatalError> {
Page::new().with_title("Nodo").render()
}

View file

@ -35,7 +35,7 @@ impl ModuleTrait for User {
}
}
async fn login() -> app::Result<Markup> {
async fn login() -> ResultPage<Markup, FatalError> {
Page::new()
.with_title("Identificación del usuario")
.add_to(

View file

@ -1,4 +1,4 @@
pub use actix_web::{http, web, App, HttpRequest, HttpResponse, HttpServer, Responder, Result};
pub use actix_web::{http, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
mod banner;
@ -13,3 +13,5 @@ mod definition;
pub use definition::AppTrait;
pub mod application;
pub mod fatal_error;

View file

@ -0,0 +1,38 @@
use crate::app::HttpResponse;
use crate::app::http::{header::ContentType, StatusCode};
use crate::response::ResponseError;
use std::fmt;
#[derive(Debug)]
pub enum FatalError {
InternalError,
BadClientData,
Timeout,
}
impl fmt::Display for FatalError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
FatalError::InternalError => write!(f, "Internal Error"),
FatalError::BadClientData => write!(f, "Bad Client Data"),
FatalError::Timeout => write!(f, "Timeout"),
}
}
}
impl ResponseError for FatalError {
fn error_response(&self) -> HttpResponse {
HttpResponse::build(self.status_code())
.insert_header(ContentType::html())
.body(self.to_string())
}
fn status_code(&self) -> StatusCode {
match *self {
FatalError::InternalError => StatusCode::INTERNAL_SERVER_ERROR,
FatalError::BadClientData => StatusCode::BAD_REQUEST,
FatalError::Timeout => StatusCode::GATEWAY_TIMEOUT,
}
}
}

View file

@ -24,7 +24,7 @@ impl ModuleTrait for DefaultHomePage {
}
}
async fn demo() -> app::Result<Markup> {
async fn demo() -> ResultPage<Markup, FatalError> {
Page::new()
.with_title(l("page_title").as_str())
.with_context(InContextOp::StyleSheet(AssetsOp::Add(StyleSheet::located(

View file

@ -34,7 +34,7 @@ impl ThemeTrait for Bootsier {
.alter_context(InContextOp::AddJQuery);
}
fn render_error_page(&self, mut s: app::http::StatusCode) -> app::Result<Markup> {
fn render_error_page(&self, mut s: app::http::StatusCode) -> ResultPage<Markup, FatalError> {
let mut description = "e500-description";
let mut message = "e500-description";
match s {

View file

@ -2,8 +2,9 @@ use crate::base::component::Chunck;
use crate::config::SETTINGS;
use crate::core::component::{ComponentTrait, InContext, InContextOp};
use crate::html::{html, Favicon, Markup};
use crate::response::page::Page;
use crate::{app, concat_string, util};
use crate::{concat_string, util};
use crate::{app, app::fatal_error::FatalError};
use crate::response::page::{Page, ResultPage};
pub trait BaseTheme {
fn single_name(&self) -> &'static str;
@ -116,7 +117,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
*/
}
fn render_error_page(&self, s: app::http::StatusCode) -> app::Result<Markup> {
fn render_error_page(&self, s: app::http::StatusCode) -> ResultPage<Markup, FatalError> {
Page::new()
.with_title(format!("Error {}", s.as_str()).as_str())
.add_to(

View file

@ -16,6 +16,7 @@ pub use crate::{db, db::*, migration_item, pub_migration};
pub use crate::app;
pub use crate::app::application::Application;
pub use crate::app::fatal_error::FatalError;
pub use crate::app::AppTrait;
pub use crate::core::{component::*, hook::*, module::*, theme::*};

View file

@ -1 +1,3 @@
pub use actix_web::ResponseError;
pub mod page;

View file

@ -1,3 +1,5 @@
pub use actix_web::Result as ResultPage;
mod hook;
pub use hook::{BeforeRenderPageHook, HOOK_BEFORE_RENDER_PAGE};

View file

@ -1,9 +1,10 @@
use super::{BeforeRenderPageHook, HOOK_BEFORE_RENDER_PAGE};
use super::{BeforeRenderPageHook, ResultPage, HOOK_BEFORE_RENDER_PAGE};
use crate::app::fatal_error::FatalError;
use crate::config::SETTINGS;
use crate::core::component::*;
use crate::core::hook::{action_ref, run_actions};
use crate::html::*;
use crate::{app, trace, Lazy};
use crate::{trace, Lazy};
use std::collections::HashMap;
@ -191,7 +192,7 @@ impl Page {
// Page RENDER.
pub fn render(&mut self) -> app::Result<Markup> {
pub fn render(&mut self) -> ResultPage<Markup, FatalError> {
// Acciones de los módulos antes de renderizar la página.
run_actions(HOOK_BEFORE_RENDER_PAGE, |hook| {
action_ref::<BeforeRenderPageHook>(&**hook).run(self)
@ -222,6 +223,4 @@ impl Page {
None => html! {},
}
}
// Page EXTRAS.
}