use url::Url;
use super::constant::*;
use super::error::{GenericError, TosError};
use super::internal::url_encode_with_safe;
#[derive(Debug, Clone)]
pub(crate) struct ConfigHolder {
pub(crate) user_agent: String,
pub(crate) region: String,
pub(crate) max_retry_count: isize,
pub(crate) request_timeout: isize,
pub(crate) connection_timeout: isize,
pub(crate) max_connections: isize,
pub(crate) idle_connection_time: isize,
pub(crate) enable_verify_ssl: bool,
pub(crate) auto_recognize_content_type: bool,
pub(crate) is_custom_domain: bool,
pub(crate) proxy_host: String,
pub(crate) proxy_port: isize,
pub(crate) proxy_username: String,
pub(crate) proxy_password: String,
pub(crate) schema: String,
pub(crate) domain: String,
}
impl Default for ConfigHolder {
fn default() -> Self {
ConfigHolder {
user_agent: String::from("ve-tos-rust-sdk/".to_string() + env!("CARGO_PKG_VERSION") +
" (" + std::env::consts::OS + "/" + std::env::consts::ARCH + ")"),
region: DEFAULT_REGION.to_string(),
max_retry_count: DEFAULT_MAX_RETRY_COUNT,
request_timeout: DEFAULT_REQUEST_TIMEOUT,
connection_timeout: DEFAULT_CONNECTION_TIMEOUT,
max_connections: DEFAULT_MAX_CONNECTIONS,
idle_connection_time: DEFAULT_IDLE_CONNECTION_TIME,
enable_verify_ssl: true,
auto_recognize_content_type: true,
is_custom_domain: false,
proxy_host: "".to_string(),
proxy_port: -1,
proxy_username: "".to_string(),
proxy_password: "".to_string(),
schema: "".to_string(),
domain: "".to_string(),
}
}
}
impl ConfigHolder {
pub(crate) fn check(&mut self, endpoint: impl Into<String>, region: impl Into<String>) -> Result<(), TosError> {
let region = region.into().trim().to_owned();
if region == "" {
return TosError::client_error_result("no region specified");
}
let mut endpoint = endpoint.into().trim().to_owned();
if endpoint == "" {
if let Some(value) = REGION_ENDPOINTS.get(region.as_str()) {
endpoint = (*value).to_string();
}
}
if endpoint == "" {
return TosError::client_error_result("no endpoint specified");
}
let (schema, domain) = self.split_endpoint(endpoint.as_str())?;
self.region = region.to_owned();
self.schema = schema;
self.domain = domain;
Ok(())
}
pub(crate) fn split_endpoint(&self, endpoint: &str) -> Result<(String, String), TosError> {
let mut endpoint = endpoint;
while endpoint.len() > 0 && endpoint.ends_with("/") {
endpoint = &endpoint[0..endpoint.len() - 1];
}
if endpoint.len() == 0 {
return Err(TosError::client_error("invalid endpoint"));
}
endpoint = endpoint.trim();
let mut schema = String::with_capacity(SCHEMA_HTTP.len());
let domain;
if endpoint.starts_with(SCHEMA_HTTP) {
schema.push_str(SCHEMA_HTTP);
(domain, _) = self.parse_domain(endpoint)?;
} else if endpoint.starts_with(SCHEMA_HTTPS) {
schema.push_str(SCHEMA_HTTPS);
(domain, _) = self.parse_domain(endpoint)?;
} else {
schema.push_str(SCHEMA_HTTPS);
(domain, _) = self.parse_domain((SCHEMA_HTTPS.to_owned() + endpoint).as_str())?;
}
Ok((schema, domain))
}
pub(crate) fn parse_domain(&self, input: &str) -> Result<(String, String), TosError> {
let mut domain = String::with_capacity(input.len());
match Url::parse(input) {
Ok(u) => {
if let Some(host) = u.host() {
if let Some(port) = u.port() {
domain.push_str(&format!("{}:{}", host, port));
} else {
domain.push_str(host.to_string().as_str());
}
Ok((domain, u.scheme().to_string()))
} else {
Err(TosError::client_error("no host error"))
}
}
Err(e) => {
Err(TosError::client_error_with_cause("parse domain error", GenericError::UrlParseError(e)))
}
}
}
pub(crate) fn get_host(&self, bucket: &str) -> String {
self.get_host_with_domain(bucket, "")
}
pub(crate) fn get_host_with_domain(&self, bucket: &str, domain: &str) -> String {
let mut host = String::with_capacity(bucket.len() + domain.len() + 1);
if bucket != "" {
host += bucket;
host += ".";
}
if domain == "" {
host += &self.domain;
} else {
host += domain;
}
host
}
pub(crate) fn get_endpoint(&self, bucket: &str, key: &str) -> String {
self.get_endpoint_with_domain(bucket, key, "", "", false)
}
pub(crate) fn get_endpoint_with_domain(&self, bucket: &str, key: &str, schema: &str, domain: &str, must_add_key: bool) -> String {
let mut endpoint = String::with_capacity(schema.len() + domain.len() + bucket.len() + key.len() * 2 + 3);
if schema == "" {
endpoint += &self.schema;
} else {
endpoint += schema;
}
if bucket != "" {
endpoint += bucket;
endpoint += ".";
}
if domain == "" {
endpoint += &self.domain;
} else {
endpoint += domain;
}
if key != "" {
if must_add_key || bucket != "" {
endpoint += "/";
endpoint += url_encode_with_safe(key, "/").as_str();
}
}
endpoint
}
}