use std::collections::HashMap;
use std::time::Duration;
use multistore::backend::multipart::build_backend_url;
use multistore::backend::url_signer::build_signer;
use multistore::types::{BucketConfig, S3Operation};
use object_store::path::Path;
use percent_encoding::percent_decode_str;
const KEYS: &[&str] = &[
"plain/file.bin",
"by_country/country_iso=ETH/ETH.pmtiles",
"spaces in/every segment.txt",
"specials !('):@+,;$&.bin",
"unicode/café/naïve.txt",
"report*.pdf",
"100%.txt",
"tilde~hash#pipe|.bin",
"brackets[1]{2}.bin",
"literal-%3D-triplet.txt",
];
fn bucket_config(with_creds: bool) -> BucketConfig {
let mut backend_options: HashMap<String, String> = HashMap::new();
backend_options.insert(
"endpoint".into(),
"https://s3.us-east-1.amazonaws.com".into(),
);
backend_options.insert("bucket_name".into(), "backend-bucket".into());
backend_options.insert("region".into(), "us-east-1".into());
if with_creds {
backend_options.insert("access_key_id".into(), "AKIAIOSFODNN7EXAMPLE".into());
backend_options.insert(
"secret_access_key".into(),
"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY".into(),
);
}
BucketConfig {
name: "test".into(),
backend_type: "s3".into(),
backend_prefix: None,
anonymous_access: !with_creds,
allowed_roles: vec![],
backend_options,
}
}
fn presigned_path(config: &BucketConfig, key: &str) -> String {
let signer = build_signer(config).unwrap();
let path = Path::parse(key).unwrap();
let url = futures::executor::block_on(signer.signed_url(
http::Method::GET,
&path,
Duration::from_secs(60),
))
.unwrap();
url.path().to_string()
}
fn raw_signed_path(config: &BucketConfig, key: &str) -> String {
let op = S3Operation::CreateMultipartUpload {
bucket: "test".into(),
key: key.into(),
};
let url = build_backend_url(config, &op).unwrap();
url::Url::parse(&url).unwrap().path().to_string()
}
#[test]
fn all_builders_agree_byte_for_byte() {
let authed = bucket_config(true);
let anon = bucket_config(false);
for key in KEYS {
let presigned = presigned_path(&authed, key);
let raw = raw_signed_path(&authed, key);
let unsigned = presigned_path(&anon, key);
assert_eq!(presigned, raw, "presigned vs raw-signed for key {key:?}");
assert_eq!(
presigned, unsigned,
"presigned vs anonymous for key {key:?}"
);
}
}
#[test]
fn wire_paths_decode_to_the_logical_key() {
let config = bucket_config(true);
for key in KEYS {
let path = presigned_path(&config, key);
let decoded = percent_decode_str(&path).decode_utf8().unwrap();
assert_eq!(decoded, format!("/backend-bucket/{key}"), "key {key:?}");
}
}