From e0a668a58170e75fc2944e6aa855181296afd849 Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 10 Mar 2024 15:26:50 +0100 Subject: [PATCH] Improve server error handling --- showbits-thermal-printer/src/server.rs | 41 ++++++++----------- .../src/server/somehow.rs | 39 ++++++++++++++++++ showbits-thermal-printer/src/server/static.rs | 12 +++--- .../src/server/statuscode.rs | 15 +++++++ showbits-thermal-printer/static/image.html | 3 +- showbits-thermal-printer/static/index.html | 2 +- 6 files changed, 79 insertions(+), 33 deletions(-) create mode 100644 showbits-thermal-printer/src/server/somehow.rs create mode 100644 showbits-thermal-printer/src/server/statuscode.rs diff --git a/showbits-thermal-printer/src/server.rs b/showbits-thermal-printer/src/server.rs index aaa7fa5..4bb2ce6 100644 --- a/showbits-thermal-printer/src/server.rs +++ b/showbits-thermal-printer/src/server.rs @@ -1,8 +1,11 @@ +mod somehow; mod r#static; +mod statuscode; use axum::{ extract::{DefaultBodyLimit, Multipart, State}, http::StatusCode, + response::{IntoResponse, Redirect, Response}, routing::{get, post}, Form, Router, }; @@ -11,6 +14,8 @@ use tokio::{net::TcpListener, sync::mpsc}; use crate::drawer::Command; +use self::{r#static::get_static_file, statuscode::status_code}; + #[derive(Clone)] struct Server { tx: mpsc::Sender, @@ -22,9 +27,9 @@ pub async fn run(tx: mpsc::Sender, addr: String) -> anyhow::Result<()> .route("/test", post(post_test)) .route("/rip", post(post_rip)) .route("/text", post(post_text)) - .route("/image", post(post_image)) + .route("/image", post(post_image).fallback(get_static_file)) .route("/chat_message", post(post_chat_message)) - .fallback(get(r#static::get_static_file)) + .fallback(get(get_static_file)) .layer(DefaultBodyLimit::max(32 * 1024 * 1024)) // 32 MiB .with_state(Server { tx }); @@ -54,35 +59,25 @@ async fn post_text(server: State, request: Form) { let _ = server.tx.send(Command::Text(request.0.text)).await; } -async fn post_image(server: State, mut multipart: Multipart) -> Result<(), StatusCode> { +async fn post_image(server: State, mut multipart: Multipart) -> somehow::Result { let mut image = None; - while let Some(field) = multipart - .next_field() - .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? - { - let name = field.name().ok_or(StatusCode::INTERNAL_SERVER_ERROR)?; - if name == "image" { - let data = field - .bytes() - .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; - - let decoded = image::load_from_memory(&data) - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? - .into_rgba8(); - - image = Some(decoded); + while let Some(field) = multipart.next_field().await? { + if let Some(name) = field.name() { + if name == "image" { + let data = field.bytes().await?; + let decoded = image::load_from_memory(&data)?.into_rgba8(); + image = Some(decoded); + } } } if let Some(image) = image { let _ = server.tx.send(Command::Image(image)).await; - Ok(()) - } else { - Err(StatusCode::INTERNAL_SERVER_ERROR) + return Ok(Redirect::to("image").into_response()); } + + Ok(status_code(StatusCode::UNPROCESSABLE_ENTITY)) } #[derive(Deserialize)] diff --git a/showbits-thermal-printer/src/server/somehow.rs b/showbits-thermal-printer/src/server/somehow.rs new file mode 100644 index 0000000..de3908c --- /dev/null +++ b/showbits-thermal-printer/src/server/somehow.rs @@ -0,0 +1,39 @@ +use std::{error, fmt, result}; + +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, +}; + +use super::statuscode::status_code_with_info; + +pub struct Error(pub anyhow::Error); + +impl From for Error +where + E: error::Error + Send + Sync + 'static, +{ + fn from(value: E) -> Self { + Self(anyhow::Error::from(value)) + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl IntoResponse for Error { + fn into_response(self) -> Response { + status_code_with_info(StatusCode::INTERNAL_SERVER_ERROR, &self.0) + } +} + +pub type Result = result::Result; diff --git a/showbits-thermal-printer/src/server/static.rs b/showbits-thermal-printer/src/server/static.rs index dc987ea..6e7efac 100644 --- a/showbits-thermal-printer/src/server/static.rs +++ b/showbits-thermal-printer/src/server/static.rs @@ -4,16 +4,14 @@ use axum::{ }; use rust_embed::RustEmbed; +use super::statuscode::status_code; + #[derive(RustEmbed)] #[folder = "static"] struct StaticFiles; struct StaticFile(String); -fn not_found() -> Response { - (StatusCode::NOT_FOUND, "404 Not Found").into_response() -} - fn look_up_path(path: &str) -> Option { let path = path.trim_start_matches('/'); let file = StaticFiles::get(path)?; @@ -32,13 +30,13 @@ impl IntoResponse for StaticFile { if path.ends_with(".html") { // A file `/foo/bar.html` should not be accessible directly, only // indirectly at `/foo/bar`. - return not_found(); + return status_code(StatusCode::NOT_FOUND); } if path.ends_with("/index") { // A file `/foo/index.html` should not be accessible directly, only // indirectly at `/foo/`. - return not_found(); + return status_code(StatusCode::NOT_FOUND); } if path.ends_with('/') { @@ -55,7 +53,7 @@ impl IntoResponse for StaticFile { return response; } - not_found() + status_code(StatusCode::NOT_FOUND) } } diff --git a/showbits-thermal-printer/src/server/statuscode.rs b/showbits-thermal-printer/src/server/statuscode.rs new file mode 100644 index 0000000..c63e8e5 --- /dev/null +++ b/showbits-thermal-printer/src/server/statuscode.rs @@ -0,0 +1,15 @@ +use core::fmt; + +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, +}; + +pub fn status_code(code: StatusCode) -> Response { + (code, code.to_string()).into_response() +} + +pub fn status_code_with_info(code: StatusCode, info: &I) -> Response { + let message = format!("{code}\n\n{info}"); + (code, message).into_response() +} diff --git a/showbits-thermal-printer/static/image.html b/showbits-thermal-printer/static/image.html index 6054f4e..1a6f399 100644 --- a/showbits-thermal-printer/static/image.html +++ b/showbits-thermal-printer/static/image.html @@ -7,11 +7,10 @@

Upload an image

-
+
  1. -
  2. Come back to this page
diff --git a/showbits-thermal-printer/static/index.html b/showbits-thermal-printer/static/index.html index f3be9de..05d51f7 100644 --- a/showbits-thermal-printer/static/index.html +++ b/showbits-thermal-printer/static/index.html @@ -8,7 +8,7 @@

Thermal Printer Control