use crate::s3::Client;
use crate::s3::client::DEFAULT_EXPIRY_SECONDS;
use crate::s3::creds::Credentials;
use crate::s3::error::Error;
use crate::s3::multimap::{Multimap, MultimapExt};
use crate::s3::response::GetPresignedObjectUrlResponse;
use crate::s3::signer::presign_v4;
use crate::s3::utils::{UtcTime, check_bucket_name, check_object_name, utc_now};
use http::Method;
#[derive(Clone, Debug, Default)]
pub struct GetPresignedObjectUrl {
client: Client,
extra_query_params: Option<Multimap>,
region: Option<String>,
bucket: String,
object: String,
version_id: Option<String>,
method: Method,
expiry_seconds: Option<u32>,
request_time: Option<UtcTime>,
}
impl GetPresignedObjectUrl {
pub fn new(client: Client, bucket: String, object: String, method: Method) -> Self {
Self {
client,
bucket,
object,
method,
expiry_seconds: Some(DEFAULT_EXPIRY_SECONDS),
..Default::default()
}
}
pub async fn send(self) -> Result<GetPresignedObjectUrlResponse, Error> {
check_bucket_name(&self.bucket, true)?;
check_object_name(&self.object)?;
let region: String = self.client.get_region_cached(&self.bucket, &self.region)?;
let mut query_params: Multimap = self.extra_query_params.unwrap_or_default();
query_params.add_version(self.version_id.clone());
let mut url = self.client.shared.base_url.build_url(
&self.method,
®ion,
&query_params,
Some(&self.bucket),
Some(&self.object),
)?;
if let Some(p) = &self.client.shared.provider {
let creds: Credentials = p.fetch();
if let Some(t) = creds.session_token {
query_params.add("X-Amz-Security-Token", t);
}
let date = match self.request_time {
Some(v) => v,
_ => utc_now(),
};
presign_v4(
&self.method,
&url.host_header_value(),
&url.path,
®ion,
&mut query_params,
&creds.access_key,
&creds.secret_key,
date,
self.expiry_seconds.unwrap_or(DEFAULT_EXPIRY_SECONDS),
);
url.query = query_params;
}
Ok(GetPresignedObjectUrlResponse {
region,
bucket: self.bucket,
object: self.object,
version_id: self.version_id,
url: url.to_string(),
})
}
}