Add proper error handling
This commit is contained in:
parent
98d71f0311
commit
ab405fc1f8
4 changed files with 107 additions and 19 deletions
src
46
src/main.rs
46
src/main.rs
|
@ -1,10 +1,17 @@
|
|||
#![allow(dead_code)]
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use actix_files::NamedFile;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::middleware::ErrorHandlers;
|
||||
use actix_web::{get, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
|
||||
use clap::Parser;
|
||||
use handlebars::Handlebars;
|
||||
use std::path::PathBuf;
|
||||
|
||||
mod errors;
|
||||
|
||||
use errors::{generic_error, UserError};
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
struct Config {
|
||||
|
@ -21,16 +28,17 @@ struct Config {
|
|||
dev_mode: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SharedData<'a> {
|
||||
handlebars: Handlebars<'a>,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
#[get("/{filename:.*.html}")]
|
||||
#[get(r"/{filename:.*\.html}")]
|
||||
async fn template(
|
||||
shared: web::Data<SharedData<'_>>,
|
||||
req: HttpRequest,
|
||||
) -> Result<impl Responder, Box<dyn std::error::Error>> {
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let path = req
|
||||
.match_info()
|
||||
.query("filename")
|
||||
|
@ -38,22 +46,21 @@ async fn template(
|
|||
.expect("only paths with this suffix should get here");
|
||||
|
||||
if shared.handlebars.has_template(path) {
|
||||
let body = shared.handlebars.render(path, &())?;
|
||||
Ok(HttpResponse::Ok().body(body))
|
||||
} else {
|
||||
let body = shared
|
||||
.handlebars
|
||||
.render("404", &())
|
||||
.expect("404 template not found");
|
||||
Ok(HttpResponse::NotFound().body(body))
|
||||
.render(path, &())
|
||||
.map_err(|_| UserError::InternalError)?;
|
||||
Ok(HttpResponse::Ok().body(body))
|
||||
} else {
|
||||
Err(UserError::NotFound)?
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/{filename:.*}")]
|
||||
#[get("/{filename:.*[^/]+}")]
|
||||
async fn static_file(
|
||||
shared: web::Data<SharedData<'_>>,
|
||||
req: HttpRequest,
|
||||
) -> Result<impl Responder, Box<dyn std::error::Error>> {
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let requested = req.match_info().query("filename");
|
||||
|
||||
match shared
|
||||
|
@ -67,17 +74,13 @@ async fn static_file(
|
|||
//
|
||||
// i.e., don't serve up /etc/passwd
|
||||
Ok(path) if path.starts_with(&shared.config.template_directory) => {
|
||||
let file = NamedFile::open_async(path).await?;
|
||||
let file = NamedFile::open_async(path)
|
||||
.await
|
||||
.map_err(|_| UserError::NotFound)?;
|
||||
Ok(file.use_last_modified(false).respond_to(&req))
|
||||
}
|
||||
// Any other cases should 404
|
||||
_ => {
|
||||
let body = shared
|
||||
.handlebars
|
||||
.render("404", &())
|
||||
.expect("404 template not found");
|
||||
Ok(HttpResponse::NotFound().body(body))
|
||||
}
|
||||
_ => Err(UserError::NotFound)?,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +104,11 @@ async fn main() -> Result<(), std::io::Error> {
|
|||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.wrap(
|
||||
ErrorHandlers::new()
|
||||
.handler(StatusCode::NOT_FOUND, generic_error)
|
||||
.handler(StatusCode::INTERNAL_SERVER_ERROR, generic_error),
|
||||
)
|
||||
.app_data(shared_data.clone())
|
||||
.service(template)
|
||||
.service(static_file)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue