mirror of
https://github.com/minio/minio-rs.git
synced 2025-12-06 15:26:51 +08:00
Add FromStr instance to BaseURL (#51)
This commit is contained in:
parent
e5f6b16051
commit
4958c01f4c
57
README.md
57
README.md
@ -5,64 +5,9 @@ MinIO Rust SDK is Simple Storage Service (aka S3) client to perform bucket and o
|
||||
For a complete list of APIs and examples, please take a look at the [MinIO Rust Client API Reference](https://minio-rs.min.io/)
|
||||
|
||||
## Example:: file-uploader.rs
|
||||
```rust
|
||||
use minio::s3::args::{BucketExistsArgs, MakeBucketArgs, UploadObjectArgs};
|
||||
use minio::s3::client::Client;
|
||||
use minio::s3::creds::StaticProvider;
|
||||
use minio::s3::http::BaseUrl;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let base_url = BaseUrl::from_string("https://play.min.io".to_string()).unwrap();
|
||||
[Upload a file to MinIO](examples/file-uploader.rs)
|
||||
|
||||
let static_provider = StaticProvider::new(
|
||||
"Q3AM3UQ867SPQQA43P2F",
|
||||
"zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
|
||||
None,
|
||||
);
|
||||
|
||||
let client = Client::new(
|
||||
base_url.clone(),
|
||||
Some(Box::new(static_provider)),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let bucket_name = "asiatrip";
|
||||
|
||||
// Check 'asiatrip' bucket exist or not.
|
||||
let exists = client
|
||||
.bucket_exists(&BucketExistsArgs::new(&bucket_name).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Make 'asiatrip' bucket if not exist.
|
||||
if !exists {
|
||||
client
|
||||
.make_bucket(&MakeBucketArgs::new(&bucket_name).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Upload '/home/user/Photos/asiaphotos.zip' as object name
|
||||
// 'asiaphotos-2015.zip' to bucket 'asiatrip'.
|
||||
client
|
||||
.upload_object(
|
||||
&mut UploadObjectArgs::new(
|
||||
&bucket_name,
|
||||
"asiaphotos-2015.zip",
|
||||
"/home/user/Photos/asiaphotos.zip",
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("'/home/user/Photos/asiaphotos.zip' is successfully uploaded as object 'asiaphotos-2015.zip' to bucket 'asiatrip'.");
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
This SDK is distributed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0), see [LICENSE](https://github.com/minio/minio-rs/blob/master/LICENSE) for more information.
|
||||
|
||||
@ -5,7 +5,7 @@ use minio::s3::http::BaseUrl;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let base_url = BaseUrl::from_string("https://play.min.io".to_string()).unwrap();
|
||||
let base_url = "https://play.min.io".parse::<BaseUrl>()?;
|
||||
|
||||
let static_provider = StaticProvider::new(
|
||||
"Q3AM3UQ867SPQQA43P2F",
|
||||
|
||||
@ -224,7 +224,7 @@ impl Client {
|
||||
/// use minio::s3::client::Client;
|
||||
/// use minio::s3::creds::StaticProvider;
|
||||
/// use minio::s3::http::BaseUrl;
|
||||
/// let mut base_url = BaseUrl::from_string("play.min.io".to_string()).unwrap();
|
||||
/// let mut base_url: BaseUrl = "play.min.io".parse().unwrap();
|
||||
/// let static_provider = StaticProvider::new(
|
||||
/// "Q3AM3UQ867SPQQA43P2F",
|
||||
/// "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
|
||||
|
||||
194
src/s3/http.rs
194
src/s3/http.rs
@ -24,6 +24,7 @@ use hyper::Uri;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
const AWS_S3_PREFIX: &str = r"^(((bucket\.|accesspoint\.)vpce(-[a-z_\d]+)+\.s3\.)|([a-z_\d-]{1,63}\.)s3-control(-[a-z_\d]+)*\.|(s3(-[a-z_\d]+)*\.))";
|
||||
|
||||
@ -217,6 +218,107 @@ pub struct BaseUrl {
|
||||
pub virtual_style: bool,
|
||||
}
|
||||
|
||||
impl FromStr for BaseUrl {
|
||||
type Err = Error;
|
||||
|
||||
/// Convert a string to a BaseUrl.
|
||||
///
|
||||
/// Enables use of [`str`]'s [`parse`] method to create a [`BaseUrl`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use minio::s3::http::BaseUrl;
|
||||
/// use std::str::FromStr;
|
||||
///
|
||||
/// // Get base URL from host name
|
||||
/// let base_url = "play.min.io".parse::<BaseUrl>().unwrap();
|
||||
/// let base_url = BaseUrl::from_str("play.min.io").unwrap();
|
||||
/// // Get base URL from host:port
|
||||
/// let base_url: BaseUrl = "play.minio.io:9000".parse().unwrap();
|
||||
/// // Get base URL from IPv4 address
|
||||
/// let base_url: BaseUrl = "http://192.168.124.63:9000".parse().unwrap();
|
||||
/// // Get base URL from IPv6 address
|
||||
/// let base_url: BaseUrl = "[0:0:0:0:0:ffff:c0a8:7c3f]:9000".parse().unwrap();
|
||||
/// ```
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let url = s.parse::<Uri>()?;
|
||||
|
||||
let https = match url.scheme() {
|
||||
None => true,
|
||||
Some(scheme) => match scheme.as_str() {
|
||||
"http" => false,
|
||||
"https" => true,
|
||||
_ => {
|
||||
return Err(Error::InvalidBaseUrl(String::from(
|
||||
"scheme must be http or https",
|
||||
)))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mut host = match url.host() {
|
||||
Some(h) => h,
|
||||
_ => {
|
||||
return Err(Error::InvalidBaseUrl(String::from(
|
||||
"valid host must be provided",
|
||||
)))
|
||||
}
|
||||
};
|
||||
|
||||
let ipv6host = "[".to_string() + host + "]";
|
||||
if host.parse::<std::net::Ipv6Addr>().is_ok() {
|
||||
host = &ipv6host;
|
||||
}
|
||||
|
||||
let mut port = match url.port() {
|
||||
Some(p) => p.as_u16(),
|
||||
_ => 0u16,
|
||||
};
|
||||
|
||||
if (https && port == 443) || (!https && port == 80) {
|
||||
port = 0u16;
|
||||
}
|
||||
|
||||
if url.path() != "/" && url.path() != "" {
|
||||
return Err(Error::InvalidBaseUrl(String::from(
|
||||
"path must be empty for base URL",
|
||||
)));
|
||||
}
|
||||
|
||||
if url.query().is_some() {
|
||||
return Err(Error::InvalidBaseUrl(String::from(
|
||||
"query must be none for base URL",
|
||||
)));
|
||||
}
|
||||
|
||||
let mut region = String::new();
|
||||
let mut aws_s3_prefix = String::new();
|
||||
let mut aws_domain_suffix = String::new();
|
||||
let mut dualstack: bool = false;
|
||||
get_aws_info(
|
||||
&host.to_string(),
|
||||
https,
|
||||
&mut region,
|
||||
&mut aws_s3_prefix,
|
||||
&mut aws_domain_suffix,
|
||||
&mut dualstack,
|
||||
)?;
|
||||
let virtual_style = !aws_domain_suffix.is_empty() || host.ends_with("aliyuncs.com");
|
||||
|
||||
Ok(BaseUrl {
|
||||
https,
|
||||
host: host.to_string(),
|
||||
port,
|
||||
region,
|
||||
aws_s3_prefix,
|
||||
aws_domain_suffix,
|
||||
dualstack,
|
||||
virtual_style,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl BaseUrl {
|
||||
/// Checks base URL is AWS host
|
||||
pub fn is_aws_host(&self) -> bool {
|
||||
@ -363,96 +465,4 @@ impl BaseUrl {
|
||||
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
/// Returns a base URL from given host string
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use minio::s3::http::BaseUrl;
|
||||
/// // Get base URL from host name
|
||||
/// let base_url = BaseUrl::from_string("play.min.io".to_string()).unwrap();
|
||||
/// // Get base URL from host:port
|
||||
/// let base_url = BaseUrl::from_string("play.minio.io:9000".to_string()).unwrap();
|
||||
/// // Get base URL from IPv4 address
|
||||
/// let base_url = BaseUrl::from_string("http://192.168.124.63:9000".to_string()).unwrap();
|
||||
/// // Get base URL from IPv6 address
|
||||
/// let base_url = BaseUrl::from_string("[0:0:0:0:0:ffff:c0a8:7c3f]:9000".to_string()).unwrap();
|
||||
/// ```
|
||||
pub fn from_string(s: String) -> Result<BaseUrl, Error> {
|
||||
let url = s.parse::<Uri>()?;
|
||||
|
||||
let https = match url.scheme() {
|
||||
None => true,
|
||||
Some(scheme) => match scheme.as_str() {
|
||||
"http" => false,
|
||||
"https" => true,
|
||||
_ => {
|
||||
return Err(Error::InvalidBaseUrl(String::from(
|
||||
"scheme must be http or https",
|
||||
)))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mut host = match url.host() {
|
||||
Some(h) => h,
|
||||
_ => {
|
||||
return Err(Error::InvalidBaseUrl(String::from(
|
||||
"valid host must be provided",
|
||||
)))
|
||||
}
|
||||
};
|
||||
|
||||
let ipv6host = "[".to_string() + host + "]";
|
||||
if host.parse::<std::net::Ipv6Addr>().is_ok() {
|
||||
host = &ipv6host;
|
||||
}
|
||||
|
||||
let mut port = match url.port() {
|
||||
Some(p) => p.as_u16(),
|
||||
_ => 0u16,
|
||||
};
|
||||
|
||||
if (https && port == 443) || (!https && port == 80) {
|
||||
port = 0u16;
|
||||
}
|
||||
|
||||
if url.path() != "/" && url.path() != "" {
|
||||
return Err(Error::InvalidBaseUrl(String::from(
|
||||
"path must be empty for base URL",
|
||||
)));
|
||||
}
|
||||
|
||||
if url.query().is_some() {
|
||||
return Err(Error::InvalidBaseUrl(String::from(
|
||||
"query must be none for base URL",
|
||||
)));
|
||||
}
|
||||
|
||||
let mut region = String::new();
|
||||
let mut aws_s3_prefix = String::new();
|
||||
let mut aws_domain_suffix = String::new();
|
||||
let mut dualstack: bool = false;
|
||||
get_aws_info(
|
||||
&host.to_string(),
|
||||
https,
|
||||
&mut region,
|
||||
&mut aws_s3_prefix,
|
||||
&mut aws_domain_suffix,
|
||||
&mut dualstack,
|
||||
)?;
|
||||
let virtual_style = !aws_domain_suffix.is_empty() || host.ends_with("aliyuncs.com");
|
||||
|
||||
Ok(BaseUrl {
|
||||
https,
|
||||
host: host.to_string(),
|
||||
port,
|
||||
region,
|
||||
aws_s3_prefix,
|
||||
aws_domain_suffix,
|
||||
dualstack,
|
||||
virtual_style,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1155,7 +1155,7 @@ async fn s3_tests() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let ignore_cert_check = std::env::var("IGNORE_CERT_CHECK").is_ok();
|
||||
let region = std::env::var("SERVER_REGION").ok();
|
||||
|
||||
let mut base_url = BaseUrl::from_string(host).unwrap();
|
||||
let mut base_url: BaseUrl = host.parse().unwrap();
|
||||
base_url.https = secure;
|
||||
if let Some(v) = region {
|
||||
base_url.region = v;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user