This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new b76664117 fix(oli): oli commands should not accept invalid URI format
(#2845)
b76664117 is described below
commit b7666411796a9699ffa2f6a8ff4cb2c7ac2f1b95
Author: Kousuke Saruta <[email protected]>
AuthorDate: Thu Aug 10 22:28:39 2023 +0900
fix(oli): oli commands should not accept invalid URI format (#2845)
Disallow invalid uri format.
---
bin/oli/src/config/mod.rs | 62 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 54 insertions(+), 8 deletions(-)
diff --git a/bin/oli/src/config/mod.rs b/bin/oli/src/config/mod.rs
index adb39665a..40dae693d 100644
--- a/bin/oli/src/config/mod.rs
+++ b/bin/oli/src/config/mod.rs
@@ -31,6 +31,7 @@ use opendal::Operator;
use opendal::Scheme;
use serde::Deserialize;
use toml;
+use url::Url;
#[derive(Deserialize, Default)]
pub struct Config {
@@ -125,7 +126,7 @@ impl Config {
/// Parse `<profile>://abc/def` into `op` and `location`.
pub fn parse_location(&self, s: &str) -> Result<(Operator, String)> {
- if !s.contains("://") {
+ if !s.contains(":/") {
let mut fs_builder = services::Fs::default();
let fp = resolve_relative_path(Path::new(s));
let fp_str = fp.as_os_str().to_string_lossy();
@@ -144,12 +145,13 @@ impl Config {
return Ok((Operator::new(fs_builder)?.finish(), filename.into()));
}
- let parts = s.splitn(2, "://").collect::<Vec<_>>();
- debug_assert!(parts.len() == 2);
-
- let profile_name = parts[0];
- let path = parts[1].into();
+ let location = Url::parse(s)?;
+ if location.has_host() {
+ Err(anyhow!("Host part in a location is not supported."))?;
+ }
+ let profile_name = location.scheme();
+ let path = location.path().to_string();
let profile = self
.profiles
.get(profile_name)
@@ -400,10 +402,54 @@ enable_virtual_host_style = "on"
]),
)]),
};
- let (op, path) = cfg.parse_location("mys3://foo/1.txt").unwrap();
- assert_eq!("foo/1.txt", path);
+ let (op, path) = cfg.parse_location("mys3:///foo/1.txt").unwrap();
+ assert_eq!("/foo/1.txt", path);
+ let info = op.info();
+ assert_eq!(Scheme::S3, info.scheme());
+ assert_eq!("mybucket", info.name());
+ }
+
+ #[test]
+ fn test_parse_s3_location2() {
+ let cfg = Config {
+ profiles: HashMap::from([(
+ "mys3".into(),
+ HashMap::from([
+ ("type".into(), "s3".into()),
+ ("bucket".into(), "mybucket".into()),
+ ("region".into(), "us-east-1".into()),
+ ]),
+ )]),
+ };
+ let (op, path) = cfg.parse_location("mys3:/foo/1.txt").unwrap();
+ assert_eq!("/foo/1.txt", path);
let info = op.info();
assert_eq!(Scheme::S3, info.scheme());
assert_eq!("mybucket", info.name());
}
+
+ #[test]
+ fn test_parse_s3_location3() -> Result<()> {
+ let cfg = Config {
+ profiles: HashMap::from([(
+ "mys3".into(),
+ HashMap::from([
+ ("type".into(), "s3".into()),
+ ("bucket".into(), "mybucket".into()),
+ ("region".into(), "us-east-1".into()),
+ ]),
+ )]),
+ };
+
+ let uri = "mys3://foo/1.txt";
+ let expected_msg = "Host part in a location is not supported.";
+ match cfg.parse_location(uri) {
+ Err(e) if e.to_string() == expected_msg => Ok(()),
+ _ => Err(anyhow!(
+ "Getting an message \"{}\" is expected when parsing {}.",
+ expected_msg,
+ uri
+ ))?,
+ }
+ }
}