Proper MimeType handling with mycelium

This commit is contained in:
Slatian 2023-10-29 16:51:43 +01:00
parent bfa383ddbe
commit de179ea7fa
4 changed files with 30 additions and 19 deletions

1
Cargo.lock generated
View File

@ -493,6 +493,7 @@ dependencies = [
"idna 0.3.0",
"lazy_static",
"maxminddb",
"mime",
"parking_lot",
"regex",
"serde",

View File

@ -25,3 +25,4 @@ tower-http = { version = "0.4", features = ["fs"] }
trust-dns-proto = "0.22"
trust-dns-resolver = { version = "0.22", features = ["dns-over-rustls","dns-over-https","dns-over-quic"] }
maxminddb = "0.23"
mime = "0.3"

View File

@ -1,6 +1,7 @@
use serde::Deserialize;
use serde::Serialize;
use mime::Mime;
/// Defines how the response should be rendered.
pub enum MycFormatFamily {
@ -14,7 +15,7 @@ pub enum MycFormatFamily {
/// Implement on a type that is able to describe a response format.
///
/// It is best implemented on an enum.
pub trait MycFormat: ToString+Clone+Default {
pub trait MycFormat: ToString+Clone+Default+Send {
// Return the format family this
fn get_family(&self) -> MycFormatFamily {
@ -48,7 +49,7 @@ pub trait MycFormat: ToString+Clone+Default {
///
/// Implementing get_mime_type() properly is recommended
/// for production use.
fn get_less_well_known_mimetype(&self) -> Option<&'static str> {
fn get_less_well_known_mimetype(&self) -> Option<Mime> {
None
}
@ -61,8 +62,8 @@ pub trait MycFormat: ToString+Clone+Default {
/// to get_less_well_known_mimetype() and the "application/octet-stream" type.
///
/// The default implementation knows the following associations:
/// * `text`: `text/plain`
/// * `html`: `text/html`
/// * `text`: `text/plain; charset=utf-8`
/// * `html`: `text/html; charset=utf-8`
/// * `json`: `application/json`
/// * `xml`: `application/xml`
/// * `rss`: `application/rss+xml`
@ -71,17 +72,20 @@ pub trait MycFormat: ToString+Clone+Default {
/// *Implementation Note:* It may be possible that two different views
/// have the same MimeType (maybe two json representations for different consumers).
///
fn get_mime_type(&self) -> &'static str {
fn get_mime_type(&self) -> Mime {
match self.get_name().as_str() {
"text" => "text/plain",
"html" => "text/html",
"json" => "application/json",
"xml" => "application/xml",
"rss" => "application/rss+xml",
"atom" => "application/atom+xml",
"text" => mime::TEXT_PLAIN_UTF_8,
"html" => mime::TEXT_HTML_UTF_8,
"json" => mime::APPLICATION_JSON,
"xml" => "application/xml".parse()
.expect("Parse static application/xml"),
"rss" => "application/rss+xml".parse()
.expect("Parse static application/rss+xml"),
"atom" => "application/atom+xml".parse()
.expect("Parse static application/atom+xml"),
_ =>
self.get_less_well_known_mimetype()
.unwrap_or_else(||"application/octet-stream"),
.unwrap_or(mime::APPLICATION_OCTET_STREAM),
}
}

View File

@ -4,10 +4,11 @@
*/
use axum::{
body::{Bytes,Full},
headers::HeaderValue,
http::StatusCode,
http::header,
http::header::SET_COOKIE,
response::Html,
response::IntoResponse,
response::Response,
response::Json,
@ -22,7 +23,6 @@ use crate::mycelium::MycView;
use crate::mycelium::MycFormat;
use crate::mycelium::MycFormatFamily;
use crate::settings::QuerySettings;
use crate::settings::ResponseFormat;
/* The engine itself */
@ -41,12 +41,13 @@ impl Engine {
let mut response = match settings.format.get_family() {
MycFormatFamily::Template => {
let template_name = view.get_template_name();
let mime_type = settings.format.get_mime_type();
let mut context = tera::Context::new();
context.insert("view", &template_name);
//intented for shared macros
context.insert("format", &settings.format.get_name());
context.insert("mimetype", &settings.format.get_mime_type());
context.insert("mimetype", &mime_type.to_string());
context.insert("language", &settings.lang);
context.insert("dns_resolvers", &settings.available_dns_resolvers);
context.insert("dns_resolver_id", &settings.dns_resolver_id);
@ -55,10 +56,14 @@ impl Engine {
match self.tera.render(&(template_name.clone()+&settings.format.get_file_extension()), &context) {
Ok(text) =>
match settings.format {
ResponseFormat::Html => Html(text).into_response(),
_ => text.into_response(),
}
(
[(
header::CONTENT_TYPE,
HeaderValue::from_str(mime_type.as_ref())
.expect("MimeType should always be a valid header value.")
)],
Into::<Full<Bytes>>::into(text),
).into_response(),
Err(e) => {
println!("There was an error while rendering template {}: {e:?}", template_name);
(