mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
fix: decode percent-encoded paths in get_file_path() (#1072)
Co-authored-by: houseme <housemecn@gmail.com> Co-authored-by: loverustfs <hello@rustfs.com>
This commit is contained in:
@@ -198,15 +198,22 @@ impl Endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_file_path(&self) -> &str {
|
||||
let path = self.url.path();
|
||||
pub fn get_file_path(&self) -> String {
|
||||
let path: &str = self.url.path();
|
||||
let decoded: std::borrow::Cow<'_, str> = match urlencoding::decode(path) {
|
||||
Ok(decoded) => decoded,
|
||||
Err(e) => {
|
||||
debug!("Failed to decode path '{}': {}, using original path", path, e);
|
||||
std::borrow::Cow::Borrowed(path)
|
||||
}
|
||||
};
|
||||
#[cfg(windows)]
|
||||
if self.url.scheme() == "file" {
|
||||
let stripped = path.strip_prefix('/').unwrap_or(path);
|
||||
let stripped: &str = decoded.strip_prefix('/').unwrap_or(&decoded);
|
||||
debug!("get_file_path windows: path={}", stripped);
|
||||
return stripped;
|
||||
return stripped.to_string();
|
||||
}
|
||||
path
|
||||
decoded.into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,6 +508,45 @@ mod test {
|
||||
assert_eq!(endpoint.get_type(), EndpointType::Path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_endpoint_with_spaces_in_path() {
|
||||
let path_with_spaces = "/Users/test/Library/Application Support/rustfs/data";
|
||||
let endpoint = Endpoint::try_from(path_with_spaces).unwrap();
|
||||
assert_eq!(endpoint.get_file_path(), path_with_spaces);
|
||||
assert!(endpoint.is_local);
|
||||
assert_eq!(endpoint.get_type(), EndpointType::Path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_endpoint_percent_encoding_roundtrip() {
|
||||
let path_with_spaces = "/Users/test/Library/Application Support/rustfs/data";
|
||||
let endpoint = Endpoint::try_from(path_with_spaces).unwrap();
|
||||
|
||||
// Verify that the URL internally stores percent-encoded path
|
||||
assert!(
|
||||
endpoint.url.path().contains("%20"),
|
||||
"URL path should contain percent-encoded spaces: {}",
|
||||
endpoint.url.path()
|
||||
);
|
||||
|
||||
// Verify that get_file_path() decodes the percent-encoded path correctly
|
||||
assert_eq!(
|
||||
endpoint.get_file_path(),
|
||||
"/Users/test/Library/Application Support/rustfs/data",
|
||||
"get_file_path() should decode percent-encoded spaces"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_endpoint_with_various_special_characters() {
|
||||
// Test path with multiple special characters that get percent-encoded
|
||||
let path_with_special = "/tmp/test path/data[1]/file+name&more";
|
||||
let endpoint = Endpoint::try_from(path_with_special).unwrap();
|
||||
|
||||
// get_file_path() should return the original path with decoded characters
|
||||
assert_eq!(endpoint.get_file_path(), path_with_special);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_endpoint_update_is_local() {
|
||||
let mut endpoint = Endpoint::try_from("http://localhost:9000/path").unwrap();
|
||||
|
||||
@@ -232,7 +232,7 @@ impl PoolEndpointList {
|
||||
|
||||
for endpoints in pool_endpoint_list.inner.iter_mut() {
|
||||
// Check whether same path is not used in endpoints of a host on different port.
|
||||
let mut path_ip_map: HashMap<&str, HashSet<IpAddr>> = HashMap::new();
|
||||
let mut path_ip_map: HashMap<String, HashSet<IpAddr>> = HashMap::new();
|
||||
let mut host_ip_cache = HashMap::new();
|
||||
for ep in endpoints.as_ref() {
|
||||
if !ep.url.has_host() {
|
||||
@@ -275,8 +275,9 @@ impl PoolEndpointList {
|
||||
match path_ip_map.entry(path) {
|
||||
Entry::Occupied(mut e) => {
|
||||
if e.get().intersection(host_ip_set).count() > 0 {
|
||||
let path_key = e.key().clone();
|
||||
return Err(Error::other(format!(
|
||||
"same path '{path}' can not be served by different port on same address"
|
||||
"same path '{path_key}' can not be served by different port on same address"
|
||||
)));
|
||||
}
|
||||
e.get_mut().extend(host_ip_set.iter());
|
||||
@@ -295,7 +296,7 @@ impl PoolEndpointList {
|
||||
}
|
||||
|
||||
let path = ep.get_file_path();
|
||||
if local_path_set.contains(path) {
|
||||
if local_path_set.contains(&path) {
|
||||
return Err(Error::other(format!(
|
||||
"path '{path}' cannot be served by different address on same server"
|
||||
)));
|
||||
|
||||
Reference in New Issue
Block a user