Blossom: Determine mime type and supply extension in Blob Descriptor URL

This commit is contained in:
Mike Dilger 2024-12-10 09:16:33 +13:00
parent a4544702b5
commit 3cacc4e963
No known key found for this signature in database
GPG Key ID: 47581A78D4329BA4
4 changed files with 77 additions and 7 deletions

36
Cargo.lock generated
View File

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "addr2line"
@ -278,6 +278,8 @@ dependencies = [
"hyper-util",
"lazy_static",
"log",
"mime-sniffer",
"new_mime_guess",
"parking_lot",
"pocket-db",
"pocket-types",
@ -1094,6 +1096,22 @@ dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime-sniffer"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b8b2a64cd735f1d5f17ff6701ced3cc3c54851f9448caf454cd9c923d812408"
dependencies = [
"mime",
"url",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -1137,6 +1155,16 @@ dependencies = [
"memmap2",
]
[[package]]
name = "new_mime_guess"
version = "4.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02a2dfb3559d53e90b709376af1c379462f7fb3085a0177deb73e6ea0d99eff4"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "nom"
version = "7.1.3"
@ -1931,6 +1959,12 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicase"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
[[package]]
name = "unicode-ident"
version = "1.0.13"

View File

@ -21,6 +21,8 @@ hyper-tungstenite = "0.15"
hyper-util = "0.1"
lazy_static = "1.5"
log = "0.4"
mime-sniffer = "0.1"
new_mime_guess = "4.0"
pocket-types = { git = "https://github.com/mikedilger/pocket", branch = "master" }
pocket-db = { git = "https://github.com/mikedilger/pocket", branch = "master" }
parking_lot = "0.12"

View File

@ -48,7 +48,7 @@ impl FileStore {
&self,
data: BoxBody<Bytes, Error>,
expected_hash: Option<HashOutput>,
) -> Result<(u64, HashOutput), Error> {
) -> Result<(u64, HashOutput, Option<String>), Error> {
use bitcoin_hashes::sha256;
use std::io::Write; // for hash_engine.write_all()
@ -78,6 +78,7 @@ impl FileStore {
// Copy the data into the tempfile (hashing and counting as we go)
let count = tokio::io::copy(&mut inspect_reader, &mut tempfile).await?;
drop(tempfile);
// Verify our code was correct
if count != size {
@ -101,6 +102,16 @@ impl FileStore {
}
}
// Sniff the mime-type
let maybe_mime_string = {
use mime_sniffer::MimeTypeSniffer;
use tokio::io::AsyncReadExt;
let mut readtempfile = File::open(&temppathbuf).await?;
let mut buffer: Vec<u8> = vec![0; 128];
let _ = readtempfile.read(&mut buffer).await?;
buffer.sniff_mime_type().map(|s| s.to_string())
};
// Compute the proper path
let pathbuf = hash.to_pathbuf(&self.base);
@ -109,7 +120,7 @@ impl FileStore {
// Just clean up
fs::remove_file(&temppathbuf).await?;
return Ok((size, hash));
return Ok((size, hash, maybe_mime_string));
}
// Make the parent directory
@ -118,7 +129,7 @@ impl FileStore {
// Move the file
fs::rename(&temppathbuf, &pathbuf).await?;
Ok((size, hash))
Ok((size, hash, maybe_mime_string))
}
/// Retrieve a file from storage by its HashOutput, streamed to a hyper BoxBoxy

View File

@ -229,7 +229,15 @@ pub async fn handle_upload(
let uri = request.uri().to_owned();
let (size, hash) = GLOBALS
let maybe_content_type = match request.headers().get(http::header::CONTENT_TYPE) {
Some(s) => match s.to_str() {
Ok(s) => Some(s.to_owned()),
Err(_) => None,
},
None => None,
};
let (size, hash, maybe_sniffed_mime_string) = GLOBALS
.filestore
.get()
.unwrap()
@ -239,11 +247,26 @@ pub async fn handle_upload(
)
.await?;
let extension = {
let mut mime_string: String = "".to_owned();
if let Some(ms) = maybe_content_type {
mime_string = ms.to_owned();
} else if let Some(ms) = maybe_sniffed_mime_string {
mime_string = ms.to_owned();
}
if let Some(exts) = new_mime_guess::get_mime_extensions_str(&mime_string) {
exts[0]
} else {
"blob"
}
};
let uri = {
let mut parts = GLOBALS.config.read().uri_parts(uri, true)?;
parts.path_and_query = Some(http::uri::PathAndQuery::from_maybe_shared(format!(
"/{}",
hash
"/{}.{}",
hash, extension
))?);
http::Uri::from_parts(parts)?
};