crate to handle just mimetype ops

This commit is contained in:
Brandon Thomas committed 2023-04-23 00:08:59 -07:00
1 parent 8c5fb0bee2
commit 2f86bc75ac
7 files changed
+142 -3

No files matched your search

Generated
+8
View File
@@ -4173,6 +4173,14 @@ dependencies = [
"unicase",
]
[[package]]
name = "mimetypes"
version = "0.0.1"
dependencies = [
"errors",
"infer 0.11.0",
]
[[package]]
name = "minidom"
version = "0.15.0"
+1
View File
@@ -35,6 +35,7 @@ members = [
"crates/lib/idempotency",
"crates/lib/jobs_common",
"crates/lib/media",
"crates/lib/mimetypes",
"crates/lib/mysql_queries",
"crates/lib/redis_common",
"crates/lib/sqlite_queries",
+24
View File
@@ -0,0 +1,24 @@
[package]
name = "mimetypes"
edition = "2018"
version = "0.0.1"
authors = [
"Brandon Thomas <bt@brand.io>",
"Brandon Thomas <echelon@gmail.com>",
]
publish = false
[lib]
# NB: Public "mimetypes" crate does not exist, so it's safe to use for now.
name = "mimetypes"
path = "src/lib.rs"
[dependencies]
# Internal
errors = { path = "../../lib/errors" }
# External
infer = "0.11" # Mimetype detection
[dev-dependencies]
# None yet
+22
View File
@@ -0,0 +1,22 @@
//! mimetypes
//!
//! The purpose of this library is to perform mimetype detection routines on files, raw bytes,
//! streams, etc.
//!
// Never allow these
#![forbid(private_in_public)]
#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things
// Okay to toggle
#![forbid(unreachable_patterns)]
#![forbid(unused_imports)]
#![forbid(unused_mut)]
#![forbid(unused_variables)]
// Always allow
#![allow(dead_code)]
#![allow(non_snake_case)]
pub mod mimetype_for_bytes;
pub mod mimetype_for_file;
@@ -0,0 +1,41 @@
const DEFAULT_BINARY_MIMETYPE : &'static str = "application/octet-stream";
pub fn get_mimetype_for_bytes(bytes: &[u8]) -> Option<&'static str> {
infer::get(bytes)
.map(|typ| typ.mime_type())
}
pub fn get_mimetype_for_bytes_or_default(bytes: &[u8]) -> &'static str {
infer::get(bytes)
.map(|typ| typ.mime_type())
.unwrap_or(DEFAULT_BINARY_MIMETYPE)
}
#[cfg(test)]
mod tests {
use crate::mimetype_for_bytes::{get_mimetype_for_bytes, get_mimetype_for_bytes_or_default};
#[test]
fn test_mimetype_png() {
// NB: From "Hanashi Mask.png"
let bytes : Vec<u8> = vec![
137, 80, 78, 71, 13, 10, 26, 10,
0, 0, 0, 13, 73, 72, 68, 82,
0, 0, 20, 193, 0, 0, 15, 239,
8, 6, 0, 0, 0, 163, 131, 119,
122, 0, 0, 0,
];
assert_eq!(get_mimetype_for_bytes(&bytes), Some("image/png"));
assert_eq!(get_mimetype_for_bytes_or_default(&bytes), "image/png");
}
#[test]
fn test_mimetype_unknown() {
let bytes : Vec<u8> = vec![];
assert_eq!(get_mimetype_for_bytes(&bytes), None);
assert_eq!(get_mimetype_for_bytes_or_default(&bytes), "application/octet-stream");
}
}
@@ -0,0 +1,43 @@
use std::path::Path;
const DEFAULT_BINARY_MIMETYPE : &'static str = "application/octet-stream";
pub fn get_mimetype_for_file<P: AsRef<Path>>(file: P) -> std::io::Result<Option<&'static str>> {
infer::get_from_path(file)
.map(|maybe_type| maybe_type.map(|typ| typ.mime_type()))
}
pub fn get_mimetype_for_file_or_default<P: AsRef<Path>>(file: P) -> std::io::Result<&'static str> {
get_mimetype_for_file(file)
.map(|maybe_type| match maybe_type {
Some(mimetype) => mimetype,
None => DEFAULT_BINARY_MIMETYPE,
})
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use crate::mimetype_for_file::get_mimetype_for_file;
fn test_file(path_from_repo_root: &str) -> PathBuf {
// https://doc.rust-lang.org/cargo/reference/environment-variables.html
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push(format!("../../../{}", path_from_repo_root));
path
}
#[test]
fn test_mimetype_mp3() {
let path = test_file("test_data/audio/mp3/super_mario_rpg_beware_the_forests_mushrooms.mp3");
assert_eq!(get_mimetype_for_file(&path).unwrap(), Some("audio/mpeg"));
}
#[test]
fn test_mimetype_unknown() {
let path = test_file("test_data/video/mp4/golden_sun_garoh.mp4");
assert_eq!(get_mimetype_for_file(&path).unwrap(), Some("video/mp4"));
}
}
@@ -14,8 +14,6 @@ use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
use crate::server_state::ServerState;
use crate::validations::model_uploads::validate_model_title;
use crate::validations::validate_idempotency_token_format::validate_idempotency_token_format;
use mysql_queries::payloads::media_upload_modification_details::MediaUploadModificationDetails;
use mysql_queries::queries::media_uploads::insert_media_upload::{Args, insert_media_upload};
use enums::by_table::media_uploads::media_upload_type::MediaUploadType;
use enums::common::visibility::Visibility;
use files::hash::hash_bytes_sha2;
@@ -24,6 +22,9 @@ use http_server_common::request::get_request_ip::get_request_ip;
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
use log::{info, warn, log, error};
use media::decode_basic_audio_info::decode_basic_audio_info;
use mysql_queries::payloads::media_upload_modification_details::MediaUploadModificationDetails;
use mysql_queries::queries::media_uploads::get_media_upload_by_uuid::{get_media_upload_by_uuid, get_media_upload_by_uuid_with_connection};
use mysql_queries::queries::media_uploads::insert_media_upload::{Args, insert_media_upload};
use regex::Regex;
use sqlx::error::DatabaseError;
use sqlx::error::Error::Database;
@@ -35,7 +36,6 @@ use symphonia::core::formats::FormatOptions;
use symphonia::core::io::{MediaSourceStream, ReadOnlySource};
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;
use mysql_queries::queries::media_uploads::get_media_upload_by_uuid::{get_media_upload_by_uuid, get_media_upload_by_uuid_with_connection};
use tokens::files::media_upload::MediaUploadToken;
#[derive(Serialize)]