add metadata

This commit is contained in:
Allie Signet 2022-06-30 21:30:28 -03:00
parent e4e4a3dc7f
commit 462134b36d
3 changed files with 201 additions and 14 deletions

143
Cargo.lock generated
View file

@ -2,6 +2,17 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "anyhow"
version = "1.0.58"
@ -69,6 +80,27 @@ dependencies = [
"safemem",
]
[[package]]
name = "bytecheck"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a31f923c2db9513e4298b72df143e6e655a759b3d6a0966df18f81223fff54f"
dependencies = [
"bytecheck_derive",
"ptr_meta",
]
[[package]]
name = "bytecheck_derive"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edb17c862a905d912174daa27ae002326fff56dc8b8ada50a0a5f0976cb174f0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -90,6 +122,7 @@ dependencies = [
"blake2",
"lmdb-zero",
"multipart",
"rkyv",
"tiny_http",
"url",
]
@ -161,6 +194,15 @@ dependencies = [
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
dependencies = [
"ahash",
]
[[package]]
name = "httparse"
version = "1.7.1"
@ -285,6 +327,12 @@ dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]]
name = "percent-encoding"
version = "2.1.0"
@ -297,12 +345,50 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro2"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
dependencies = [
"unicode-ident",
]
[[package]]
name = "ptr_meta"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
@ -351,12 +437,52 @@ dependencies = [
"winapi",
]
[[package]]
name = "rend"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95"
dependencies = [
"bytecheck",
]
[[package]]
name = "rkyv"
version = "0.7.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15"
dependencies = [
"bytecheck",
"hashbrown",
"ptr_meta",
"rend",
"rkyv_derive",
"seahash",
]
[[package]]
name = "rkyv_derive"
version = "0.7.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "safemem"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "subtle"
version = "2.4.1"
@ -369,6 +495,17 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "171758edb47aa306a78dfa4ab9aeb5167405bd4e3dc2b64e88f6a84bbe98bd63"
[[package]]
name = "syn"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.3.0"
@ -459,6 +596,12 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
[[package]]
name = "unicode-normalization"
version = "0.1.20"

View file

@ -11,5 +11,6 @@ base64-url = "1.4.13"
blake2 = "0.10.4"
lmdb-zero = "0.4.4"
multipart = { git = "https://github.com/emily-signet/multipart", default-features = false, features = ["server", "tiny_http"] }
rkyv = { version = "0.7.39", features = ["strict", "archive_le"] }
tiny_http = "0.11.0"
url = "2.2.2"

View file

@ -5,16 +5,20 @@ use blake2::{Blake2s256, Digest};
use lmdb::{Database, Environment, LmdbResultExt};
use lmdb_zero as lmdb;
use multipart::server::Multipart;
use std::{
io::{self, Read},
sync::Arc,
thread,
};
use tiny_http::{Request, Response};
use rkyv::option::ArchivedOption;
use std::{io::Read, sync::Arc, thread};
use tiny_http::{Header, Request, Response};
#[derive(rkyv::Archive, rkyv::Serialize)]
pub struct FileHeader {
file_name: Option<String>,
content_type: Option<String>,
}
#[derive(Clone)]
pub struct DatabaseContext {
env: Arc<Environment>,
metadata_store: Arc<Database<'static>>,
binary_store: Arc<Database<'static>>,
image_store: Arc<Database<'static>>,
}
@ -23,7 +27,7 @@ impl DatabaseContext {
pub fn create(path: &str) -> anyhow::Result<DatabaseContext> {
let env = Arc::new(unsafe {
let mut builder = lmdb::EnvBuilder::new()?;
builder.set_maxdbs(2)?;
builder.set_maxdbs(3)?;
builder.open(path, lmdb::open::NOTLS, 0o600)?
});
@ -37,10 +41,16 @@ impl DatabaseContext {
Some("image"),
&lmdb::DatabaseOptions::new(lmdb::db::CREATE),
)?);
let metadata_store = Arc::new(lmdb::Database::open(
env.clone(),
Some("metadata"),
&lmdb::DatabaseOptions::new(lmdb::db::CREATE),
)?);
Ok(DatabaseContext {
env,
binary_store,
metadata_store,
image_store,
})
}
@ -123,6 +133,21 @@ fn process_upload(mut request: Request, db_context: &DatabaseContext) -> anyhow:
lmdb::put::Flags::empty(),
)?;
let header = FileHeader {
file_name: entry.headers.filename,
content_type: entry
.headers
.content_type
.map(|v| v.essence_str().to_owned()),
};
accessor.put(
&db_context.metadata_store,
data_hash.as_slice(),
rkyv::to_bytes::<_, 256>(&header)?.as_slice(),
lmdb::put::Flags::empty(),
)?;
request.respond(Response::from_string(base64_url::encode(&data_hash)))?;
drop(accessor);
@ -147,13 +172,31 @@ fn process_get(request: Request, db_context: &DatabaseContext) -> anyhow::Result
.to_opt()
.unwrap()
{
request.respond(Response::new(
200.into(),
vec![],
data,
Some(data.len()),
None,
))?;
let header_bytes = access
.get::<[u8], [u8]>(&db_context.metadata_store, &get_id)
.to_opt()?
.ok_or(anyhow::anyhow!("header missing for file"))?;
let header = unsafe { rkyv::archived_root::<FileHeader>(header_bytes) };
let mut response = Response::new(200.into(), vec![], data, Some(data.len()), None);
if let ArchivedOption::Some(ref file_name) = header.file_name {
response = response.with_header(
Header::from_bytes(
&b"Content-Disposition"[..],
format!("inline; filename=\"{file_name}\"").into_bytes(),
)
.unwrap(),
);
}
if let ArchivedOption::Some(ref mime_type) = header.content_type {
response = response.with_header(
Header::from_bytes(&b"Content-Type"[..], mime_type.as_bytes()).unwrap(),
);
}
request.respond(response)?;
} else {
request.respond(Response::empty(404))?;
}