Skip to content

Commit

Permalink
Fixed URI encoding with special characters
Browse files Browse the repository at this point in the history
Fixes issue Upplication#105 by running the uri through URLEncoder.encode and then
converting allowable characters :, / and [space] back.
  • Loading branch information
amarcionek committed Nov 27, 2018
1 parent 1e2554e commit b3c275f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 23 deletions.
35 changes: 24 additions & 11 deletions src/main/java/com/upplication/s3fs/S3Path.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
package com.upplication.s3fs;

import com.google.common.base.*;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.upplication.s3fs.attribute.S3BasicFileAttributes;
import static com.google.common.collect.Iterables.concat;
import static java.lang.String.format;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.file.*;
import java.net.URLEncoder;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Iterator;
import java.util.List;

import static com.google.common.collect.Iterables.*;
import static java.lang.String.format;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.upplication.s3fs.attribute.S3BasicFileAttributes;

public class S3Path implements Path {

Expand Down Expand Up @@ -583,10 +589,17 @@ public int hashCode() {
* @return String
*/
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);
}
}

/**
Expand Down
43 changes: 31 additions & 12 deletions src/test/java/com/upplication/s3fs/Path/ToUriTest.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
package com.upplication.s3fs.Path;

import com.google.common.collect.ImmutableMap;
import com.upplication.s3fs.S3FileSystem;
import com.upplication.s3fs.S3FileSystemProvider;
import com.upplication.s3fs.S3Path;
import com.upplication.s3fs.S3UnitTestBase;
import com.upplication.s3fs.util.S3EndpointConstant;
import org.junit.Before;
import org.junit.Test;
import static com.upplication.s3fs.AmazonS3Factory.ACCESS_KEY;
import static com.upplication.s3fs.AmazonS3Factory.SECRET_KEY;
import static com.upplication.s3fs.util.S3EndpointConstant.S3_GLOBAL_URI_TEST;
import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.util.Map;

import static com.upplication.s3fs.AmazonS3Factory.ACCESS_KEY;
import static com.upplication.s3fs.AmazonS3Factory.SECRET_KEY;
import static com.upplication.s3fs.util.S3EndpointConstant.*;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import com.google.common.collect.ImmutableMap;
import com.upplication.s3fs.S3FileSystem;
import com.upplication.s3fs.S3FileSystemProvider;
import com.upplication.s3fs.S3Path;
import com.upplication.s3fs.S3UnitTestBase;
import com.upplication.s3fs.util.S3EndpointConstant;

public class ToUriTest extends S3UnitTestBase {

Expand Down Expand Up @@ -50,6 +50,25 @@ public 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
public void toUriWithEndSlash() {
S3Path s3Path = getPath("/bucket/folder/");
Expand Down

0 comments on commit b3c275f

Please sign in to comment.