diff --git a/examples/basic/static/index.html b/examples/basic/static/index.html index 50a7e97..acd58ab 100644 --- a/examples/basic/static/index.html +++ b/examples/basic/static/index.html @@ -16,8 +16,8 @@

Routes

diff --git a/examples/paste_bin/src/error.rs b/examples/paste_bin/src/error.rs new file mode 100644 index 0000000..b418819 --- /dev/null +++ b/examples/paste_bin/src/error.rs @@ -0,0 +1,41 @@ +use std::sync::Arc; + +use afire::{headers::Vary, route::RouteError, Content, HeaderName, Request, Response, Server}; +use serde_json::json; + +use crate::app::App; + +pub fn error_handler(_server: Arc>, req: Arc, error: RouteError) -> Response { + if req + .headers + .get(HeaderName::Accept) + .map(|x| x == "application/json") + .unwrap_or(false) + { + Response::new() + .text(json!({ + "message": error.message, + "location": error.location.map(|x| x.to_string()), + "error": error.error.map(|x| format!("{x:?}")), + })) + .content(Content::JSON) + } else { + Response::new() + .text(format!( + "Internal Server Error\n{}{}{}", + error.message, + error + .error + .map(|x| format!("\n{:?}", x)) + .unwrap_or_default(), + error + .location + .map(|x| format!("\n{}", x)) + .unwrap_or_default(), + )) + .content(Content::TXT) + } + .header(Vary::headers([HeaderName::Accept])) + .status(error.status) + .headers(error.headers) +} diff --git a/examples/paste_bin/src/main.rs b/examples/paste_bin/src/main.rs index daca3d8..987377f 100644 --- a/examples/paste_bin/src/main.rs +++ b/examples/paste_bin/src/main.rs @@ -10,6 +10,7 @@ use app::App; mod app; mod config; mod database; +mod error; mod pages; mod routes; @@ -18,6 +19,7 @@ fn main() -> Result<()> { // Create a new server with values loaded from config.toml let mut server = Server::new(&app.config.server.host, app.config.server.port) + .error_handler(error::error_handler) .workers(app.config.server.workers) .state(app); diff --git a/lib/proto/http/content_type.rs b/lib/proto/http/content_type.rs index fc32a50..b5ed38d 100644 --- a/lib/proto/http/content_type.rs +++ b/lib/proto/http/content_type.rs @@ -1,6 +1,9 @@ //! Common MIME types for HTTP responses. -use crate::{headers::ContentType, Header}; +use crate::{ + headers::{Charset, ContentType}, + Header, +}; use super::mime::{self, Mime}; @@ -51,6 +54,6 @@ impl Content<'_> { impl From> for Header { // Convert Content to a Content-Type Header fn from(x: Content<'_>) -> Self { - ContentType::new(x.as_type()).into() + ContentType::new(x.as_type()).charset(Charset::Utf8).into() } } diff --git a/lib/proto/http/headers.rs b/lib/proto/http/headers.rs index ec228ea..3fcc866 100644 --- a/lib/proto/http/headers.rs +++ b/lib/proto/http/headers.rs @@ -392,6 +392,12 @@ mod content_type { } } + /// Sets the charset of the ContentType header. + pub fn charset(mut self, charset: impl Into) -> Self { + self.charset = Some(charset.into()); + self + } + content_type_shortcut![ (html, HTML), (text, TEXT), diff --git a/lib/server.rs b/lib/server.rs index 78481a8..d074967 100644 --- a/lib/server.rs +++ b/lib/server.rs @@ -33,7 +33,7 @@ pub struct Server { pub ip: IpAddr, /// The event loop used to handle incoming connections. - pub event_loop: Box>, + pub event_loop: Box + Send + Sync>, /// Routes to handle. pub routes: Vec>, @@ -46,7 +46,7 @@ pub struct Server { pub state: Option>, /// Default response for internal server errors - pub error_handler: Box>, + pub error_handler: Box + Send + Sync>, /// Headers automatically added to every response. pub default_headers: Headers, @@ -170,7 +170,7 @@ impl Server { /// The default is [`TcpEventLoop`], which uses the standard library's built-in TCP listener. /// /// The [afire_tls](https://github.com/Basicprogrammer10/afire_tls) crate contains an event loop that uses rustls to handle TLS connections. - pub fn event_loop(self, event_loop: impl EventLoop + 'static) -> Self { + pub fn event_loop(self, event_loop: impl EventLoop + Send + Sync + 'static) -> Self { Server { event_loop: Box::new(event_loop), ..self @@ -292,7 +292,7 @@ impl Server { /// .text(format!("Internal Server Error: {}", err.message)) /// })); /// ``` - pub fn error_handler(self, res: impl ErrorHandler + 'static) -> Self { + pub fn error_handler(self, res: impl ErrorHandler + Send + Sync + 'static) -> Self { trace!("{}Setting Error Handler", emoji("✌")); Self {