Improve asset mime handling robustness and readability
Some checks failed
/ publish (push) Has been cancelled

This commit is contained in:
Juno Takano 2026-03-16 20:11:59 -03:00
commit ce61c0df27
3 changed files with 27 additions and 31 deletions

10
Cargo.lock generated
View file

@ -135,9 +135,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cc"
version = "1.2.56"
version = "1.2.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423"
dependencies = [
"find-msvc-tools",
"shlex",
@ -259,7 +259,7 @@ dependencies = [
[[package]]
name = "en"
version = "0.3.0-alpha"
version = "0.3.1-alpha"
dependencies = [
"axum",
"serde",
@ -616,9 +616,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.21.3"
version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "parse-zoneinfo"

View file

@ -1,6 +1,6 @@
[package]
name = "en"
version = "0.3.0-alpha"
version = "0.3.1-alpha"
description = "A non-linear writing instrument."
license = "AGPL-3.0-only"

View file

@ -8,6 +8,7 @@ use axum::{
use serde::Serialize;
use crate::{
dev::log,
graph::{Format, Graph, SerialErrorCause},
prelude::*,
router::{
@ -18,17 +19,6 @@ use crate::{
/// Assembles an HTTP response given Asset.
fn assemble(asset: Asset, graph: &Graph) -> Response<Body> {
let kind = match asset.mime.kind() {
Ok(kind) => kind,
Err(error) => {
return error::make(
Some(500),
Some(&format!("Could not determine a mimetype kind: {error}")),
graph,
)
},
};
let set_content_type = |response: &mut Response<_>, content_type: &str| {
if let Ok(header_value) =
HeaderValue::from_str(&String::from(content_type))
@ -37,6 +27,8 @@ fn assemble(asset: Asset, graph: &Graph) -> Response<Body> {
.headers_mut()
.append(header::CONTENT_TYPE, header_value);
} else {
// This should be unreachable considering the possible mimetypes
// and their string representations are internal to en
log!(
WARN,
"Failed to create content type header value from {content_type}"
@ -44,7 +36,7 @@ fn assemble(asset: Asset, graph: &Graph) -> Response<Body> {
}
};
match kind {
match asset.mime.kind() {
mime::Kind::Text => {
if let Some(text) = asset.text {
let mut response = Response::new(Body::from(text));
@ -54,6 +46,8 @@ fn assemble(asset: Asset, graph: &Graph) -> Response<Body> {
);
response
} else {
// This should be unreachable, considering the constructors
// will convert to text even if a blob is passed
let mut response = error::make(
Some(500),
Some(
@ -75,6 +69,8 @@ fn assemble(asset: Asset, graph: &Graph) -> Response<Body> {
);
response
} else {
// This should be unreachable, considering the constructors
// will convert to blob even if a text is passed
let mut response = error::make(
Some(500),
Some(
@ -182,7 +178,7 @@ struct Asset {
impl Asset {
fn new(blob: &[u8], mime: mime::Mime) -> Result<Asset, AssetError> {
match mime.kind()? {
match mime.kind() {
mime::Kind::Text => Ok(Asset {
text: Some(String::from_utf8(blob.to_vec())?),
blob: None,
@ -198,19 +194,17 @@ impl Asset {
}
}
fn from_str(str: &str, mime: mime::Mime) -> Result<Asset, AssetError> {
match mime.kind()? {
mime::Kind::Text => Ok(Asset {
fn from_str(str: &str, mime: mime::Mime) -> Asset {
match mime.kind() {
mime::Kind::Text => Asset {
text: Some(String::from(str)),
blob: None,
mime,
}),
mime::Kind::Font | mime::Kind::Image | mime::Kind::Blob => {
Ok(Asset {
text: None,
blob: Some(String::from(str).into_bytes()),
mime,
})
},
mime::Kind::Font | mime::Kind::Image | mime::Kind::Blob => Asset {
text: None,
blob: Some(String::from(str).into_bytes()),
mime,
},
}
}
@ -239,7 +233,7 @@ fn fallback(path: &str, graph: &Graph) -> Result<Asset, AssetError> {
Err(io_error) => {
if io_error.kind() == ErrorKind::NotFound {
if let Some(content) = defaults.get(path) {
Asset::from_str(content, mime)
Ok(Asset::from_str(content, mime))
} else {
let not_found_error = Err(AssetError::new(
path,
@ -625,6 +619,8 @@ static CCND: License = License {
#[cfg(test)]
mod tests {
use axum::http::status::StatusCode;
use super::*;
async fn wrap_serial(format: &str) -> Response<Body> {
@ -670,6 +666,6 @@ mod tests {
graph: Graph::default(),
};
let response = file(Path("/k/j/m".to_string()), State(state)).await;
assert!(response.status() == axum::http::status::StatusCode::NOT_FOUND);
assert!(response.status() == StatusCode::NOT_FOUND);
}
}