add metadata
This commit is contained in:
parent
e4e4a3dc7f
commit
462134b36d
143
Cargo.lock
generated
143
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
71
src/main.rs
71
src/main.rs
|
@ -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))?;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue