diff --git a/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java b/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java index 0b3315a9..3421df0d 100644 --- a/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java +++ b/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java @@ -7,6 +7,7 @@ import java.net.URI; import java.net.URL; import java.net.URLDecoder; +import java.net.URLEncoder; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.WatchEvent; @@ -735,11 +736,20 @@ public int hashCode() */ private String encode(String uri) { - // remove special case URI starting with // - uri = uri.replace("//", "/"); - uri = uri.replaceAll(" ", "%20"); - - return uri; + try + { + // URL encode all characters, but then convert known allowed characters back + return URLEncoder.encode(uri, "UTF-8") + .replace("%3A", ":") + .replace("%2F", "/") + .replace("+", "%20"); + } + catch (UnsupportedEncodingException e) + { + // This should never happen unless there is something + // fundamentally broken with the running JVM. + throw new RuntimeException(e); + } } /** diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/path/ToUriTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/path/ToUriTest.java index 713b624d..53921f97 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/path/ToUriTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/path/ToUriTest.java @@ -58,6 +58,26 @@ void toUri() assertEquals(path, pathActual); } + @Test + public void toUriSpecialChars() + { + Path path = getPath("/bucket/([fol! @#$%der])"); + URI uri = path.toUri(); + + // the scheme is s3 + assertEquals("s3", uri.getScheme()); + + // could get the correct fileSystem + S3FileSystem fs = s3fsProvider.getFileSystem(uri); + // the host is the endpoint specified in fileSystem + assertEquals(fs.getEndpoint(), uri.getHost()); + + // bucket name as first path + Path pathActual = fs.provider().getPath(uri); + + assertEquals(path, pathActual); + } + @Test void toUriWithEndSlash() {